diff options
Diffstat (limited to 'lib/AST/Decl.cpp')
-rw-r--r-- | lib/AST/Decl.cpp | 509 |
1 files changed, 365 insertions, 144 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 3d02150b65bff..429729ea3b0e2 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -16,11 +16,14 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/TypeLoc.h" #include "clang/AST/Stmt.h" #include "clang/AST/Expr.h" #include "clang/AST/PrettyPrinter.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Parse/DeclSpec.h" +#include "llvm/Support/ErrorHandling.h" #include <vector> using namespace clang; @@ -34,11 +37,15 @@ void Attr::Destroy(ASTContext &C) { C.Deallocate((void*)this); } +/// \brief Return the TypeLoc wrapper for the type source info. +TypeLoc DeclaratorInfo::getTypeLoc() const { + return TypeLoc(Ty, (void*)(this + 1)); +} //===----------------------------------------------------------------------===// // Decl Allocation/Deallocation Method Implementations //===----------------------------------------------------------------------===// - + TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { return new (C) TranslationUnitDecl(C); @@ -52,7 +59,7 @@ NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, void NamespaceDecl::Destroy(ASTContext& C) { // NamespaceDecl uses "NextDeclarator" to chain namespace declarations // together. They are all top-level Decls. - + this->~NamespaceDecl(); C.Deallocate((void *)this); } @@ -68,9 +75,9 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { case VarDecl::None: break; case VarDecl::Auto: return "auto"; break; case VarDecl::Extern: return "extern"; break; - case VarDecl::PrivateExtern: return "__private_extern__"; break; + case VarDecl::PrivateExtern: return "__private_extern__"; break; case VarDecl::Register: return "register"; break; - case VarDecl::Static: return "static"; break; + case VarDecl::Static: return "static"; break; } assert(0 && "Invalid storage class"); @@ -79,34 +86,45 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, StorageClass S, - Expr *DefArg) { - return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, S, DefArg); + QualType T, DeclaratorInfo *DInfo, + StorageClass S, Expr *DefArg) { + return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, DInfo, S, DefArg); } QualType ParmVarDecl::getOriginalType() const { - if (const OriginalParmVarDecl *PVD = + if (const OriginalParmVarDecl *PVD = dyn_cast<OriginalParmVarDecl>(this)) return PVD->OriginalType; return getType(); } -void VarDecl::setInit(ASTContext &C, Expr *I) { - if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) { - Eval->~EvaluatedStmt(); - C.Deallocate(Eval); - } +SourceRange ParmVarDecl::getDefaultArgRange() const { + if (const Expr *E = getInit()) + return E->getSourceRange(); + + if (const Expr *E = getUninstantiatedDefaultArg()) + return E->getSourceRange(); + + return SourceRange(); +} - Init = I; +void VarDecl::setInit(ASTContext &C, Expr *I) { + if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) { + Eval->~EvaluatedStmt(); + C.Deallocate(Eval); } -bool VarDecl::isExternC(ASTContext &Context) const { + Init = I; +} + +bool VarDecl::isExternC() const { + ASTContext &Context = getASTContext(); if (!Context.getLangOptions().CPlusPlus) - return (getDeclContext()->isTranslationUnit() && + return (getDeclContext()->isTranslationUnit() && getStorageClass() != Static) || (getDeclContext()->isFunctionOrMethod() && hasExternalStorage()); - for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); + for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); DC = DC->getParent()) { if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) @@ -125,20 +143,19 @@ bool VarDecl::isExternC(ASTContext &Context) const { OriginalParmVarDecl *OriginalParmVarDecl::Create( ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, QualType OT, StorageClass S, - Expr *DefArg) { - return new (C) OriginalParmVarDecl(DC, L, Id, T, OT, S, DefArg); + QualType T, DeclaratorInfo *DInfo, + QualType OT, StorageClass S, Expr *DefArg) { + return new (C) OriginalParmVarDecl(DC, L, Id, T, DInfo, OT, S, DefArg); } FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - DeclarationName N, QualType T, - StorageClass S, bool isInline, - bool hasWrittenPrototype, - SourceLocation TypeSpecStartLoc) { - FunctionDecl *New - = new (C) FunctionDecl(Function, DC, L, N, T, S, isInline, - TypeSpecStartLoc); + SourceLocation L, + DeclarationName N, QualType T, + DeclaratorInfo *DInfo, + StorageClass S, bool isInline, + bool hasWrittenPrototype) { + FunctionDecl *New + = new (C) FunctionDecl(Function, DC, L, N, T, DInfo, S, isInline); New->HasWrittenPrototype = hasWrittenPrototype; return New; } @@ -148,16 +165,16 @@ BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { } FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, Expr *BW, - bool Mutable) { - return new (C) FieldDecl(Decl::Field, DC, L, Id, T, BW, Mutable); + IdentifierInfo *Id, QualType T, + DeclaratorInfo *DInfo, Expr *BW, bool Mutable) { + return new (C) FieldDecl(Decl::Field, DC, L, Id, T, DInfo, BW, Mutable); } bool FieldDecl::isAnonymousStructOrUnion() const { if (!isImplicit() || getDeclName()) return false; - - if (const RecordType *Record = getType()->getAsRecordType()) + + if (const RecordType *Record = getType()->getAs<RecordType>()) return Record->getDecl()->isAnonymousStructOrUnion(); return false; @@ -182,9 +199,9 @@ TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, } EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, + IdentifierInfo *Id, SourceLocation TKL, EnumDecl *PrevDecl) { - EnumDecl *Enum = new (C) EnumDecl(DC, L, Id); + EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, PrevDecl, TKL); C.getTypeDeclType(Enum, PrevDecl); return Enum; } @@ -210,6 +227,10 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, //===----------------------------------------------------------------------===// std::string NamedDecl::getQualifiedNameAsString() const { + return getQualifiedNameAsString(getASTContext().getLangOptions()); +} + +std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { std::vector<std::string> Names; std::string QualName; const DeclContext *Ctx = getDeclContext(); @@ -223,15 +244,14 @@ std::string NamedDecl::getQualifiedNameAsString() const { // scope class/struct/union. How do we handle this case? break; - if (const ClassTemplateSpecializationDecl *Spec + if (const ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) { const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - PrintingPolicy Policy(getASTContext().getLangOptions()); std::string TemplateArgsStr = TemplateSpecializationType::PrintTemplateArgumentList( TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size(), - Policy); + P); Names.push_back(Spec->getIdentifier()->getName() + TemplateArgsStr); } else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx)) Names.push_back(ND->getNameAsString()); @@ -253,7 +273,6 @@ std::string NamedDecl::getQualifiedNameAsString() const { return QualName; } - bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch"); @@ -263,7 +282,7 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() == cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace(); } - + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) // For function declarations, we keep track of redeclarations. return FD->getPreviousDeclaration() == OldD; @@ -275,11 +294,14 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { = dyn_cast<FunctionTemplateDecl>(OldD)) return FunctionTemplate->getTemplatedDecl() ->declarationReplaces(OldFunctionTemplate->getTemplatedDecl()); - + // For method declarations, we keep track of redeclarations. if (isa<ObjCMethodDecl>(this)) return false; - + + if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(OldD)) + return true; + // For non-function declarations, if the declarations are of the // same kind then this must be a redeclaration, or semantic analysis // would not have given us the new declaration. @@ -310,13 +332,23 @@ NamedDecl *NamedDecl::getUnderlyingDecl() { } //===----------------------------------------------------------------------===// +// DeclaratorDecl Implementation +//===----------------------------------------------------------------------===// + +SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const { + if (DeclInfo) + return DeclInfo->getTypeLoc().getTypeSpecRange().getBegin(); + return SourceLocation(); +} + +//===----------------------------------------------------------------------===// // VarDecl Implementation //===----------------------------------------------------------------------===// VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, StorageClass S, - SourceLocation TypeSpecStartLoc) { - return new (C) VarDecl(Var, DC, L, Id, T, S, TypeSpecStartLoc); + IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo, + StorageClass S) { + return new (C) VarDecl(Var, DC, L, Id, T, DInfo, S); } void VarDecl::Destroy(ASTContext& C) { @@ -341,6 +373,31 @@ SourceRange VarDecl::getSourceRange() const { return SourceRange(getLocation(), getLocation()); } +VarDecl *VarDecl::getInstantiatedFromStaticDataMember() { + if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) + return cast<VarDecl>(MSI->getInstantiatedFrom()); + + return 0; +} + +TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() { + if (MemberSpecializationInfo *MSI + = getASTContext().getInstantiatedFromStaticDataMember(this)) + return MSI->getTemplateSpecializationKind(); + + return TSK_Undeclared; +} + +MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() { + return getASTContext().getInstantiatedFromStaticDataMember(this); +} + +void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) { + MemberSpecializationInfo *MSI = getMemberSpecializationInfo(); + assert(MSI && "Not an instantiated static data member?"); + MSI->setTemplateSpecializationKind(TSK); +} + bool VarDecl::isTentativeDefinition(ASTContext &Context) const { if (!isFileVarDecl() || Context.getLangOptions().CPlusPlus) return false; @@ -351,11 +408,19 @@ bool VarDecl::isTentativeDefinition(ASTContext &Context) const { } const Expr *VarDecl::getDefinition(const VarDecl *&Def) const { - Def = this; - while (Def && !Def->getInit()) - Def = Def->getPreviousDeclaration(); + redecl_iterator I = redecls_begin(), E = redecls_end(); + while (I != E && !I->getInit()) + ++I; - return Def? Def->getInit() : 0; + if (I != E) { + Def = *I; + return I->getInit(); + } + return 0; +} + +VarDecl *VarDecl::getCanonicalDecl() { + return getFirstDeclaration(); } //===----------------------------------------------------------------------===// @@ -369,27 +434,39 @@ void FunctionDecl::Destroy(ASTContext& C) { for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) (*I)->Destroy(C); + FunctionTemplateSpecializationInfo *FTSInfo + = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); + if (FTSInfo) + C.Deallocate(FTSInfo); + + MemberSpecializationInfo *MSInfo + = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>(); + if (MSInfo) + C.Deallocate(MSInfo); + C.Deallocate(ParamInfo); Decl::Destroy(C); } - -Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { - for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) { - if (FD->Body) { - Definition = FD; - return FD->Body.get(getASTContext().getExternalSource()); - } - } - - return 0; +void FunctionDecl::getNameForDiagnostic(std::string &S, + const PrintingPolicy &Policy, + bool Qualified) const { + NamedDecl::getNameForDiagnostic(S, Policy, Qualified); + const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs(); + if (TemplateArgs) + S += TemplateSpecializationType::PrintTemplateArgumentList( + TemplateArgs->getFlatArgumentList(), + TemplateArgs->flat_size(), + Policy); + } -Stmt *FunctionDecl::getBodyIfAvailable() const { - for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) { - if (FD->Body && !FD->Body.isOffset()) { - return FD->Body.get(0); +Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { + for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { + if (I->Body) { + Definition = *I; + return I->Body.get(getASTContext().getExternalSource()); } } @@ -403,21 +480,24 @@ void FunctionDecl::setBody(Stmt *B) { } bool FunctionDecl::isMain() const { - return getDeclContext()->getLookupContext()->isTranslationUnit() && + ASTContext &Context = getASTContext(); + return !Context.getLangOptions().Freestanding && + getDeclContext()->getLookupContext()->isTranslationUnit() && getIdentifier() && getIdentifier()->isStr("main"); } -bool FunctionDecl::isExternC(ASTContext &Context) const { +bool FunctionDecl::isExternC() const { + ASTContext &Context = getASTContext(); // In C, any non-static, non-overloadable function has external // linkage. if (!Context.getLangOptions().CPlusPlus) return getStorageClass() != Static && !getAttr<OverloadableAttr>(); - for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); + for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); DC = DC->getParent()) { if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) - return getStorageClass() != Static && + return getStorageClass() != Static && !getAttr<OverloadableAttr>(); break; @@ -434,7 +514,7 @@ bool FunctionDecl::isGlobal() const { if (getStorageClass() == Static) return false; - for (const DeclContext *DC = getDeclContext(); + for (const DeclContext *DC = getDeclContext(); DC->isNamespace(); DC = DC->getParent()) { if (const NamespaceDecl *Namespace = cast<NamespaceDecl>(DC)) { @@ -454,9 +534,10 @@ bool FunctionDecl::isGlobal() const { /// declared at translation scope or within an extern "C" block and /// its name matches with the name of a builtin. The returned value /// will be 0 for functions that do not correspond to a builtin, a -/// value of type \c Builtin::ID if in the target-independent range +/// value of type \c Builtin::ID if in the target-independent range /// \c [1,Builtin::First), or a target-specific builtin value. -unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const { +unsigned FunctionDecl::getBuiltinID() const { + ASTContext &Context = getASTContext(); if (!getIdentifier() || !getIdentifier()->getBuiltinID()) return 0; @@ -481,7 +562,7 @@ unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const { // If the function is in an extern "C" linkage specification and is // not marked "overloadable", it's the real function. if (isa<LinkageSpecDecl>(getDeclContext()) && - cast<LinkageSpecDecl>(getDeclContext())->getLanguage() + cast<LinkageSpecDecl>(getDeclContext())->getLanguage() == LinkageSpecDecl::lang_c && !getAttr<OverloadableAttr>()) return BuiltinID; @@ -495,18 +576,18 @@ unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const { /// based on its FunctionType. This is the length of the PararmInfo array /// after it has been created. unsigned FunctionDecl::getNumParams() const { - const FunctionType *FT = getType()->getAsFunctionType(); + const FunctionType *FT = getType()->getAs<FunctionType>(); if (isa<FunctionNoProtoType>(FT)) return 0; return cast<FunctionProtoType>(FT)->getNumArgs(); - + } void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo, unsigned NumParams) { assert(ParamInfo == 0 && "Already has param info!"); assert(NumParams == getNumParams() && "Parameter count mismatch!"); - + // Zero params -> null pointer. if (NumParams) { void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams); @@ -533,42 +614,87 @@ unsigned FunctionDecl::getMinRequiredArguments() const { return NumRequiredArgs; } -bool FunctionDecl::hasActiveGNUInlineAttribute(ASTContext &Context) const { - if (!isInline() || !hasAttr<GNUInlineAttr>()) +/// \brief For an inline function definition in C, determine whether the +/// definition will be externally visible. +/// +/// Inline function definitions are always available for inlining optimizations. +/// However, depending on the language dialect, declaration specifiers, and +/// attributes, the definition of an inline function may or may not be +/// "externally" visible to other translation units in the program. +/// +/// In C99, inline definitions are not externally visible by default. However, +/// if even one of the globa-scope declarations is marked "extern inline", the +/// inline definition becomes externally visible (C99 6.7.4p6). +/// +/// In GNU89 mode, or if the gnu_inline attribute is attached to the function +/// definition, we use the GNU semantics for inline, which are nearly the +/// opposite of C99 semantics. In particular, "inline" by itself will create +/// an externally visible symbol, but "extern inline" will not create an +/// externally visible symbol. +bool FunctionDecl::isInlineDefinitionExternallyVisible() const { + assert(isThisDeclarationADefinition() && "Must have the function definition"); + assert(isInline() && "Function must be inline"); + + if (!getASTContext().getLangOptions().C99 || hasAttr<GNUInlineAttr>()) { + // GNU inline semantics. Based on a number of examples, we came up with the + // following heuristic: if the "inline" keyword is present on a + // declaration of the function but "extern" is not present on that + // declaration, then the symbol is externally visible. Otherwise, the GNU + // "extern inline" semantics applies and the symbol is not externally + // visible. + for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end(); + Redecl != RedeclEnd; + ++Redecl) { + if (Redecl->isInline() && Redecl->getStorageClass() != Extern) + return true; + } + + // GNU "extern inline" semantics; no externally visible symbol. return false; - - for (const FunctionDecl *FD = getPreviousDeclaration(); FD; - FD = FD->getPreviousDeclaration()) { - if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>()) - return false; } - - return true; -} - -bool FunctionDecl::isExternGNUInline(ASTContext &Context) const { - if (!hasActiveGNUInlineAttribute(Context)) - return false; - - for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDeclaration()) - if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>()) - return true; - + + // C99 6.7.4p6: + // [...] If all of the file scope declarations for a function in a + // translation unit include the inline function specifier without extern, + // then the definition in that translation unit is an inline definition. + for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end(); + Redecl != RedeclEnd; + ++Redecl) { + // Only consider file-scope declarations in this test. + if (!Redecl->getLexicalDeclContext()->isTranslationUnit()) + continue; + + if (!Redecl->isInline() || Redecl->getStorageClass() == Extern) + return true; // Not an inline definition + } + + // C99 6.7.4p6: + // An inline definition does not provide an external definition for the + // function, and does not forbid an external definition in another + // translation unit. return false; } -void +void FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { - PreviousDeclaration = PrevDecl; - + redeclarable_base::setPreviousDeclaration(PrevDecl); + if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) { - FunctionTemplateDecl *PrevFunTmpl + FunctionTemplateDecl *PrevFunTmpl = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0; assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch"); FunTmpl->setPreviousDeclaration(PrevFunTmpl); } } +const FunctionDecl *FunctionDecl::getCanonicalDecl() const { + return getFirstDeclaration(); +} + +FunctionDecl *FunctionDecl::getCanonicalDecl() { + return getFirstDeclaration(); +} + /// getOverloadedOperator - Which C++ overloaded operator this /// function represents, if any. OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { @@ -578,8 +704,29 @@ OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { return OO_None; } +FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const { + if (MemberSpecializationInfo *Info = getMemberSpecializationInfo()) + return cast<FunctionDecl>(Info->getInstantiatedFrom()); + + return 0; +} + +MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const { + return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>(); +} + +void +FunctionDecl::setInstantiationOfMemberFunction(FunctionDecl *FD, + TemplateSpecializationKind TSK) { + assert(TemplateOrSpecialization.isNull() && + "Member function is already a specialization"); + MemberSpecializationInfo *Info + = new (getASTContext()) MemberSpecializationInfo(FD, TSK); + TemplateOrSpecialization = Info; +} + FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { - if (FunctionTemplateSpecializationInfo *Info + if (FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization .dyn_cast<FunctionTemplateSpecializationInfo*>()) { return Info->Template.getPointer(); @@ -589,79 +736,151 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { const TemplateArgumentList * FunctionDecl::getTemplateSpecializationArgs() const { - if (FunctionTemplateSpecializationInfo *Info - = TemplateOrSpecialization - .dyn_cast<FunctionTemplateSpecializationInfo*>()) { + if (FunctionTemplateSpecializationInfo *Info + = TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo*>()) { return Info->TemplateArguments; } return 0; } -void +void FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context, FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, - void *InsertPos) { - FunctionTemplateSpecializationInfo *Info + void *InsertPos, + TemplateSpecializationKind TSK) { + assert(TSK != TSK_Undeclared && + "Must specify the type of function template specialization"); + FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); if (!Info) Info = new (Context) FunctionTemplateSpecializationInfo; - + Info->Function = this; Info->Template.setPointer(Template); - Info->Template.setInt(0); // Implicit instantiation, unless told otherwise + Info->Template.setInt(TSK - 1); Info->TemplateArguments = TemplateArgs; TemplateOrSpecialization = Info; - + // Insert this function template specialization into the set of known - // function template specialiations. - Template->getSpecializations().InsertNode(Info, InsertPos); + // function template specializations. + if (InsertPos) + Template->getSpecializations().InsertNode(Info, InsertPos); + else { + // Try to insert the new node. If there is an existing node, remove it + // first. + FunctionTemplateSpecializationInfo *Existing + = Template->getSpecializations().GetOrInsertNode(Info); + if (Existing) { + Template->getSpecializations().RemoveNode(Existing); + Template->getSpecializations().GetOrInsertNode(Info); + } + } } -bool FunctionDecl::isExplicitSpecialization() const { - // FIXME: check this property for explicit specializations of member - // functions of class templates. - FunctionTemplateSpecializationInfo *Info +TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const { + // For a function template specialization, query the specialization + // information object. + FunctionTemplateSpecializationInfo *FTSInfo = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); - if (!Info) - return false; + if (FTSInfo) + return FTSInfo->getTemplateSpecializationKind(); + + MemberSpecializationInfo *MSInfo + = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>(); + if (MSInfo) + return MSInfo->getTemplateSpecializationKind(); - return Info->isExplicitSpecialization(); + return TSK_Undeclared; +} + +void +FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) { + if (FunctionTemplateSpecializationInfo *FTSInfo + = TemplateOrSpecialization.dyn_cast< + FunctionTemplateSpecializationInfo*>()) + FTSInfo->setTemplateSpecializationKind(TSK); + else if (MemberSpecializationInfo *MSInfo + = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) + MSInfo->setTemplateSpecializationKind(TSK); + else + assert(false && "Function cannot have a template specialization kind"); } -void FunctionDecl::setExplicitSpecialization(bool ES) { - // FIXME: set this property for explicit specializations of member functions - // of class templates. - FunctionTemplateSpecializationInfo *Info - = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); - if (Info) - Info->setExplicitSpecialization(ES); +bool FunctionDecl::isOutOfLine() const { + // FIXME: Should we restrict this to member functions? + if (Decl::isOutOfLine()) + return true; + + // If this function was instantiated from a member function of a + // class template, check whether that member function was defined out-of-line. + if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) { + const FunctionDecl *Definition; + if (FD->getBody(Definition)) + return Definition->isOutOfLine(); + } + + // If this function was instantiated from a function template, + // check whether that function template was defined out-of-line. + if (FunctionTemplateDecl *FunTmpl = getPrimaryTemplate()) { + const FunctionDecl *Definition; + if (FunTmpl->getTemplatedDecl()->getBody(Definition)) + return Definition->isOutOfLine(); + } + + return false; } //===----------------------------------------------------------------------===// // TagDecl Implementation //===----------------------------------------------------------------------===// +SourceRange TagDecl::getSourceRange() const { + SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation(); + return SourceRange(TagKeywordLoc, E); +} + +TagDecl* TagDecl::getCanonicalDecl() { + return getFirstDeclaration(); +} + void TagDecl::startDefinition() { - TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType()); - TagT->decl.setPointer(this); - TagT->getAsTagType()->decl.setInt(1); + if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) { + TagT->decl.setPointer(this); + TagT->decl.setInt(1); + } } void TagDecl::completeDefinition() { - assert((!TypeForDecl || - TypeForDecl->getAsTagType()->decl.getPointer() == this) && - "Attempt to redefine a tag definition?"); IsDefinition = true; - TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType()); - TagT->decl.setPointer(this); - TagT->decl.setInt(0); + if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) { + assert(TagT->decl.getPointer() == this && + "Attempt to redefine a tag definition?"); + TagT->decl.setInt(0); + } } TagDecl* TagDecl::getDefinition(ASTContext& C) const { - QualType T = C.getTypeDeclType(const_cast<TagDecl*>(this)); - TagDecl* D = cast<TagDecl>(T->getAsTagType()->getDecl()); - return D->isDefinition() ? D : 0; + if (isDefinition()) + return const_cast<TagDecl *>(this); + + for (redecl_iterator R = redecls_begin(), REnd = redecls_end(); + R != REnd; ++R) + if (R->isDefinition()) + return *R; + + return 0; +} + +TagDecl::TagKind TagDecl::getTagKindForTypeSpec(unsigned TypeSpec) { + switch (TypeSpec) { + default: llvm::llvm_unreachable("unexpected type specifier"); + case DeclSpec::TST_struct: return TK_struct; + case DeclSpec::TST_class: return TK_class; + case DeclSpec::TST_union: return TK_union; + case DeclSpec::TST_enum: return TK_enum; + } } //===----------------------------------------------------------------------===// @@ -669,18 +888,20 @@ TagDecl* TagDecl::getDefinition(ASTContext& C) const { //===----------------------------------------------------------------------===// RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id) - : TagDecl(DK, TK, DC, L, Id) { + IdentifierInfo *Id, RecordDecl *PrevDecl, + SourceLocation TKL) + : TagDecl(DK, TK, DC, L, Id, PrevDecl, TKL) { HasFlexibleArrayMember = false; AnonymousStructOrUnion = false; + HasObjectMember = false; assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); } RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - RecordDecl* PrevDecl) { - - RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id); + SourceLocation TKL, RecordDecl* PrevDecl) { + + RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id, PrevDecl, TKL); C.getTypeDeclType(R, PrevDecl); return R; } @@ -693,7 +914,7 @@ void RecordDecl::Destroy(ASTContext& C) { } bool RecordDecl::isInjectedClassName() const { - return isImplicit() && getDeclName() && getDeclContext()->isRecord() && + return isImplicit() && getDeclName() && getDeclContext()->isRecord() && cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName(); } @@ -717,15 +938,15 @@ void BlockDecl::Destroy(ASTContext& C) { for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) (*I)->Destroy(C); - - C.Deallocate(ParamInfo); + + C.Deallocate(ParamInfo); Decl::Destroy(C); } void BlockDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo, unsigned NParms) { assert(ParamInfo == 0 && "Already has param info!"); - + // Zero params -> null pointer. if (NParms) { NumParams = NParms; |