[cfe-commits] r59193 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/DeclCXX.h include/clang/Basic/IdentifierTable.h include/clang/Parse/Action.h lib/AST/DeclCXX.cpp lib/Basic/IdentifierTable.cpp lib/Parse/ParseDecl.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp

Douglas Gregor doug.gregor at gmail.com
Wed Nov 12 15:21:10 PST 2008


Author: dgregor
Date: Wed Nov 12 17:21:09 2008
New Revision: 59193

URL: http://llvm.org/viewvc/llvm-project?rev=59193&view=rev
Log:
Don't build identifiers for C++ constructors, destructors, or
conversion functions. Instead, we just use a placeholder identifier
for these (e.g., "<constructor>") and override NamedDecl::getName() to
provide a human-readable name.

This is one potential solution to the problem; another solution would
be to replace the use of IdentifierInfo* in NamedDecl with a different
class that deals with identifiers better. I'm also prototyping that to
see how it compares, but this commit is better than what we had
previously.


Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/Basic/IdentifierTable.h
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Basic/IdentifierTable.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=59193&r1=59192&r2=59193&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Wed Nov 12 17:21:09 2008
@@ -67,7 +67,7 @@
    : Decl(DK, L), Identifier(Id) {}
   
   IdentifierInfo *getIdentifier() const { return Identifier; }
-  const char *getName() const;
+  virtual const char *getName() const;
     
   static bool classof(const Decl *D) {
     return D->getKind() >= NamedFirst && D->getKind() <= NamedLast;

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=59193&r1=59192&r2=59193&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Wed Nov 12 17:21:09 2008
@@ -246,12 +246,8 @@
   /// CXXConversionDecl.
   OverloadedFunctionDecl Conversions;
 
-  CXXRecordDecl(TagKind TK, DeclContext *DC,
-                SourceLocation L, IdentifierInfo *Id) 
-    : RecordDecl(CXXRecord, TK, DC, L, Id), DeclContext(CXXRecord),
-      UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
-      Aggregate(true), Polymorphic(false), Bases(0), NumBases(0),
-      Constructors(DC, Id), Destructor(0), Conversions(DC, Id) { }
+  CXXRecordDecl(ASTContext &C, TagKind TK, DeclContext *DC,
+                SourceLocation L, IdentifierInfo *Id);
 
   ~CXXRecordDecl();
 
@@ -592,6 +588,9 @@
                                     QualType T, bool isExplicit,
                                     bool isInline, bool isImplicitlyDeclared);
 
+  /// getName - Returns a human-readable name for this constructor.
+  virtual const char *getName() const;
+
   /// isExplicit - Whether this constructor was marked "explicit" or not.  
   bool isExplicit() const { return Explicit; }
 
@@ -687,13 +686,17 @@
   /// @c !ImplicitlyDeclared && ImplicitlyDefined.
   bool ImplicitlyDefined : 1;
 
+  /// Name - The formatted name of this destructor. This will be
+  /// generated when getName() is called.
+  mutable char *Name;
+
   CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
                     IdentifierInfo *Id, QualType T,
                     bool isInline, bool isImplicitlyDeclared)
     : CXXMethodDecl(CXXDestructor, RD, L, Id, T, false, isInline, 
                     /*PrevDecl=*/0),
       ImplicitlyDeclared(isImplicitlyDeclared),
-      ImplicitlyDefined(false) { }
+      ImplicitlyDefined(false), Name(0) { }
 
 public:
   static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
@@ -701,6 +704,11 @@
                                    QualType T, bool isInline, 
                                    bool isImplicitlyDeclared);
 
+  virtual ~CXXDestructorDecl();
+
+  /// getName - Returns a human-readable name for this destructor.
+  virtual const char *getName() const;
+
   /// isImplicitlyDeclared - Whether this destructor was implicitly
   /// declared. If false, then this destructor was explicitly
   /// declared by the user.
@@ -754,12 +762,16 @@
   /// explicitly wrote a cast. This is a C++0x feature.
   bool Explicit : 1;
 
