diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 6521fc3e9a9da..c7859a69dd8de 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -582,6 +582,7 @@ Moved checkers Sanitizers ---------- +- Improved documentation for legacy ``no_sanitize`` attributes. Python Binding Changes ---------------------- diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 2623f9ff6972f..de56bb38fd63e 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3921,16 +3921,31 @@ def NoSanitize : InheritableAttr { }]; } -// Attributes to disable a specific sanitizer. No new sanitizers should be added +// Attribute to disable AddressSanitizer. No new spellings should be added // to this list; the no_sanitize attribute should be extended instead. -def NoSanitizeSpecific : InheritableAttr { +def NoSanitizeAddress : InheritableAttr { let Spellings = [GCC<"no_address_safety_analysis">, - GCC<"no_sanitize_address">, - GCC<"no_sanitize_thread">, - Clang<"no_sanitize_memory">]; + GCC<"no_sanitize_address">]; let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag>; - let Documentation = [NoSanitizeAddressDocs, NoSanitizeThreadDocs, - NoSanitizeMemoryDocs]; + let Documentation = [NoSanitizeAddressDocs]; + let ASTNode = 0; +} + +// Attribute to disable ThreadSanitizer. No new spellings should be added +// to this list; the no_sanitize attribute should be extended instead. +def NoSanitizeThread : InheritableAttr { + let Spellings = [GCC<"no_sanitize_thread">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [NoSanitizeThreadDocs]; + let ASTNode = 0; +} + +// Attribute to disable MemorySanitizer. No new spellings should be added +// to this list; the no_sanitize attribute should be extended instead. +def NoSanitizeMemory : InheritableAttr { + let Spellings = [Clang<"no_sanitize_memory">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [NoSanitizeMemoryDocs]; let ASTNode = 0; } diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index ee212a9b50f36..20a52b49a8f10 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -13,16 +13,16 @@ // version control. // // To run clang-tblgen to generate the .rst file: -// clang-tblgen -gen-attr-docs -I /llvm/tools/clang/include -// /llvm/tools/clang/include/clang/Basic/Attr.td -o -// /llvm/tools/clang/docs/AttributeReference.rst +// clang-tblgen -gen-attr-docs -I /clang/include +// /clang/include/clang/Basic/Attr.td -o +// /clang/docs/AttributeReference.rst // // To run sphinx to generate the .html files (note that sphinx-build must be // available on the PATH): // Windows (from within the clang\docs directory): // make.bat html -// Non-Windows (from within the clang\docs directory): -// sphinx-build -b html _build/html +// Non-Windows (from within the clang/docs directory): +// sphinx-build -b html . _build/html def GlobalDocumentation { code Intro =[{.. @@ -3629,6 +3629,7 @@ instrumentations should not be applied. The attribute takes a list of string literals with the following accepted values: + * all values accepted by ``-fno-sanitize=``; * ``coverage``, to disable SanitizerCoverage instrumentation. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index a8dfa4d7df2d5..328ccf6694073 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6361,19 +6361,8 @@ static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { Sanitizers.size())); } -static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - StringRef AttrName = AL.getAttrName()->getName(); - normalizeName(AttrName); - StringRef SanitizerName = llvm::StringSwitch(AttrName) - .Case("no_address_safety_analysis", "address") - .Case("no_sanitize_address", "address") - .Case("no_sanitize_thread", "thread") - .Case("no_sanitize_memory", "memory"); - if (isGlobalVar(D) && SanitizerName != "address") - S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << AL << AL.isRegularKeywordAttribute() << ExpectedFunction; - +static AttributeCommonInfo +getNoSanitizeAttrInfo(const ParsedAttr &NoSanitizeSpecificAttr) { // FIXME: Rather than create a NoSanitizeSpecificAttr, this creates a // NoSanitizeAttr object; but we need to calculate the correct spelling list // index rather than incorrectly assume the index for NoSanitizeSpecificAttr @@ -6383,11 +6372,32 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, // getSpelling() or prettyPrint() on the resulting semantic attribute object // without failing assertions. unsigned TranslatedSpellingIndex = 0; - if (AL.isStandardAttributeSyntax()) + if (NoSanitizeSpecificAttr.isStandardAttributeSyntax()) TranslatedSpellingIndex = 1; - AttributeCommonInfo Info = AL; + AttributeCommonInfo Info = NoSanitizeSpecificAttr; Info.setAttributeSpellingListIndex(TranslatedSpellingIndex); + return Info; +} + +static void handleNoSanitizeAddressAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + StringRef SanitizerName = "address"; + AttributeCommonInfo Info = getNoSanitizeAttrInfo(AL); + D->addAttr(::new (S.Context) + NoSanitizeAttr(S.Context, Info, &SanitizerName, 1)); +} + +static void handleNoSanitizeThreadAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + StringRef SanitizerName = "thread"; + AttributeCommonInfo Info = getNoSanitizeAttrInfo(AL); + D->addAttr(::new (S.Context) + NoSanitizeAttr(S.Context, Info, &SanitizerName, 1)); +} + +static void handleNoSanitizeMemoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + StringRef SanitizerName = "memory"; + AttributeCommonInfo Info = getNoSanitizeAttrInfo(AL); D->addAttr(::new (S.Context) NoSanitizeAttr(S.Context, Info, &SanitizerName, 1)); } @@ -7513,8 +7523,14 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_NoSanitize: handleNoSanitizeAttr(S, D, AL); break; - case ParsedAttr::AT_NoSanitizeSpecific: - handleNoSanitizeSpecificAttr(S, D, AL); + case ParsedAttr::AT_NoSanitizeAddress: + handleNoSanitizeAddressAttr(S, D, AL); + break; + case ParsedAttr::AT_NoSanitizeThread: + handleNoSanitizeThreadAttr(S, D, AL); + break; + case ParsedAttr::AT_NoSanitizeMemory: + handleNoSanitizeMemoryAttr(S, D, AL); break; case ParsedAttr::AT_GuardedBy: handleGuardedByAttr(S, D, AL); diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 37ff33e5a1523..73d4cb1769ed5 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -126,7 +126,9 @@ // CHECK-NEXT: NoProfileFunction (SubjectMatchRule_function) // CHECK-NEXT: NoRandomizeLayout (SubjectMatchRule_record) // CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global) -// CHECK-NEXT: NoSanitizeSpecific (SubjectMatchRule_function, SubjectMatchRule_variable_is_global) +// CHECK-NEXT: NoSanitizeAddress (SubjectMatchRule_function, SubjectMatchRule_variable_is_global) +// CHECK-NEXT: NoSanitizeMemory (SubjectMatchRule_function) +// CHECK-NEXT: NoSanitizeThread (SubjectMatchRule_function) // CHECK-NEXT: NoSpeculativeLoadHardening (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: NoSplitStack (SubjectMatchRule_function) // CHECK-NEXT: NoStackProtector (SubjectMatchRule_function)