diff options
-rw-r--r-- | include/clang/AST/Decl.h | 2 | ||||
-rw-r--r-- | include/clang/AST/DeclCXX.h | 34 | ||||
-rw-r--r-- | include/clang/Basic/IdentifierTable.h | 22 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 8 | ||||
-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 |
10 files changed, 131 insertions, 47 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index d7e25357c5..3a766bfd5e 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -67,7 +67,7 @@ public: : 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; diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 26ccb62bdc..39c22aaf70 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -246,12 +246,8 @@ class CXXRecordDecl : public RecordDecl, public DeclContext { /// 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 @@ public: 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 @@ class CXXDestructorDecl : public CXXMethodDecl { /// @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 @@ public: 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 @@ class CXXConversionDecl : public CXXMethodDecl { /// 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 @@ public: 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. diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 4a16a3e42b..f6b95ba380 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -178,6 +178,16 @@ class IdentifierTable { /// 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 @@ public: 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; diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 1e036e7559..4aa900f628 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -154,14 +154,6 @@ public: 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". 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, |