+  /// Name - The formatted name of this conversion function. This will
+  /// be generated when getName() is called.
+  mutable char *Name;
+
   CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L,
                     IdentifierInfo *Id, QualType T, 
                     bool isInline, bool isExplicit)
     : CXXMethodDecl(CXXConversion, RD, L, Id, T, false, isInline, 
                     /*PrevDecl=*/0),
-      Explicit(isExplicit) { }
+      Explicit(isExplicit), Name(0) { }
 
 public:
   static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
@@ -767,6 +779,12 @@
                                    QualType T, bool isInline, 
                                    bool isExplicit);
 
+  virtual ~CXXConversionDecl();
+
+  /// getName - Returns a human-readable name for this conversion
+  /// function.
+  virtual const char *getName() const;
+
   /// isExplicit - Whether this is an explicit conversion operator
   /// (C++0x only). Explicit conversion operators are only considered
   /// when the user has explicitly written a cast.

Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/IdentifierTable.h?rev=59193&r1=59192&r2=59193&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/IdentifierTable.h (original)
+++ cfe/trunk/include/clang/Basic/IdentifierTable.h Wed Nov 12 17:21:09 2008
@@ -178,6 +178,16 @@
   /// overloadable operators in C++.
   IdentifierInfo *OverloadedOperators[NUM_OVERLOADED_OPERATORS];
 
+  /// ConstructorId - Placeholder identifier for C++ constructors.
+  IdentifierInfo *ConstructorId;
+
+  /// DestructorId - Placeholder identifier for C++ destructor.
+  IdentifierInfo *DestructorId;
+
+  /// ConversionFunctionId - Placeholder identifier for a C++
+  /// conversion function.
+  IdentifierInfo *ConversionFunctionId;
+
 public:
   /// IdentifierTable ctor - Create the identifier table, populating it with
   /// info about the language keywords for the language specified by LangOpts.
@@ -203,6 +213,18 @@
     return *OverloadedOperators[Op];
   }
 
+  /// getConstructorId - Return a placeholder identifier for a C++
+  /// constructor.
+  IdentifierInfo &getConstructorId();
+
+  /// getDestructorId - Return a placeholder identifier for a C++
+  /// destructor.
+  IdentifierInfo &getDestructorId();
+
+  /// getConversionFunctionId - Return a placeholder identifier for a
+  /// C++ conversion function.
+  IdentifierInfo &getConversionFunctionId();
+
   typedef HashTableTy::const_iterator iterator;
   typedef HashTableTy::const_iterator const_iterator;
   

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=59193&r1=59192&r2=59193&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Nov 12 17:21:09 2008
@@ -154,14 +154,6 @@
   virtual void ActOnCXXExitDeclaratorScope(const CXXScopeSpec &SS) {
   }
 
-  /// getTypeAsString - Returns a string that describes the given
-  /// type. This callback is used in C++ to form identifiers for
-  /// special declarations that otherwise don't have simple names,
-  /// such as constructors, destructors, and conversion functions.
-  virtual std::string getTypeAsString(TypeTy *Type) {
-    return "<unknown type>";
-  }
-
   /// ActOnDeclarator - This callback is invoked when a declarator is parsed and
   /// 'Init' specifies the initializer if any.  This is for things like:
   /// "int X = 4" or "typedef int foo".

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=59193&r1=59192&r2=59193&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Wed Nov 12 17:21:09 2008
@@ -13,6 +13,7 @@
 
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/Basic/IdentifierTable.h"
 using namespace clang;
 
 //===----------------------------------------------------------------------===//
@@ -26,11 +27,20 @@
   return new (Mem) CXXFieldDecl(RD, L, Id, T, BW);
 }
 
+CXXRecordDecl::CXXRecordDecl(ASTContext &C, TagKind TK, DeclContext *DC,
+                             SourceLocation L, IdentifierInfo *Id) 
+  : RecordDecl(CXXRecord, TK, DC, L, Id), DeclContext(CXXRecord),
+    UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
+    Aggregate(true), Polymorphic(false), Bases(0), NumBases(0),
+    Constructors(DC, &C.Idents.getConstructorId()), 
+    Destructor(0), 
+    Conversions(DC, &C.Idents.getConversionFunctionId()) { }
+
 CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
                                      SourceLocation L, IdentifierInfo *Id,
                                      CXXRecordDecl* PrevDecl) {
   void *Mem = C.getAllocator().Allocate<CXXRecordDecl>();
-  CXXRecordDecl* R = new (Mem) CXXRecordDecl(TK, DC, L, Id);
+  CXXRecordDecl* R = new (Mem) CXXRecordDecl(C, TK, DC, L, Id);
   C.getTypeDeclType(R, PrevDecl);  
   return R;
 }
