@@ -3015,12 +3015,24 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
30153015 }
30163016
30173017 bool ParseSymbolName = true ;
3018+
3019+ ExposureKind ExpKind;
30183020 if (DK == DAK_Expose) {
3019- if (Tok. isNot (tok::identifier) || Tok. getText () != " Cxx " ) {
3021+ auto diagnoseExpectOption = [&]( ) {
30203022 diagnose (Tok.getLoc (), diag::attr_expected_option_such_as, AttrName,
30213023 " Cxx" );
3022- if (Tok.isNot (tok::identifier))
3023- return makeParserSuccess ();
3024+ ParseSymbolName = false ;
3025+ };
3026+ if (Tok.isNot (tok::identifier)) {
3027+ diagnoseExpectOption ();
3028+ return makeParserSuccess ();
3029+ }
3030+ if (Tok.getText () == " Cxx" ) {
3031+ ExpKind = ExposureKind::Cxx;
3032+ } else if (Tok.getText () == " wasm" ) {
3033+ ExpKind = ExposureKind::Wasm;
3034+ } else {
3035+ diagnoseExpectOption ();
30243036 DiscardAttribute = true ;
30253037 }
30263038 consumeToken (tok::identifier);
@@ -3076,10 +3088,19 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
30763088 else if (DK == DAK_CDecl)
30773089 Attributes.add (new (Context) CDeclAttr (AsmName.value (), AtLoc,
30783090 AttrRange, /* Implicit=*/ false ));
3079- else if (DK == DAK_Expose)
3091+ else if (DK == DAK_Expose) {
3092+ for (auto *EA : Attributes.getAttributes <ExposeAttr>()) {
3093+ // A single declaration cannot have two @_exported attributes with
3094+ // the same exposure kind.
3095+ if (EA->getExposureKind () == ExpKind) {
3096+ diagnose (Loc, diag::duplicate_attribute, false );
3097+ break ;
3098+ }
3099+ }
30803100 Attributes.add (new (Context) ExposeAttr (
30813101 AsmName ? AsmName.value () : StringRef (" " ), AtLoc, AttrRange,
3082- /* Implicit=*/ false ));
3102+ ExpKind, /* Implicit=*/ false ));
3103+ }
30833104 else
30843105 llvm_unreachable (" out of sync with switch" );
30853106 }
0 commit comments