diff options
author | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
commit | 056abd2059c65a3e908193aeae16fad98017437c (patch) | |
tree | 2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /lib/AST/ASTContext.cpp | |
parent | cc73504950eb7b5dff2dded9bedd67bc36d64641 (diff) | |
download | FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.zip FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.tar.gz |
Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2):
http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r-- | lib/AST/ASTContext.cpp | 325 |
1 files changed, 296 insertions, 29 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index c021323..74c68ae 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -24,6 +24,7 @@ #include "clang/AST/ASTMutationListener.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/Mangle.h" +#include "clang/AST/Comment.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -72,6 +73,22 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { return NULL; } + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (VD->isStaticDataMember() && + VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) + return NULL; + } + + if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) { + if (CRD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) + return NULL; + } + + if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) { + if (ED->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) + return NULL; + } + // TODO: handle comments for function parameters properly. if (isa<ParmVarDecl>(D)) return NULL; @@ -196,15 +213,72 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { namespace { /// If we have a 'templated' declaration for a template, adjust 'D' to /// refer to the actual template. +/// If we have an implicit instantiation, adjust 'D' to refer to template. const Decl *adjustDeclToTemplate(const Decl *D) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + // Is this function declaration part of a function template? if (const FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate()) - D = FTD; - } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { - if (const ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) - D = CTD; + return FTD; + + // Nothing to do if function is not an implicit instantiation. + if (FD->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) + return D; + + // Function is an implicit instantiation of a function template? + if (const FunctionTemplateDecl *FTD = FD->getPrimaryTemplate()) + return FTD; + + // Function is instantiated from a member definition of a class template? + if (const FunctionDecl *MemberDecl = + FD->getInstantiatedFromMemberFunction()) + return MemberDecl; + + return D; } - // FIXME: Alias templates? + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + // Static data member is instantiated from a member definition of a class + // template? + if (VD->isStaticDataMember()) + if (const VarDecl *MemberDecl = VD->getInstantiatedFromStaticDataMember()) + return MemberDecl; + + return D; + } + if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) { + // Is this class declaration part of a class template? + if (const ClassTemplateDecl *CTD = CRD->getDescribedClassTemplate()) + return CTD; + + // Class is an implicit instantiation of a class template or partial + // specialization? + if (const ClassTemplateSpecializationDecl *CTSD = + dyn_cast<ClassTemplateSpecializationDecl>(CRD)) { + if (CTSD->getSpecializationKind() != TSK_ImplicitInstantiation) + return D; + llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *> + PU = CTSD->getSpecializedTemplateOrPartial(); + return PU.is<ClassTemplateDecl*>() ? + static_cast<const Decl*>(PU.get<ClassTemplateDecl *>()) : + static_cast<const Decl*>( + PU.get<ClassTemplatePartialSpecializationDecl *>()); + } + + // Class is instantiated from a member definition of a class template? + if (const MemberSpecializationInfo *Info = + CRD->getMemberSpecializationInfo()) + return Info->getInstantiatedFrom(); + + return D; + } + if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) { + // Enum is instantiated from a member definition of a class template? + if (const EnumDecl *MemberDecl = ED->getInstantiatedFromMemberEnum()) + return MemberDecl; + + return D; + } + // FIXME: Adjust alias templates? return D; } } // unnamed namespace @@ -282,23 +356,83 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl( return RC; } -comments::FullComment *ASTContext::getCommentForDecl(const Decl *D) const { +static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod, + SmallVectorImpl<const NamedDecl *> &Redeclared) { + const DeclContext *DC = ObjCMethod->getDeclContext(); + if (const ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(DC)) { + const ObjCInterfaceDecl *ID = IMD->getClassInterface(); + if (!ID) + return; + // Add redeclared method here. + for (const ObjCCategoryDecl *ClsExtDecl = ID->getFirstClassExtension(); + ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { + if (ObjCMethodDecl *RedeclaredMethod = + ClsExtDecl->getMethod(ObjCMethod->getSelector(), + ObjCMethod->isInstanceMethod())) + Redeclared.push_back(RedeclaredMethod); + } + } +} + +comments::FullComment *ASTContext::cloneFullComment(comments::FullComment *FC, + const Decl *D) const { + comments::DeclInfo *ThisDeclInfo = new (*this) comments::DeclInfo; + ThisDeclInfo->CommentDecl = D; + ThisDeclInfo->IsFilled = false; + ThisDeclInfo->fill(); + ThisDeclInfo->CommentDecl = FC->getDecl(); + comments::FullComment *CFC = + new (*this) comments::FullComment(FC->getBlocks(), + ThisDeclInfo); + return CFC; + +} + +comments::FullComment *ASTContext::getCommentForDecl( + const Decl *D, + const Preprocessor *PP) const { D = adjustDeclToTemplate(D); + const Decl *Canonical = D->getCanonicalDecl(); llvm::DenseMap<const Decl *, comments::FullComment *>::iterator Pos = ParsedComments.find(Canonical); - if (Pos != ParsedComments.end()) + + if (Pos != ParsedComments.end()) { + if (Canonical != D) { + comments::FullComment *FC = Pos->second; + comments::FullComment *CFC = cloneFullComment(FC, D); + return CFC; + } return Pos->second; - + } + const Decl *OriginalDecl; + const RawComment *RC = getRawCommentForAnyRedecl(D, &OriginalDecl); - if (!RC) + if (!RC) { + if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) { + SmallVector<const NamedDecl*, 8> Overridden; + if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) + addRedeclaredMethods(OMD, Overridden); + getOverriddenMethods(dyn_cast<NamedDecl>(D), Overridden); + for (unsigned i = 0, e = Overridden.size(); i < e; i++) { + if (comments::FullComment *FC = getCommentForDecl(Overridden[i], PP)) { + comments::FullComment *CFC = cloneFullComment(FC, D); + return CFC; + } + } + } return NULL; - + } + + // If the RawComment was attached to other redeclaration of this Decl, we + // should parse the comment in context of that other Decl. This is important + // because comments can contain references to parameter names which can be + // different across redeclarations. if (D != OriginalDecl) - return getCommentForDecl(OriginalDecl); + return getCommentForDecl(OriginalDecl, PP); - comments::FullComment *FC = RC->parse(*this, D); + comments::FullComment *FC = RC->parse(*this, PP, D); ParsedComments[Canonical] = FC; return FC; } @@ -481,6 +615,7 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, Int128Decl(0), UInt128Decl(0), BuiltinVaListDecl(0), ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0), ObjCProtocolClassDecl(0), + BOOLDecl(0), CFConstantStringTypeDecl(0), ObjCInstanceTypeDecl(0), FILEDecl(0), jmp_bufDecl(0), sigjmp_bufDecl(0), ucontext_tDecl(0), @@ -495,6 +630,7 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, DeclarationNames(*this), ExternalSource(0), Listener(0), Comments(SM), CommentsLoaded(false), + CommentCommandTraits(BumpAlloc), LastSDM(0, 0), UniqueBlockByRefTypeID(0) { @@ -683,12 +819,12 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { InitBuiltinType(Int128Ty, BuiltinType::Int128); InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128); - if (LangOpts.CPlusPlus) { // C++ 3.9.1p5 + if (LangOpts.CPlusPlus && LangOpts.WChar) { // C++ 3.9.1p5 if (TargetInfo::isTypeSigned(Target.getWCharType())) InitBuiltinType(WCharTy, BuiltinType::WChar_S); else // -fshort-wchar makes wchar_t be unsigned. InitBuiltinType(WCharTy, BuiltinType::WChar_U); - } else // C99 + } else // C99 (or C++ using -fno-wchar) WCharTy = getFromTargetType(Target.getWCharType()); WIntTy = getFromTargetType(Target.getWIntType()); @@ -725,6 +861,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { // Placeholder type for unbridged ARC casts. InitBuiltinType(ARCUnbridgedCastTy, BuiltinType::ARCUnbridgedCast); + // Placeholder type for builtin functions. + InitBuiltinType(BuiltinFnTy, BuiltinType::BuiltinFn); + // C99 6.2.5p11. FloatComplexTy = getComplexType(FloatTy); DoubleComplexTy = getComplexType(DoubleTy); @@ -909,7 +1048,7 @@ bool ASTContext::BitfieldFollowsNonBitfield(const FieldDecl *FD, ASTContext::overridden_cxx_method_iterator ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const { llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos - = OverriddenMethods.find(Method); + = OverriddenMethods.find(Method->getCanonicalDecl()); if (Pos == OverriddenMethods.end()) return 0; @@ -919,7 +1058,7 @@ ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const { ASTContext::overridden_cxx_method_iterator ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const { llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos - = OverriddenMethods.find(Method); + = OverriddenMethods.find(Method->getCanonicalDecl()); if (Pos == OverriddenMethods.end()) return 0; @@ -929,7 +1068,7 @@ ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const { unsigned ASTContext::overridden_methods_size(const CXXMethodDecl *Method) const { llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos - = OverriddenMethods.find(Method); + = OverriddenMethods.find(Method->getCanonicalDecl()); if (Pos == OverriddenMethods.end()) return 0; @@ -938,9 +1077,30 @@ ASTContext::overridden_methods_size(const CXXMethodDecl *Method) const { void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method, const CXXMethodDecl *Overridden) { + assert(Method->isCanonicalDecl() && Overridden->isCanonicalDecl()); OverriddenMethods[Method].push_back(Overridden); } +void ASTContext::getOverriddenMethods( + const NamedDecl *D, + SmallVectorImpl<const NamedDecl *> &Overridden) const { + assert(D); + + if (const CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) { + Overridden.append(CXXMethod->begin_overridden_methods(), + CXXMethod->end_overridden_methods()); + return; + } + + const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D); + if (!Method) + return; + + SmallVector<const ObjCMethodDecl *, 8> OverDecls; + Method->getOverriddenMethods(OverDecls); + Overridden.append(OverDecls.begin(), OverDecls.end()); +} + void ASTContext::addedLocalImportDecl(ImportDecl *Import) { assert(!Import->NextLocalImport && "Import declaration already in the chain"); assert(!Import->isFromASTFile() && "Non-local import declaration"); @@ -1062,6 +1222,27 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { return toCharUnitsFromBits(Align); } +// getTypeInfoDataSizeInChars - Return the size of a type, in +// chars. If the type is a record, its data size is returned. This is +// the size of the memcpy that's performed when assigning this type +// using a trivial copy/move assignment operator. +std::pair<CharUnits, CharUnits> +ASTContext::getTypeInfoDataSizeInChars(QualType T) const { + std::pair<CharUnits, CharUnits> sizeAndAlign = getTypeInfoInChars(T); + + // In C++, objects can sometimes be allocated into the tail padding + // of a base-class subobject. We decide whether that's possible + // during class layout, so here we can just trust the layout results. + if (getLangOpts().CPlusPlus) { + if (const RecordType *RT = T->getAs<RecordType>()) { + const ASTRecordLayout &layout = getASTRecordLayout(RT->getDecl()); + sizeAndAlign.first = layout.getDataSize(); + } + } + + return sizeAndAlign; +} + std::pair<CharUnits, CharUnits> ASTContext::getTypeInfoInChars(const Type *T) const { std::pair<uint64_t, unsigned> Info = getTypeInfo(T); @@ -3353,6 +3534,12 @@ QualType ASTContext::getPointerDiffType() const { return getFromTargetType(Target->getPtrDiffType(0)); } +/// \brief Return the unique type for "pid_t" defined in +/// <sys/types.h>. We need this to compute the correct type for vfork(). +QualType ASTContext::getProcessIDType() const { + return getFromTargetType(Target->getProcessIDType()); +} + //===----------------------------------------------------------------------===// // Type Operators //===----------------------------------------------------------------------===// @@ -3581,11 +3768,14 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { return Arg; case TemplateArgument::Declaration: { - if (Decl *D = Arg.getAsDecl()) - return TemplateArgument(D->getCanonicalDecl()); - return TemplateArgument((Decl*)0); + ValueDecl *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl()); + return TemplateArgument(D, Arg.isDeclForReferenceParam()); } + case TemplateArgument::NullPtr: + return TemplateArgument(getCanonicalType(Arg.getNullPtrType()), + /*isNullPtr*/true); + case TemplateArgument::Template: return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate())); @@ -4297,7 +4487,13 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { QualType BlockTy = Expr->getType()->getAs<BlockPointerType>()->getPointeeType(); // Encode result type. - getObjCEncodingForType(BlockTy->getAs<FunctionType>()->getResultType(), S); + if (getLangOpts().EncodeExtendedBlockSig) + getObjCEncodingForMethodParameter(Decl::OBJC_TQ_None, + BlockTy->getAs<FunctionType>()->getResultType(), + S, true /*Extended*/); + else + getObjCEncodingForType(BlockTy->getAs<FunctionType>()->getResultType(), + S); // Compute size of all parameters. // Start with computing size of a pointer in number of bytes. // FIXME: There might(should) be a better way of doing this computation! @@ -4332,7 +4528,11 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { PType = PVDecl->getType(); } else if (PType->isFunctionType()) PType = PVDecl->getType(); - getObjCEncodingForType(PType, S); + if (getLangOpts().EncodeExtendedBlockSig) + getObjCEncodingForMethodParameter(Decl::OBJC_TQ_None, PType, + S, true /*Extended*/); + else + getObjCEncodingForType(PType, S); S += charUnitsToString(ParmOffset); ParmOffset += getObjCEncodingTypeSize(PType); } @@ -5393,6 +5593,65 @@ static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) { return VaListTypedefDecl; } +static TypedefDecl * +CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) { + RecordDecl *VaListDecl; + if (Context->getLangOpts().CPlusPlus) { + // namespace std { struct __va_list { + NamespaceDecl *NS; + NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context), + Context->getTranslationUnitDecl(), + /*Inline*/false, SourceLocation(), + SourceLocation(), &Context->Idents.get("std"), + /*PrevDecl*/0); + + VaListDecl = CXXRecordDecl::Create(*Context, TTK_Struct, + Context->getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + &Context->Idents.get("__va_list")); + + VaListDecl->setDeclContext(NS); + + } else { + // struct __va_list { + VaListDecl = CreateRecordDecl(*Context, TTK_Struct, + Context->getTranslationUnitDecl(), + &Context->Idents.get("__va_list")); + } + + VaListDecl->startDefinition(); + + // void * __ap; + FieldDecl *Field = FieldDecl::Create(const_cast<ASTContext &>(*Context), + VaListDecl, + SourceLocation(), + SourceLocation(), + &Context->Idents.get("__ap"), + Context->getPointerType(Context->VoidTy), + /*TInfo=*/0, + /*BitWidth=*/0, + /*Mutable=*/false, + ICIS_NoInit); + Field->setAccess(AS_public); + VaListDecl->addDecl(Field); + + // }; + VaListDecl->completeDefinition(); + + // typedef struct __va_list __builtin_va_list; + TypeSourceInfo *TInfo + = Context->getTrivialTypeSourceInfo(Context->getRecordType(VaListDecl)); + + TypedefDecl *VaListTypeDecl + = TypedefDecl::Create(const_cast<ASTContext &>(*Context), + Context->getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + &Context->Idents.get("__builtin_va_list"), + TInfo); + + return VaListTypeDecl; +} + static TypedefDecl *CreateVaListDecl(const ASTContext *Context, TargetInfo::BuiltinVaListKind Kind) { switch (Kind) { @@ -5406,6 +5665,8 @@ static TypedefDecl *CreateVaListDecl(const ASTContext *Context, return CreateX86_64ABIBuiltinVaListDecl(Context); case TargetInfo::PNaClABIBuiltinVaList: return CreatePNaClABIBuiltinVaListDecl(Context); + case TargetInfo::AAPCSABIBuiltinVaList: + return CreateAAPCSABIBuiltinVaListDecl(Context); } llvm_unreachable("Unhandled __builtin_va_list type kind"); @@ -5702,7 +5963,7 @@ ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, return false; } -/// QualifiedIdConformsQualifiedId - compare id<p,...> with id<p1,...> +/// QualifiedIdConformsQualifiedId - compare id<pr,...> with id<pr1,...> /// return true if lhs's protocols conform to rhs's protocol; false /// otherwise. bool ASTContext::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) { @@ -5711,8 +5972,8 @@ bool ASTContext::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) { return false; } -/// ObjCQualifiedClassTypesAreCompatible - compare Class<p,...> and -/// Class<p1, ...>. +/// ObjCQualifiedClassTypesAreCompatible - compare Class<pr,...> and +/// Class<pr1, ...>. bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs, QualType rhs) { const ObjCObjectPointerType *lhsQID = lhs->getAs<ObjCObjectPointerType>(); @@ -6315,10 +6576,13 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, for (unsigned i = 0; i < proto_nargs; ++i) { QualType argTy = proto->getArgType(i); - // Look at the promotion type of enum types, since that is the type used + // Look at the converted type of enum types, since that is the type used // to pass enum values. - if (const EnumType *Enum = argTy->getAs<EnumType>()) - argTy = Enum->getDecl()->getPromotionType(); + if (const EnumType *Enum = argTy->getAs<EnumType>()) { + argTy = Enum->getDecl()->getIntegerType(); + if (argTy.isNull()) + return QualType(); + } if (argTy->isPromotableIntegerType() || getCanonicalType(argTy).getUnqualifiedType() == FloatTy) @@ -6725,7 +6989,7 @@ unsigned ASTContext::getIntWidth(QualType T) const { return (unsigned)getTypeSize(T); } -QualType ASTContext::getCorrespondingUnsignedType(QualType T) { +QualType ASTContext::getCorrespondingUnsignedType(QualType T) const { assert(T->hasSignedIntegerRepresentation() && "Unexpected type"); // Turn <4 x signed int> -> <4 x unsigned int> @@ -6959,6 +7223,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, return QualType(); } break; + case 'p': + Type = Context.getProcessIDType(); + break; } // If there are modifiers and if we're allowed to parse them, go for it. |