diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index f8a34573f3c8..03b38bf2158d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6329,9 +6329,21 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, if (isGlobalVar(D) && SanitizerName != "address") S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) << AL << ExpectedFunction; - D->addAttr(::new (S.Context) - NoSanitizeAttr(AL.getRange(), S.Context, &SanitizerName, 1, - AL.getAttributeSpellingListIndex())); + + // 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 + // has the same spellings as the index for NoSanitizeAttr. We don't have a + // general way to "translate" between the two, so this hack attempts to work + // around the issue with hard-coded indicies. This is critical for calling + // getSpelling() or prettyPrint() on the resulting semantic attribute object + // without failing assertions. + unsigned TranslatedSpellingIndex = 0; + if (AL.isC2xAttribute() || AL.isCXX11Attribute()) + TranslatedSpellingIndex = 1; + + D->addAttr(::new (S.Context) NoSanitizeAttr( + AL.getRange(), S.Context, &SanitizerName, 1, TranslatedSpellingIndex)); } static void handleInternalLinkageAttr(Sema &S, Decl *D, const ParsedAttr &AL) { diff --git a/clang/test/AST/ast-print-no-sanitize.cpp b/clang/test/AST/ast-print-no-sanitize.cpp new file mode 100644 index 000000000000..4ff97190955a --- /dev/null +++ b/clang/test/AST/ast-print-no-sanitize.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -std=c++11 -ast-print %s -o - | FileCheck %s + +void should_not_crash_1() __attribute__((no_sanitize_memory)); +[[clang::no_sanitize_memory]] void should_not_crash_2(); + +// CHECK: void should_not_crash_1() __attribute__((no_sanitize("memory"))); +// CHECK: void should_not_crash_2() {{\[\[}}clang::no_sanitize("memory"){{\]\]}};