diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-11-12 23:21:09 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-11-12 23:21:09 +0000 |
commit | 7d7e6727a5de032c86dcb58ae734e7c1603c26e6 (patch) | |
tree | 0c542ae5d737114b92f73e8291c51903e8c0b74b /lib | |
parent | b7c3ca8af0a1a3b66fb220562c72dd3102153d5b (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59193 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclCXX.cpp | 44 | ||||
-rw-r--r-- | lib/Basic/IdentifierTable.cpp | 31 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 23 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 8 |
6 files changed, 82 insertions, 30 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index d008544074..1de640743d 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -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 @@ CXXFieldDecl *CXXFieldDecl::Create(ASTContext &C, CXXRecordDecl *RD, 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 @@ bool CXXConstructorDecl::isConvertingConstructor() const { (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 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, 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, diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index 2b9d7e3845..b8684753b2 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -42,7 +42,8 @@ IdentifierInfo::IdentifierInfo() { 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 @@ IdentifierTable::IdentifierTable(const LangOptions &LangOpts) } // 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 diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 70d65f3b48..0c1080a5b8 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1437,7 +1437,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) { 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 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // 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 @@ void Parser::ParseDirectDeclarator(Declarator &D) { } 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()) { diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 6a86a8ab78..efe481abae 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -284,7 +284,6 @@ public: // 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, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index bf29bdf2ce..8c3a5c12c6 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -45,11 +45,6 @@ Sema::TypeTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S, 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. diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 128df11385..9bf10cece8 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -705,7 +705,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { 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 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { 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 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { // 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, |