@@ -232,6 +242,10 @@
          (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
 }
 
+const char *CXXConstructorDecl::getName() const { 
+  return getParent()->getName();
+}
+
 CXXDestructorDecl *
 CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
                           SourceLocation L, IdentifierInfo *Id,
@@ -242,6 +256,34 @@
                                      isImplicitlyDeclared);
 }
 
+CXXDestructorDecl::~CXXDestructorDecl() {
+  delete [] Name;
+}
+
+const char *CXXDestructorDecl::getName() const {
+  if (!Name) {
+    std::string Builder = "~";
+    Builder += getParent()->getName();
+    Name = new char[Builder.size()+1];
+    strcpy(Name, Builder.c_str());
+  }
+  return Name;
+}
+
+CXXConversionDecl::~CXXConversionDecl() {
+  delete [] Name;
+}
+
+const char *CXXConversionDecl::getName() const {
+  if (!Name) {
+    std::string Builder = "operator ";
+    Builder += getConversionType().getAsString();
+    Name = new char[Builder.size()+1];
+    strcpy(Name, Builder.c_str());    
+  }
+  return Name;
+}
+
 CXXConversionDecl *
 CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
                           SourceLocation L, IdentifierInfo *Id,

Modified: cfe/trunk/lib/Basic/IdentifierTable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/IdentifierTable.cpp?rev=59193&r1=59192&r2=59193&view=diff

==============================================================================
--- cfe/trunk/lib/Basic/IdentifierTable.cpp (original)
+++ cfe/trunk/lib/Basic/IdentifierTable.cpp Wed Nov 12 17:21:09 2008
@@ -42,7 +42,8 @@
 
 IdentifierTable::IdentifierTable(const LangOptions &LangOpts)
   // Start with space for 8K identifiers.
-  : HashTable(8192) {
+  : HashTable(8192), 
+    ConstructorId(0), DestructorId(0), ConversionFunctionId(0) {
 
   // Populate the identifier table with info about keywords for the current
   // language.
@@ -51,7 +52,33 @@
 }
 
 // This cstor is intended to be used only for serialization.
-IdentifierTable::IdentifierTable() : HashTable(8192) {}
+IdentifierTable::IdentifierTable() 
+  : HashTable(8192), 
+    ConstructorId(0), DestructorId(0), ConversionFunctionId(0) { }
+
+/// getConstructorId - Return a placeholder identifier for a C++
+/// constructor.
+IdentifierInfo &IdentifierTable::getConstructorId() {
+  if (!ConstructorId)
+    ConstructorId = &get("<constructor>");
+  return *ConstructorId;
+}
+
+/// getDestructorId - Return a placeholder identifier for a C++
+/// destructor.
+IdentifierInfo &IdentifierTable::getDestructorId() {
+  if (!DestructorId)
+    DestructorId = &get("<destructor>");
+  return *DestructorId;
+}
+
+/// getConversionFunctionId - Return a placeholder identifier for a
+/// C++ conversion function.
+IdentifierInfo &IdentifierTable::getConversionFunctionId() {
+  if (!ConversionFunctionId)
+    ConversionFunctionId = &get("<conversion function>");
+  return *ConversionFunctionId;
+}
 
 //===----------------------------------------------------------------------===//
 // Language Keyword Implementation

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=59193&r1=59192&r2=59193&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Nov 12 17:21:09 2008
@@ -1437,7 +1437,8 @@
     if (getLang().CPlusPlus && 
         Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope))
       D.SetConstructor(Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope),
-                       Tok.getIdentifierInfo(), Tok.getLocation());
+                       &PP.getIdentifierTable().getConstructorId(), 
+                       Tok.getLocation());
     else
       D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
     ConsumeToken();
