FYI I've fixed a memory leak in the new test in r372925.

On Wed, Sep 25, 2019 at 10:58 AM Vedant Kumar via cfe-commits
<cfe-commits@lists.llvm.org> wrote:
>
> Author: vedantk
> Date: Wed Sep 25 11:00:31 2019
> New Revision: 372903
>
> URL: http://llvm.org/viewvc/llvm-project?rev=372903&view=rev
> Log:
> [Mangle] Add flag to asm labels to disable '\01' prefixing
>
> LLDB synthesizes decls using asm labels. These decls cannot have a mangle
> different than the one specified in the label name. I.e., the '\01' prefix
> should not be added.
>
> Fixes an expression evaluation failure in lldb's TestVirtual.py on iOS.
>
> rdar://45827323
>
> Differential Revision: https://reviews.llvm.org/D67774
>
> Modified:
>     cfe/trunk/include/clang/Basic/Attr.td
>     cfe/trunk/include/clang/Basic/AttrDocs.td
>     cfe/trunk/lib/AST/Mangle.cpp
>     cfe/trunk/lib/Sema/SemaDecl.cpp
>     cfe/trunk/unittests/AST/DeclTest.cpp
>
> Modified: cfe/trunk/include/clang/Basic/Attr.td
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=372903&r1=372902&r2=372903&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/Attr.td (original)
> +++ cfe/trunk/include/clang/Basic/Attr.td Wed Sep 25 11:00:31 2019
> @@ -722,9 +722,25 @@ def AVRSignal : InheritableAttr, TargetS
>
>  def AsmLabel : InheritableAttr {
>    let Spellings = [Keyword<"asm">, Keyword<"__asm__">];
> -  let Args = [StringArgument<"Label">];
> +  let Args = [
> +    // Label specifies the mangled name for the decl.
> +    StringArgument<"Label">,
> +
> +    // IsLiteralLabel specifies whether the label is literal (i.e. suppresses
> +    // the global C symbol prefix) or not. If not, the mangle-suppression 
> prefix
> +    // ('\01') is omitted from the decl name at the LLVM IR level.
> +    //
> +    // Non-literal labels are used by some external AST sources like LLDB.
> +    BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
> +  ];
>    let SemaHandler = 0;
> -  let Documentation = [Undocumented];
> +  let Documentation = [AsmLabelDocs];
> +  let AdditionalMembers =
> +[{
> +bool isEquivalent(AsmLabelAttr *Other) const {
> +  return getLabel() == Other->getLabel() && getIsLiteralLabel() == 
> Other->getIsLiteralLabel();
> +}
> +}];
>  }
>
>  def Availability : InheritableAttr {
>
> Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=372903&r1=372902&r2=372903&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
> +++ cfe/trunk/include/clang/Basic/AttrDocs.td Wed Sep 25 11:00:31 2019
> @@ -2558,6 +2558,30 @@ manipulating bits of the enumerator when
>    }];
>  }
>
> +def AsmLabelDocs : Documentation {
> +  let Category = DocCatDecl;
> +  let Content = [{
> +This attribute can be used on a function or variable to specify its symbol 
> name.
> +
> +On some targets, all C symbols are prefixed by default with a single 
> character, typically ``_``.  This was done historically to distinguish them 
> from symbols used by other languages.  (This prefix is also added to the 
> standard Itanium C++ ABI prefix on "mangled" symbol names, so that e.g. on 
> such targets the true symbol name for a C++ variable declared as ``int 
> cppvar;`` would be ``__Z6cppvar``; note the two underscores.)  This prefix is 
> *not* added to the symbol names specified by the ``asm`` attribute; 
> programmers wishing to match a C symbol name must compensate for this.
> +
> +For example, consider the following C code:
> +
> +.. code-block:: c
> +
> +  int var1 asm("altvar") = 1;  // "altvar" in symbol table.
> +  int var2 = 1; // "_var2" in symbol table.
> +
> +  void func1(void) asm("altfunc");
> +  void func1(void) {} // "altfunc" in symbol table.
> +  void func2(void) {} // "_func2" in symbol table.
> +
> +Clang's implementation of this attribute is compatible with GCC's, 
> `documented here <https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html>`_.
> +
> +While it is possible to use this attribute to name a special symbol used 
> internally by the compiler, such as an LLVM intrinsic, this is neither 
> recommended nor supported and may cause the compiler to crash or miscompile.  
> Users who wish to gain access to intrinsic behavior are strongly encouraged 
> to request new builtin functions.
> +  }];
> +}
> +
>  def EnumExtensibilityDocs : Documentation {
>    let Category = DocCatDecl;
>    let Content = [{
>
> Modified: cfe/trunk/lib/AST/Mangle.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Mangle.cpp?rev=372903&r1=372902&r2=372903&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/Mangle.cpp (original)
> +++ cfe/trunk/lib/AST/Mangle.cpp Wed Sep 25 11:00:31 2019
> @@ -122,15 +122,21 @@ void MangleContext::mangleName(const Nam
>    if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
>      // If we have an asm name, then we use it as the mangling.
>
> +    // If the label isn't literal, or if this is an alias for an LLVM 
> intrinsic,
> +    // do not add a "\01" prefix.
> +    if (!ALA->getIsLiteralLabel() || ALA->getLabel().startswith("llvm.")) {
> +      Out << ALA->getLabel();
> +      return;
> +    }
> +
>      // Adding the prefix can cause problems when one file has a "foo" and
>      // another has a "\01foo". That is known to happen on ELF with the
>      // 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.
> +    // marker.
>      char GlobalPrefix =
>          getASTContext().getTargetInfo().getDataLayout().getGlobalPrefix();
> -    if (GlobalPrefix && !ALA->getLabel().startswith("llvm."))
> +    if (GlobalPrefix)
>        Out << '\01'; // LLVM IR Marker for __asm("foo")
>
>      Out << ALA->getLabel();
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=372903&r1=372902&r2=372903&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Sep 25 11:00:31 2019
> @@ -2766,7 +2766,7 @@ void Sema::mergeDeclAttributes(NamedDecl
>
>    if (AsmLabelAttr *NewA = New->getAttr<AsmLabelAttr>()) {
>      if (AsmLabelAttr *OldA = Old->getAttr<AsmLabelAttr>()) {
> -      if (OldA->getLabel() != NewA->getLabel()) {
> +      if (!OldA->isEquivalent(NewA)) {
>          // This redeclaration changes __asm__ label.
>          Diag(New->getLocation(), diag::err_different_asm_label);
>          Diag(OldA->getLocation(), diag::note_previous_declaration);
> @@ -6983,8 +6983,8 @@ NamedDecl *Sema::ActOnVariableDeclarator
>        }
>      }
>
> -    NewVD->addAttr(::new (Context)
> -                       AsmLabelAttr(Context, SE->getStrTokenLoc(0), Label));
> +    NewVD->addAttr(::new (Context) AsmLabelAttr(
> +        Context, SE->getStrTokenLoc(0), Label, /*IsLiteralLabel=*/true));
>    } else if (!ExtnameUndeclaredIdentifiers.empty()) {
>      llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
>        ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
> @@ -8882,8 +8882,9 @@ Sema::ActOnFunctionDeclarator(Scope *S,
>    if (Expr *E = (Expr*) D.getAsmLabel()) {
>      // The parser guarantees this is a string.
>      StringLiteral *SE = cast<StringLiteral>(E);
> -    NewFD->addAttr(::new (Context) AsmLabelAttr(Context, 
> SE->getStrTokenLoc(0),
> -                                                SE->getString()));
> +    NewFD->addAttr(::new (Context)
> +                       AsmLabelAttr(Context, SE->getStrTokenLoc(0),
> +                                    SE->getString(), 
> /*IsLiteralLabel=*/true));
>    } else if (!ExtnameUndeclaredIdentifiers.empty()) {
>      llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
>        ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
> @@ -17555,8 +17556,8 @@ void Sema::ActOnPragmaRedefineExtname(Id
>                                           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=*/true, Info);
>
>    // If a declaration that:
>    // 1) declares a function or a variable
>
> Modified: cfe/trunk/unittests/AST/DeclTest.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/DeclTest.cpp?rev=372903&r1=372902&r2=372903&view=diff
> ==============================================================================
> --- cfe/trunk/unittests/AST/DeclTest.cpp (original)
> +++ cfe/trunk/unittests/AST/DeclTest.cpp Wed Sep 25 11:00:31 2019
> @@ -10,12 +10,16 @@
>  //
>  
> //===----------------------------------------------------------------------===//
>
> +#include "clang/AST/ASTContext.h"
> +#include "clang/AST/Mangle.h"
>  #include "clang/ASTMatchers/ASTMatchFinder.h"
> +#include "clang/Basic/LLVM.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,48 @@ TEST(Decl, CleansUpAPValues) {
>        "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();
> +  assert(Ctx.getTargetInfo().getDataLayout().getGlobalPrefix() &&
> +         "Expected target to have a global prefix");
> +  DiagnosticsEngine &Diags = AST->getDiagnostics();
> +  SourceManager &SM = AST->getSourceManager();
> +  FileID MainFileID = SM.getMainFileID();
> +
> +  // Find the method decls within the AST.
> +  SmallVector<Decl *, 1> Decls;
> +  AST->findFileRegionDecls(MainFileID, Code.find('{'), 0, Decls);
> +  ASSERT_TRUE(Decls.size() == 1);
> +  CXXRecordDecl *DeclS = cast<CXXRecordDecl>(Decls[0]);
> +  NamedDecl *DeclF = *DeclS->method_begin();
> +  NamedDecl *DeclG = *(++DeclS->method_begin());
> +
> +  // Attach asm labels to the decls: one literal, and one not.
> +  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_F(MangleF);
> +    llvm::raw_string_ostream OS_G(MangleG);
> +    MC->mangleName(DeclF, OS_F);
> +    MC->mangleName(DeclG, OS_G);
> +  }
> +
> +  ASSERT_TRUE(0 == MangleF.compare("\x01" "foo"));
> +  ASSERT_TRUE(0 == MangleG.compare("goo"));
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits@lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to