diff options
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r-- | lib/AST/ASTContext.cpp | 259 |
1 files changed, 225 insertions, 34 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index b55a926e32..176aec53a2 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -97,7 +97,12 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { if (ED->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) return NULL; } - + if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { + // When tag declaration (but not definition!) is part of the + // decl-specifier-seq of some other declaration, it doesn't get comment + if (TD->isEmbeddedInDeclarator() && !TD->isCompleteDefinition()) + return NULL; + } // TODO: handle comments for function parameters properly. if (isa<ParmVarDecl>(D)) return NULL; @@ -141,7 +146,9 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // When searching for comments during parsing, the comment we are looking // for is usually among the last two comments we parsed -- check them // first. - RawComment CommentAtDeclLoc(SourceMgr, SourceRange(DeclLoc)); + RawComment CommentAtDeclLoc( + SourceMgr, SourceRange(DeclLoc), false, + LangOpts.CommentOpts.ParseAllComments); BeforeThanCompare<RawComment> Compare(SourceMgr); ArrayRef<RawComment *>::iterator MaybeBeforeDecl = RawComments.end() - 1; bool Found = Compare(*MaybeBeforeDecl, &CommentAtDeclLoc); @@ -435,7 +442,7 @@ comments::FullComment *ASTContext::getCommentForDecl( if (comments::FullComment *FC = getCommentForDecl(Overridden[i], PP)) return cloneFullComment(FC, D); } - else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { + else if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { // Attach any tag type's documentation to its typedef if latter // does not have one of its own. QualType QT = TD->getUnderlyingType(); @@ -444,6 +451,53 @@ comments::FullComment *ASTContext::getCommentForDecl( if (comments::FullComment *FC = getCommentForDecl(TD, PP)) return cloneFullComment(FC, D); } + else if (const ObjCInterfaceDecl *IC = dyn_cast<ObjCInterfaceDecl>(D)) { + while (IC->getSuperClass()) { + IC = IC->getSuperClass(); + if (comments::FullComment *FC = getCommentForDecl(IC, PP)) + return cloneFullComment(FC, D); + } + } + else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) { + if (const ObjCInterfaceDecl *IC = CD->getClassInterface()) + if (comments::FullComment *FC = getCommentForDecl(IC, PP)) + return cloneFullComment(FC, D); + } + else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { + if (!(RD = RD->getDefinition())) + return NULL; + // Check non-virtual bases. + for (CXXRecordDecl::base_class_const_iterator I = + RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { + if (I->isVirtual() || (I->getAccessSpecifier() != AS_public)) + continue; + QualType Ty = I->getType(); + if (Ty.isNull()) + continue; + if (const CXXRecordDecl *NonVirtualBase = Ty->getAsCXXRecordDecl()) { + if (!(NonVirtualBase= NonVirtualBase->getDefinition())) + continue; + + if (comments::FullComment *FC = getCommentForDecl((NonVirtualBase), PP)) + return cloneFullComment(FC, D); + } + } + // Check virtual bases. + for (CXXRecordDecl::base_class_const_iterator I = + RD->vbases_begin(), E = RD->vbases_end(); I != E; ++I) { + if (I->getAccessSpecifier() != AS_public) + continue; + QualType Ty = I->getType(); + if (Ty.isNull()) + continue; + if (const CXXRecordDecl *VirtualBase = Ty->getAsCXXRecordDecl()) { + if (!(VirtualBase= VirtualBase->getDefinition())) + continue; + if (comments::FullComment *FC = getCommentForDecl((VirtualBase), PP)) + return cloneFullComment(FC, D); + } + } + } return NULL; } @@ -1125,8 +1179,8 @@ void ASTContext::getOverriddenMethods( assert(D); if (const CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) { - Overridden.append(CXXMethod->begin_overridden_methods(), - CXXMethod->end_overridden_methods()); + Overridden.append(overridden_methods_begin(CXXMethod), + overridden_methods_end(CXXMethod)); return; } @@ -1229,6 +1283,10 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { T = getBaseElementType(arrayType); } Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr())); + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (VD->hasGlobalStorage()) + Align = std::max(Align, getTargetInfo().getMinGlobalAlign()); + } } // Fields can be subject to extra alignment constraints, like if @@ -1496,10 +1554,7 @@ ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::MemberPointer: { const MemberPointerType *MPT = cast<MemberPointerType>(T); - std::pair<uint64_t, unsigned> PtrDiffInfo = - getTypeInfo(getPointerDiffType()); - Width = PtrDiffInfo.first * ABI->getMemberPointerSize(MPT); - Align = PtrDiffInfo.second; + llvm::tie(Width, Align) = ABI->getMemberPointerWidthAndAlign(MPT); break; } case Type::Complex: { @@ -1546,7 +1601,8 @@ ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Auto: { const AutoType *A = cast<AutoType>(T); - assert(A->isDeduced() && "Cannot request the size of a dependent type"); + assert(!A->getDeducedType().isNull() && + "cannot request the size of an undeduced or dependent auto type"); return getTypeInfo(A->getDeducedType().getTypePtr()); } @@ -1673,6 +1729,18 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { return ABIAlign; } +/// getAlignOfGlobalVar - Return the alignment in bits that should be given +/// to a global variable of the specified type. +unsigned ASTContext::getAlignOfGlobalVar(QualType T) const { + return std::max(getTypeAlign(T), getTargetInfo().getMinGlobalAlign()); +} + +/// getAlignOfGlobalVarInChars - Return the alignment in characters that +/// should be given to a global variable of the specified type. +CharUnits ASTContext::getAlignOfGlobalVarInChars(QualType T) const { + return toCharUnitsFromBits(getAlignOfGlobalVar(T)); +} + /// DeepCollectObjCIvars - /// This routine first collects all declared, but not synthesized, ivars in /// super class and then collects all ivars, including those synthesized for @@ -1983,6 +2051,16 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, return cast<FunctionType>(Result.getTypePtr()); } +void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD, + QualType ResultType) { + // FIXME: Need to inform serialization code about this! + for (FD = FD->getMostRecentDecl(); FD; FD = FD->getPreviousDecl()) { + const FunctionProtoType *FPT = FD->getType()->castAs<FunctionProtoType>(); + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + FD->setType(getFunctionType(ResultType, FPT->getArgTypes(), EPI)); + } +} + /// getComplexType - Return the uniqued reference to the type for a complex /// number with the specified element type. QualType ASTContext::getComplexType(QualType T) const { @@ -3511,18 +3589,24 @@ QualType ASTContext::getUnaryTransformType(QualType BaseType, return QualType(Ty, 0); } -/// getAutoType - We only unique auto types after they've been deduced. -QualType ASTContext::getAutoType(QualType DeducedType) const { +/// getAutoType - Return the uniqued reference to the 'auto' type which has been +/// deduced to the given type, or to the canonical undeduced 'auto' type, or the +/// canonical deduced-but-dependent 'auto' type. +QualType ASTContext::getAutoType(QualType DeducedType, bool IsDecltypeAuto, + bool IsDependent) const { + if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent) + return getAutoDeductType(); + + // Look in the folding set for an existing type. void *InsertPos = 0; - if (!DeducedType.isNull()) { - // Look in the folding set for an existing type. - llvm::FoldingSetNodeID ID; - AutoType::Profile(ID, DeducedType); - if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos)) - return QualType(AT, 0); - } + llvm::FoldingSetNodeID ID; + AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent); + if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(AT, 0); - AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType); + AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType, + IsDecltypeAuto, + IsDependent); Types.push_back(AT); if (InsertPos) AutoTypes.InsertNode(AT, InsertPos); @@ -3560,8 +3644,10 @@ QualType ASTContext::getAtomicType(QualType T) const { /// getAutoDeductType - Get type pattern for deducing against 'auto'. QualType ASTContext::getAutoDeductType() const { if (AutoDeductTy.isNull()) - AutoDeductTy = getAutoType(QualType()); - assert(!AutoDeductTy.isNull() && "can't build 'auto' pattern"); + AutoDeductTy = QualType( + new (*this, TypeAlignment) AutoType(QualType(), /*decltype(auto)*/false, + /*dependent*/false), + 0); return AutoDeductTy; } @@ -4191,7 +4277,7 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { if (E->isTypeDependent() || E->isValueDependent()) return QualType(); - FieldDecl *Field = E->getBitField(); + FieldDecl *Field = E->getSourceBitField(); // FIXME: conditional bit-fields? if (!Field) return QualType(); @@ -5334,6 +5420,11 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // FIXME. We should do a better job than gcc. return; + case Type::Auto: + // We could see an undeduced auto type here during error recovery. + // Just ignore it. + return; + #define ABSTRACT_TYPE(KIND, BASE) #define TYPE(KIND, BASE) #define DEPENDENT_TYPE(KIND, BASE) \ @@ -5889,6 +5980,80 @@ CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) { return VaListTypeDecl; } +static TypedefDecl * +CreateSystemZBuiltinVaListDecl(const ASTContext *Context) { + // typedef struct __va_list_tag { + RecordDecl *VaListTagDecl; + VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct, + Context->getTranslationUnitDecl(), + &Context->Idents.get("__va_list_tag")); + VaListTagDecl->startDefinition(); + + const size_t NumFields = 4; + QualType FieldTypes[NumFields]; + const char *FieldNames[NumFields]; + + // long __gpr; + FieldTypes[0] = Context->LongTy; + FieldNames[0] = "__gpr"; + + // long __fpr; + FieldTypes[1] = Context->LongTy; + FieldNames[1] = "__fpr"; + + // void *__overflow_arg_area; + FieldTypes[2] = Context->getPointerType(Context->VoidTy); + FieldNames[2] = "__overflow_arg_area"; + + // void *__reg_save_area; + FieldTypes[3] = Context->getPointerType(Context->VoidTy); + FieldNames[3] = "__reg_save_area"; + + // Create fields + for (unsigned i = 0; i < NumFields; ++i) { + FieldDecl *Field = FieldDecl::Create(const_cast<ASTContext &>(*Context), + VaListTagDecl, + SourceLocation(), + SourceLocation(), + &Context->Idents.get(FieldNames[i]), + FieldTypes[i], /*TInfo=*/0, + /*BitWidth=*/0, + /*Mutable=*/false, + ICIS_NoInit); + Field->setAccess(AS_public); + VaListTagDecl->addDecl(Field); + } + VaListTagDecl->completeDefinition(); + QualType VaListTagType = Context->getRecordType(VaListTagDecl); + Context->VaListTagTy = VaListTagType; + + // } __va_list_tag; + TypedefDecl *VaListTagTypedefDecl + = TypedefDecl::Create(const_cast<ASTContext &>(*Context), + Context->getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + &Context->Idents.get("__va_list_tag"), + Context->getTrivialTypeSourceInfo(VaListTagType)); + QualType VaListTagTypedefType = + Context->getTypedefType(VaListTagTypedefDecl); + + // typedef __va_list_tag __builtin_va_list[1]; + llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1); + QualType VaListTagArrayType + = Context->getConstantArrayType(VaListTagTypedefType, + Size, ArrayType::Normal,0); + TypeSourceInfo *TInfo + = Context->getTrivialTypeSourceInfo(VaListTagArrayType); + TypedefDecl *VaListTypedefDecl + = TypedefDecl::Create(const_cast<ASTContext &>(*Context), + Context->getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + &Context->Idents.get("__builtin_va_list"), + TInfo); + + return VaListTypedefDecl; +} + static TypedefDecl *CreateVaListDecl(const ASTContext *Context, TargetInfo::BuiltinVaListKind Kind) { switch (Kind) { @@ -5906,6 +6071,8 @@ static TypedefDecl *CreateVaListDecl(const ASTContext *Context, return CreatePNaClABIBuiltinVaListDecl(Context); case TargetInfo::AAPCSABIBuiltinVaList: return CreateAAPCSABIBuiltinVaListDecl(Context); + case TargetInfo::SystemZBuiltinVaList: + return CreateSystemZBuiltinVaListDecl(Context); } llvm_unreachable("Unhandled __builtin_va_list type kind"); @@ -6844,6 +7011,27 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, return getFunctionNoProtoType(retType, einfo); } +/// Given that we have an enum type and a non-enum type, try to merge them. +static QualType mergeEnumWithInteger(ASTContext &Context, const EnumType *ET, + QualType other, bool isBlockReturnType) { + // C99 6.7.2.2p4: Each enumerated type shall be compatible with char, + // a signed integer type, or an unsigned integer type. + // Compatibility is based on the underlying type, not the promotion + // type. + QualType underlyingType = ET->getDecl()->getIntegerType(); + if (underlyingType.isNull()) return QualType(); + if (Context.hasSameType(underlyingType, other)) + return other; + + // In block return types, we're more permissive and accept any + // integral type of the same size. + if (isBlockReturnType && other->isIntegerType() && + Context.getTypeSize(underlyingType) == Context.getTypeSize(other)) + return other; + + return QualType(); +} + QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool OfBlockPointer, bool Unqualified, bool BlockReturnType) { @@ -6925,19 +7113,13 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, // If the canonical type classes don't match. if (LHSClass != RHSClass) { - // C99 6.7.2.2p4: Each enumerated type shall be compatible with char, - // a signed integer type, or an unsigned integer type. - // Compatibility is based on the underlying type, not the promotion - // type. + // Note that we only have special rules for turning block enum + // returns into block int returns, not vice-versa. if (const EnumType* ETy = LHS->getAs<EnumType>()) { - QualType TINT = ETy->getDecl()->getIntegerType(); - if (!TINT.isNull() && hasSameType(TINT, RHSCan.getUnqualifiedType())) - return RHS; + return mergeEnumWithInteger(*this, ETy, RHS, false); } if (const EnumType* ETy = RHS->getAs<EnumType>()) { - QualType TINT = ETy->getDecl()->getIntegerType(); - if (!TINT.isNull() && hasSameType(TINT, LHSCan.getUnqualifiedType())) - return LHS; + return mergeEnumWithInteger(*this, ETy, LHS, BlockReturnType); } // allow block pointer type to match an 'id' type. if (OfBlockPointer && !BlockReturnType) { @@ -6960,6 +7142,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, #include "clang/AST/TypeNodes.def" llvm_unreachable("Non-canonical and dependent types shouldn't get here"); + case Type::Auto: case Type::LValueReference: case Type::RValueReference: case Type::MemberPointer: @@ -7661,7 +7844,15 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (!VD->isFileVarDecl()) return false; - } else if (!isa<FunctionDecl>(D)) + } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + // We never need to emit an uninstantiated function template. + if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate) + return false; + } else + return false; + + // If this is a member of a class template, we do not need to emit it. + if (D->getDeclContext()->isDependentContext()) return false; // Weak references don't produce any output by themselves. |