@@ -1446,18 +1447,9 @@
     // This should be a C++ destructor.
     SourceLocation TildeLoc = ConsumeToken();
     if (Tok.is(tok::identifier)) {
-      // Use the next identifier and "~" to form a name for the
-      // destructor. This is useful both for diagnostics and for
-      // correctness of the parser, since we use presence/absence of the
-      // identifier to determine what we parsed.
-      // FIXME: We could end up with a template-id here, once we parse
-      // templates, and will have to do something different to form the
-      // name of the destructor.
-      IdentifierInfo *II = Tok.getIdentifierInfo();
-      II = &PP.getIdentifierTable().get(std::string("~") + II->getName());
-
       if (TypeTy *Type = ParseClassName())
-        D.SetDestructor(Type, II, TildeLoc);
+        D.SetDestructor(Type, &PP.getIdentifierTable().getDestructorId(), 
+                        TildeLoc);
       else
         D.SetIdentifier(0, TildeLoc);
     } else {
@@ -1473,10 +1465,9 @@
     } else {
       // This must be a conversion function (C++ [class.conv.fct]).
       if (TypeTy *ConvType = ParseConversionFunctionId()) {
-        IdentifierInfo *II 
-          = &PP.getIdentifierTable().get(std::string("operator ") + 
-                                         Actions.getTypeAsString(ConvType));
-        D.SetConversionFunction(ConvType, II, OperatorLoc);
+        D.SetConversionFunction(ConvType, 
+                                &PP.getIdentifierTable().getConversionFunctionId(), 
+                                OperatorLoc);
       }
     }
   } else if (Tok.is(tok::l_paren) && SS.isEmpty()) {

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=59193&r1=59192&r2=59193&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Nov 12 17:21:09 2008
@@ -284,7 +284,6 @@
   //
   virtual TypeTy *isTypeName(const IdentifierInfo &II, Scope *S,
                              const CXXScopeSpec *SS);
-  virtual std::string getTypeAsString(TypeTy *Type);
   virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup);
   virtual DeclTy *ActOnParamDeclarator(Scope *S, Declarator &D);
   virtual void ActOnParamDefaultArgument(DeclTy *param, 

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=59193&r1=59192&r2=59193&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Nov 12 17:21:09 2008
@@ -45,11 +45,6 @@
   return 0;
 }
 
-std::string Sema::getTypeAsString(TypeTy *Type) {
-  QualType Ty = QualType::getFromOpaquePtr(Type);
-  return Ty.getAsString();
-}
-
 DeclContext *Sema::getContainingDC(DeclContext *DC) {
   if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
     // A C++ out-of-line method will return to the file declaration context.

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=59193&r1=59192&r2=59193&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Nov 12 17:21:09 2008
@@ -705,7 +705,7 @@
     CXXConstructorDecl *DefaultCon = 
       CXXConstructorDecl::Create(Context, ClassDecl,
                                  ClassDecl->getLocation(),
-                                 ClassDecl->getIdentifier(),
+                                 &Context.Idents.getConstructorId(),
                                  Context.getFunctionType(Context.VoidTy,
                                                          0, 0, false, 0),
                                  /*isExplicit=*/false,
@@ -771,7 +771,7 @@
     CXXConstructorDecl *CopyConstructor
       = CXXConstructorDecl::Create(Context, ClassDecl,
                                    ClassDecl->getLocation(),
-                                   ClassDecl->getIdentifier(),
+                                   &Context.Idents.getConstructorId(),
                                    Context.getFunctionType(Context.VoidTy,
                                                            &ArgType, 1,
                                                            false, 0),
@@ -795,12 +795,10 @@
     //   If a class has no user-declared destructor, a destructor is
     //   declared implicitly. An implicitly-declared destructor is an
     //   inline public member of its class.
-    std::string DestructorName = "~";
-    DestructorName += ClassDecl->getName();
     CXXDestructorDecl *Destructor 
       = CXXDestructorDecl::Create(Context, ClassDecl,
                                   ClassDecl->getLocation(),
-                                  &PP.getIdentifierTable().get(DestructorName),
+                                  &Context.Idents.getConstructorId(),
                                   Context.getFunctionType(Context.VoidTy,
                                                           0, 0, false, 0),
                                   /*isInline=*/true,





More information about the cfe-commits mailing list