diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 62c8c0130c3d0..9a5efe97d0595 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -449,6 +449,8 @@ Improvements to Clang's diagnostics - A new warning ``-Wenum-compare-typo`` has been added to detect potential erroneous comparison operators when mixed with bitwise operators in enum value initializers. This can be locally disabled by explicitly casting the initializer value. +- Clang now emits a diagnostic when an invalid identifier string is passed to + the `gnu::abi_tag` attribute (#GH168901). Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 53aa86a7dabde..ce52066d38957 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3326,6 +3326,8 @@ def err_attribute_no_member_function : Error< def err_attribute_parameter_types : Error< "%0 attribute parameter types do not match: parameter %1 of function %2 has type %3, " "but parameter %4 of function %5 has type %6">; +def err_attribute_string_literal_invalid_ident : Error< + "%0 attribute parameters must be string literals containing valid identifiers">; def err_attribute_too_many_arguments : Error< "%0 attribute takes no more than %1 argument%s1">; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e3af5023c74d0..1d1a2c5b52dab 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6172,12 +6172,29 @@ static void handleMSConstexprAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) MSConstexprAttr(S.Context, AL)); } +static bool checkIsRawIdentifier(const Sema &S, StringRef StrRef) { + std::string Str = StrRef.str(); + auto FileLoc = S.getSourceManager().getLocForStartOfFile( + S.getSourceManager().getMainFileID()); + Lexer Lex(FileLoc, S.getLangOpts(), Str.c_str(), Str.c_str(), + Str.c_str() + Str.size()); + Token Tok; + bool LexedToEnd = Lex.LexFromRawLexer(Tok); + return LexedToEnd && Tok.is(tok::raw_identifier); +} + static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) { SmallVector Tags; for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { StringRef Tag; if (!S.checkStringLiteralArgumentAttr(AL, I, Tag)) return; + if (!checkIsRawIdentifier(S, Tag)) { + S.Diag(AL.getArgAsExpr(I)->getBeginLoc(), + diag::err_attribute_string_literal_invalid_ident) + << AL; + return; + } Tags.push_back(Tag); } diff --git a/clang/test/SemaCXX/attr-abi-tag-syntax.cpp b/clang/test/SemaCXX/attr-abi-tag-syntax.cpp index 4f14a3c043b5c..ea3f5b184aba2 100644 --- a/clang/test/SemaCXX/attr-abi-tag-syntax.cpp +++ b/clang/test/SemaCXX/attr-abi-tag-syntax.cpp @@ -31,3 +31,13 @@ extern int a2; // expected-note@-1 {{previous declaration is here}} __attribute__((abi_tag("A")))extern int a2; // expected-error@-1 {{cannot add 'abi_tag' attribute in a redeclaration}} + +[[gnu::abi_tag("[[something]]")]] // expected-error {{'gnu::abi_tag' attribute parameters must be string literals containing valid identifiers}} +int f1() { + return 0; +} + +[[gnu::abi_tag("something")]] +int f2() { + return 0; +}