Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -722,7 +722,7 @@ def AsmLabel : InheritableAttr { let Spellings = [Keyword<"asm">, Keyword<"__asm__">]; - let Args = [StringArgument<"Label">]; + let Args = [StringArgument<"Label">, BoolArgument<"LiteralLabel">]; let SemaHandler = 0; let Documentation = [Undocumented]; } Index: clang/lib/AST/Mangle.cpp =================================================================== --- clang/lib/AST/Mangle.cpp +++ clang/lib/AST/Mangle.cpp @@ -127,10 +127,11 @@ // tricks normally used for producing aliases (PR9177). Fortunately the // llvm mangler on ELF is a nop, so we can just avoid adding the \01 // marker. We also avoid adding the marker if this is an alias for an - // LLVM intrinsic. + // LLVM intrinsic, or if label has a literal label. char GlobalPrefix = getASTContext().getTargetInfo().getDataLayout().getGlobalPrefix(); - if (GlobalPrefix && !ALA->getLabel().startswith("llvm.")) + if (GlobalPrefix && !ALA->getLabel().startswith("llvm.") && + !ALA->getLiteralLabel()) Out << '\01'; // LLVM IR Marker for __asm("foo") Out << ALA->getLabel(); Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -2766,6 +2766,8 @@ if (AsmLabelAttr *NewA = New->getAttr()) { if (AsmLabelAttr *OldA = Old->getAttr()) { + assert(OldA->getLiteralLabel() == NewA->getLiteralLabel() && + "Redeclaration of asm label changes label kind"); if (OldA->getLabel() != NewA->getLabel()) { // This redeclaration changes __asm__ label. Diag(New->getLocation(), diag::err_different_asm_label); @@ -6983,8 +6985,8 @@ } } - NewVD->addAttr(::new (Context) - AsmLabelAttr(Context, SE->getStrTokenLoc(0), Label)); + NewVD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getStrTokenLoc(0), + Label, /*LiteralLabel=*/false)); } else if (!ExtnameUndeclaredIdentifiers.empty()) { llvm::DenseMap::iterator I = ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier()); @@ -8882,8 +8884,9 @@ if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast(E); - NewFD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getStrTokenLoc(0), - SE->getString())); + NewFD->addAttr(::new (Context) + AsmLabelAttr(Context, SE->getStrTokenLoc(0), + SE->getString(), /*LiteralLabel=*/false)); } else if (!ExtnameUndeclaredIdentifiers.empty()) { llvm::DenseMap::iterator I = ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier()); @@ -17555,8 +17558,8 @@ LookupOrdinaryName); AttributeCommonInfo Info(AliasName, SourceRange(AliasNameLoc), AttributeCommonInfo::AS_Pragma); - AsmLabelAttr *Attr = - AsmLabelAttr::CreateImplicit(Context, AliasName->getName(), Info); + AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit( + Context, AliasName->getName(), /*LiteralLabel=*/false, Info); // If a declaration that: // 1) declares a function or a variable Index: clang/unittests/AST/DeclTest.cpp =================================================================== --- clang/unittests/AST/DeclTest.cpp +++ clang/unittests/AST/DeclTest.cpp @@ -10,12 +10,16 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/ASTContext.h" +#include "clang/AST/Mangle.h" +#include "clang/Basic/LLVM.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Tooling/Tooling.h" #include "gtest/gtest.h" using namespace clang::ast_matchers; using namespace clang::tooling; +using namespace clang; TEST(Decl, CleansUpAPValues) { MatchFinder Finder; @@ -56,3 +60,49 @@ "constexpr _Complex __uint128_t c = 0xffffffffffffffff;", Args)); } + +TEST(Decl, AsmLabelAttr) { + // Create two method decls: `f` and `g`. + StringRef Code = R"( + struct S { + void f() {} + void g() {} + }; + )"; + auto AST = + tooling::buildASTFromCodeWithArgs(Code, {"-target", "i386-apple-darwin"}); + ASTContext &Ctx = AST->getASTContext(); + DiagnosticsEngine &Diags = AST->getDiagnostics(); + SourceManager &SM = AST->getSourceManager(); + FileID MainFileID = SM.getMainFileID(); + + // Find the method decls within the AST. + SmallVector Decls; + AST->findFileRegionDecls(MainFileID, Code.find('{'), 0, Decls); + ASSERT_TRUE(Decls.size() == 1); + CXXRecordDecl *DeclS = cast(Decls[0]); + NamedDecl *DeclF = *DeclS->method_begin(); + NamedDecl *DeclG = *(++DeclS->method_begin()); + + // Attach asm labels to the decls: one literal, and one subject to global + // prefixing. + DeclF->addAttr(::new (Ctx) AsmLabelAttr(Ctx, SourceLocation(), "foo", + /*LiteralLabel=*/true)); + DeclG->addAttr(::new (Ctx) AsmLabelAttr(Ctx, SourceLocation(), "goo", + /*LiteralLabel=*/false)); + + // Mangle the decl names. + std::string MangleF, MangleG; + MangleContext *MC = ItaniumMangleContext::create(Ctx, Diags); + { + llvm::raw_string_ostream OS(MangleF); + MC->mangleName(DeclF, OS); + } + { + llvm::raw_string_ostream OS(MangleG); + MC->mangleName(DeclG, OS); + } + + ASSERT_TRUE(0 == MangleF.compare("foo")); + ASSERT_TRUE(0 == MangleG.compare("\x01goo")); +} Index: lldb/source/Symbol/ClangASTContext.cpp =================================================================== --- lldb/source/Symbol/ClangASTContext.cpp +++ lldb/source/Symbol/ClangASTContext.cpp @@ -8300,8 +8300,8 @@ cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(*getASTContext())); if (mangled_name != nullptr) { - cxx_method_decl->addAttr( - clang::AsmLabelAttr::CreateImplicit(*getASTContext(), mangled_name)); + cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit( + *getASTContext(), mangled_name, /*literal=*/true)); } // Populate the method decl with parameter decls