diff options
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/ASTContext.cpp | 216 | ||||
-rw-r--r-- | lib/AST/CXXInheritance.cpp | 51 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 47 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 48 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 190 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 4 | ||||
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 35 | ||||
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 4 | ||||
-rw-r--r-- | lib/AST/DeclarationName.cpp | 2 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 64 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 46 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 53 | ||||
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 78 | ||||
-rw-r--r-- | lib/AST/RecordLayoutBuilder.h | 1 | ||||
-rw-r--r-- | lib/AST/StmtDumper.cpp | 264 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 16 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 25 | ||||
-rw-r--r-- | lib/AST/TemplateBase.cpp | 2 | ||||
-rw-r--r-- | lib/AST/TemplateName.cpp | 28 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 46 | ||||
-rw-r--r-- | lib/AST/TypeLoc.cpp | 29 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 40 |
22 files changed, 808 insertions, 481 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 6c9ecf0..cc7055d 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -260,24 +260,40 @@ ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, } NamedDecl * -ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) { +ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) { llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos - = InstantiatedFromUnresolvedUsingDecl.find(UUD); - if (Pos == InstantiatedFromUnresolvedUsingDecl.end()) + = InstantiatedFromUsingDecl.find(UUD); + if (Pos == InstantiatedFromUsingDecl.end()) return 0; return Pos->second; } void -ASTContext::setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD, - NamedDecl *UUD) { - assert((isa<UnresolvedUsingValueDecl>(UUD) || - isa<UnresolvedUsingTypenameDecl>(UUD)) && - "original declaration is not an unresolved using decl"); - assert(!InstantiatedFromUnresolvedUsingDecl[UD] && - "Already noted what using decl what instantiated from"); - InstantiatedFromUnresolvedUsingDecl[UD] = UUD; +ASTContext::setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern) { + assert((isa<UsingDecl>(Pattern) || + isa<UnresolvedUsingValueDecl>(Pattern) || + isa<UnresolvedUsingTypenameDecl>(Pattern)) && + "pattern decl is not a using decl"); + assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists"); + InstantiatedFromUsingDecl[Inst] = Pattern; +} + +UsingShadowDecl * +ASTContext::getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst) { + llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>::const_iterator Pos + = InstantiatedFromUsingShadowDecl.find(Inst); + if (Pos == InstantiatedFromUsingShadowDecl.end()) + return 0; + + return Pos->second; +} + +void +ASTContext::setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst, + UsingShadowDecl *Pattern) { + assert(!InstantiatedFromUsingShadowDecl[Inst] && "pattern already exists"); + InstantiatedFromUsingShadowDecl[Inst] = Pattern; } FieldDecl *ASTContext::getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field) { @@ -711,10 +727,6 @@ ASTContext::getTypeInfo(const Type *T) { break; } case Type::MemberPointer: { - // FIXME: This is ABI dependent. We use the Itanium C++ ABI. - // http://www.codesourcery.com/public/cxx-abi/abi.html#member-pointers - // If we ever want to support other ABIs this needs to be abstracted. - QualType Pointee = cast<MemberPointerType>(T)->getPointeeType(); std::pair<uint64_t, unsigned> PtrDiffInfo = getTypeInfo(getPointerDiffType()); @@ -997,31 +1009,31 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD, ObjCImpls[CatD] = ImplD; } -/// \brief Allocate an uninitialized DeclaratorInfo. +/// \brief Allocate an uninitialized TypeSourceInfo. /// -/// The caller should initialize the memory held by DeclaratorInfo using +/// The caller should initialize the memory held by TypeSourceInfo using /// the TypeLoc wrappers. /// /// \param T the type that will be the basis for type source info. This type /// should refer to how the declarator was written in source code, not to /// what type semantic analysis resolved the declarator to. -DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T, +TypeSourceInfo *ASTContext::CreateTypeSourceInfo(QualType T, unsigned DataSize) { if (!DataSize) DataSize = TypeLoc::getFullDataSizeForType(T); else assert(DataSize == TypeLoc::getFullDataSizeForType(T) && - "incorrect data size provided to CreateDeclaratorInfo!"); + "incorrect data size provided to CreateTypeSourceInfo!"); - DeclaratorInfo *DInfo = - (DeclaratorInfo*)BumpAlloc.Allocate(sizeof(DeclaratorInfo) + DataSize, 8); - new (DInfo) DeclaratorInfo(T); - return DInfo; + TypeSourceInfo *TInfo = + (TypeSourceInfo*)BumpAlloc.Allocate(sizeof(TypeSourceInfo) + DataSize, 8); + new (TInfo) TypeSourceInfo(T); + return TInfo; } -DeclaratorInfo *ASTContext::getTrivialDeclaratorInfo(QualType T, +TypeSourceInfo *ASTContext::getTrivialTypeSourceInfo(QualType T, SourceLocation L) { - DeclaratorInfo *DI = CreateDeclaratorInfo(T); + TypeSourceInfo *DI = CreateTypeSourceInfo(T); DI->getTypeLoc().initialize(L); return DI; } @@ -1092,6 +1104,20 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) { return *NewEntry; } +const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) { + RD = cast<CXXRecordDecl>(RD->getDefinition(*this)); + assert(RD && "Cannot get key function for forward declarations!"); + + const CXXMethodDecl *&Entry = KeyFunctions[RD]; + if (!Entry) + Entry = ASTRecordLayoutBuilder::ComputeKeyFunction(RD); + else + assert(Entry == ASTRecordLayoutBuilder::ComputeKeyFunction(RD) && + "Key function changed!"); + + return Entry; +} + //===----------------------------------------------------------------------===// // Type creation/memoization methods //===----------------------------------------------------------------------===// @@ -1174,32 +1200,42 @@ QualType ASTContext::getObjCGCQualType(QualType T, return getExtQualType(TypeNode, Quals); } -QualType ASTContext::getNoReturnType(QualType T) { +QualType ASTContext::getNoReturnType(QualType T, bool AddNoReturn) { QualType ResultType; - if (T->isPointerType()) { - QualType Pointee = T->getAs<PointerType>()->getPointeeType(); - ResultType = getNoReturnType(Pointee); + if (const PointerType *Pointer = T->getAs<PointerType>()) { + QualType Pointee = Pointer->getPointeeType(); + ResultType = getNoReturnType(Pointee, AddNoReturn); + if (ResultType == Pointee) + return T; + ResultType = getPointerType(ResultType); - } else if (T->isBlockPointerType()) { - QualType Pointee = T->getAs<BlockPointerType>()->getPointeeType(); - ResultType = getNoReturnType(Pointee); + } else if (const BlockPointerType *BlockPointer + = T->getAs<BlockPointerType>()) { + QualType Pointee = BlockPointer->getPointeeType(); + ResultType = getNoReturnType(Pointee, AddNoReturn); + if (ResultType == Pointee) + return T; + ResultType = getBlockPointerType(ResultType); - } else { - assert (T->isFunctionType() - && "can't noreturn qualify non-pointer to function or block type"); - - if (const FunctionNoProtoType *FNPT = T->getAs<FunctionNoProtoType>()) { - ResultType = getFunctionNoProtoType(FNPT->getResultType(), true); + } else if (const FunctionType *F = T->getAs<FunctionType>()) { + if (F->getNoReturnAttr() == AddNoReturn) + return T; + + if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(F)) { + ResultType = getFunctionNoProtoType(FNPT->getResultType(), AddNoReturn); } else { - const FunctionProtoType *F = T->getAs<FunctionProtoType>(); + const FunctionProtoType *FPT = cast<FunctionProtoType>(F); ResultType - = getFunctionType(F->getResultType(), F->arg_type_begin(), - F->getNumArgs(), F->isVariadic(), F->getTypeQuals(), - F->hasExceptionSpec(), F->hasAnyExceptionSpec(), - F->getNumExceptions(), F->exception_begin(), true); + = getFunctionType(FPT->getResultType(), FPT->arg_type_begin(), + FPT->getNumArgs(), FPT->isVariadic(), + FPT->getTypeQuals(), + FPT->hasExceptionSpec(), FPT->hasAnyExceptionSpec(), + FPT->getNumExceptions(), FPT->exception_begin(), + AddNoReturn); } - } - + } else + return T; + return getQualifiedType(ResultType, T.getLocalQualifiers()); } @@ -1766,6 +1802,9 @@ QualType ASTContext::getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl) { Decl->TypeForDecl = PrevDecl->TypeForDecl; else Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Enum); + } else if (UnresolvedUsingTypenameDecl *Using = + dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) { + Decl->TypeForDecl = new (*this, TypeAlignment) UnresolvedUsingType(Using); } else assert(false && "TypeDecl without a type?"); @@ -2238,7 +2277,7 @@ QualType ASTContext::getTagDeclType(const TagDecl *Decl) { /// getSizeType - Return the unique type for "size_t" (C99 7.17), the result /// of the sizeof operator (C99 6.5.3.4p4). The value is target dependent and /// needs to agree with the definition in <stddef.h>. -QualType ASTContext::getSizeType() const { +CanQualType ASTContext::getSizeType() const { return getFromTargetType(Target.getSizeType()); } @@ -2354,8 +2393,9 @@ DeclarationName ASTContext::getNameForTemplate(TemplateName Name) { } } - assert(Name.getAsOverloadedFunctionDecl()); - return Name.getAsOverloadedFunctionDecl()->getDeclName(); + OverloadedTemplateStorage *Storage = Name.getAsOverloadedTemplate(); + assert(Storage); + return (*Storage->begin())->getDeclName(); } TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) { @@ -2364,27 +2404,7 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) { if (TemplateDecl *Template = Name.getAsTemplateDecl()) return TemplateName(cast<TemplateDecl>(Template->getCanonicalDecl())); - // If this template name refers to a set of overloaded function templates, - /// the canonical template name merely stores the set of function templates. - if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl()) { - OverloadedFunctionDecl *CanonOvl = 0; - for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(), - FEnd = Ovl->function_end(); - F != FEnd; ++F) { - Decl *Canon = F->get()->getCanonicalDecl(); - if (CanonOvl || Canon != F->get()) { - if (!CanonOvl) - CanonOvl = OverloadedFunctionDecl::Create(*this, - Ovl->getDeclContext(), - Ovl->getDeclName()); - - CanonOvl->addOverload( - AnyFunctionDecl::getFromNamedDecl(cast<NamedDecl>(Canon))); - } - } - - return TemplateName(CanonOvl? CanonOvl : Ovl); - } + assert(!Name.getAsOverloadedTemplate()); DependentTemplateName *DTN = Name.getAsDependentTemplateName(); assert(DTN && "Non-dependent template names must refer to template decls."); @@ -2651,7 +2671,7 @@ int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) { unsigned ASTContext::getIntegerRank(Type *T) { assert(T->isCanonicalUnqualified() && "T should be canonicalized"); if (EnumType* ET = dyn_cast<EnumType>(T)) - T = ET->getDecl()->getIntegerType().getTypePtr(); + T = ET->getDecl()->getPromotionType().getTypePtr(); if (T->isSpecificBuiltinType(BuiltinType::WChar)) T = getFromTargetType(Target.getWCharType()).getTypePtr(); @@ -2732,6 +2752,8 @@ QualType ASTContext::isPromotableBitField(Expr *E) { QualType ASTContext::getPromotedIntegerType(QualType Promotable) { assert(!Promotable.isNull()); assert(Promotable->isPromotableIntegerType()); + if (const EnumType *ET = Promotable->getAs<EnumType>()) + return ET->getDecl()->getPromotionType(); if (Promotable->isSignedIntegerType()) return IntTy; uint64_t PromotableSize = getTypeSize(Promotable); @@ -2812,7 +2834,7 @@ QualType ASTContext::getCFConstantStringType() { for (unsigned i = 0; i < 4; ++i) { FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTypeDecl, SourceLocation(), 0, - FieldTypes[i], /*DInfo=*/0, + FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, /*Mutable=*/false); CFConstantStringTypeDecl->addDecl(Field); @@ -2848,7 +2870,7 @@ QualType ASTContext::getObjCFastEnumerationStateType() { FieldDecl *Field = FieldDecl::Create(*this, ObjCFastEnumerationStateTypeDecl, SourceLocation(), 0, - FieldTypes[i], /*DInfo=*/0, + FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, /*Mutable=*/false); ObjCFastEnumerationStateTypeDecl->addDecl(Field); @@ -2884,7 +2906,7 @@ QualType ASTContext::getBlockDescriptorType() { T, SourceLocation(), &Idents.get(FieldNames[i]), - FieldTypes[i], /*DInfo=*/0, + FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, /*Mutable=*/false); T->addDecl(Field); @@ -2931,7 +2953,7 @@ QualType ASTContext::getBlockDescriptorExtendedType() { T, SourceLocation(), &Idents.get(FieldNames[i]), - FieldTypes[i], /*DInfo=*/0, + FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, /*Mutable=*/false); T->addDecl(Field); @@ -3009,7 +3031,7 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) { continue; FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), &Idents.get(FieldNames[i]), - FieldTypes[i], /*DInfo=*/0, + FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, /*Mutable=*/false); T->addDecl(Field); } @@ -3052,7 +3074,7 @@ QualType ASTContext::getBlockParmType( for (size_t i = 0; i < 5; ++i) { FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), &Idents.get(FieldNames[i]), - FieldTypes[i], /*DInfo=*/0, + FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, /*Mutable=*/false); T->addDecl(Field); } @@ -3072,7 +3094,7 @@ QualType ASTContext::getBlockParmType( FieldType); FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), - Name, FieldType, /*DInfo=*/0, + Name, FieldType, /*TInfo=*/0, /*BitWidth=*/0, /*Mutable=*/false); T->addDecl(Field); } @@ -3690,36 +3712,40 @@ void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) { ObjCConstantStringType = getObjCInterfaceType(Decl); } -/// \brief Retrieve the template name that represents a qualified -/// template name such as \c std::vector. -TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, - bool TemplateKeyword, - TemplateDecl *Template) { - llvm::FoldingSetNodeID ID; - QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template); +/// \brief Retrieve the template name that corresponds to a non-empty +/// lookup. +TemplateName ASTContext::getOverloadedTemplateName(NamedDecl * const *Begin, + NamedDecl * const *End) { + unsigned size = End - Begin; + assert(size > 1 && "set is not overloaded!"); - void *InsertPos = 0; - QualifiedTemplateName *QTN = - QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos); - if (!QTN) { - QTN = new (*this,4) QualifiedTemplateName(NNS, TemplateKeyword, Template); - QualifiedTemplateNames.InsertNode(QTN, InsertPos); + void *memory = Allocate(sizeof(OverloadedTemplateStorage) + + size * sizeof(FunctionTemplateDecl*)); + OverloadedTemplateStorage *OT = new(memory) OverloadedTemplateStorage(size); + + NamedDecl **Storage = OT->getStorage(); + for (NamedDecl * const *I = Begin; I != End; ++I) { + NamedDecl *D = *I; + assert(isa<FunctionTemplateDecl>(D) || + (isa<UsingShadowDecl>(D) && + isa<FunctionTemplateDecl>(D->getUnderlyingDecl()))); + *Storage++ = D; } - return TemplateName(QTN); + return TemplateName(OT); } /// \brief Retrieve the template name that represents a qualified /// template name such as \c std::vector. TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, - OverloadedFunctionDecl *Template) { + TemplateDecl *Template) { llvm::FoldingSetNodeID ID; QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template); void *InsertPos = 0; QualifiedTemplateName *QTN = - QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos); + QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos); if (!QTN) { QTN = new (*this,4) QualifiedTemplateName(NNS, TemplateKeyword, Template); QualifiedTemplateNames.InsertNode(QTN, InsertPos); @@ -4334,6 +4360,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { 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. if (const EnumType* ETy = LHS->getAs<EnumType>()) { if (ETy->getDecl()->getIntegerType() == RHSCan.getUnqualifiedType()) return RHS; @@ -4493,6 +4521,8 @@ unsigned ASTContext::getIntWidth(QualType T) { if (FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) { return FWIT->getWidth(); } + if (EnumType *ET = dyn_cast<EnumType>(T)) + T = ET->getDecl()->getIntegerType(); // For builtin types, just use the standard type sizing method return (unsigned)getTypeSize(T); } diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index 023bca4..92a58b7 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -90,6 +90,57 @@ bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) cons return lookupInBases(&FindBaseClass, Base->getCanonicalDecl(), Paths); } +static bool BaseIsNot(const CXXRecordDecl *Base, void *OpaqueTarget) { + // OpaqueTarget is a CXXRecordDecl*. + return Base->getCanonicalDecl() != (const CXXRecordDecl*) OpaqueTarget; +} + +bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const { + return forallBases(BaseIsNot, (void*) Base->getCanonicalDecl()); +} + +bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches, + void *OpaqueData, + bool AllowShortCircuit) const { + ASTContext &Context = getASTContext(); + llvm::SmallVector<const CXXRecordDecl*, 8> Queue; + + const CXXRecordDecl *Record = this; + bool AllMatches = true; + while (true) { + for (CXXRecordDecl::base_class_const_iterator + I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) { + const RecordType *Ty = I->getType()->getAs<RecordType>(); + if (!Ty) { + if (AllowShortCircuit) return false; + AllMatches = false; + continue; + } + + CXXRecordDecl *Base = + cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition(Context)); + if (!Base) { + if (AllowShortCircuit) return false; + AllMatches = false; + continue; + } + + Queue.push_back(Base); + if (!BaseMatches(Base, OpaqueData)) { + if (AllowShortCircuit) return false; + AllMatches = false; + continue; + } + } + + if (Queue.empty()) break; + Record = Queue.back(); // not actually a queue. + Queue.pop_back(); + } + + return AllMatches; +} + bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData, CXXBasePaths &Paths) const { diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 572d76f..4d0d422 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -38,7 +38,7 @@ void Attr::Destroy(ASTContext &C) { } /// \brief Return the TypeLoc wrapper for the type source info. -TypeLoc DeclaratorInfo::getTypeLoc() const { +TypeLoc TypeSourceInfo::getTypeLoc() const { return TypeLoc(Ty, (void*)(this + 1)); } @@ -86,17 +86,17 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, DeclaratorInfo *DInfo, + QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg) { - return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, DInfo, S, DefArg); + return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, TInfo, S, DefArg); } SourceRange ParmVarDecl::getDefaultArgRange() const { if (const Expr *E = getInit()) return E->getSourceRange(); - if (const Expr *E = getUninstantiatedDefaultArg()) - return E->getSourceRange(); + if (hasUninstantiatedDefaultArg()) + return getUninstantiatedDefaultArg()->getSourceRange(); return SourceRange(); } @@ -136,11 +136,11 @@ bool VarDecl::isExternC() const { FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, - DeclaratorInfo *DInfo, + TypeSourceInfo *TInfo, StorageClass S, bool isInline, bool hasWrittenPrototype) { FunctionDecl *New - = new (C) FunctionDecl(Function, DC, L, N, T, DInfo, S, isInline); + = new (C) FunctionDecl(Function, DC, L, N, T, TInfo, S, isInline); New->HasWrittenPrototype = hasWrittenPrototype; return New; } @@ -151,8 +151,8 @@ BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, - DeclaratorInfo *DInfo, Expr *BW, bool Mutable) { - return new (C) FieldDecl(Decl::Field, DC, L, Id, T, DInfo, BW, Mutable); + TypeSourceInfo *TInfo, Expr *BW, bool Mutable) { + return new (C) FieldDecl(Decl::Field, DC, L, Id, T, TInfo, BW, Mutable); } bool FieldDecl::isAnonymousStructOrUnion() const { @@ -179,8 +179,8 @@ void EnumConstantDecl::Destroy(ASTContext& C) { TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - DeclaratorInfo *DInfo) { - return new (C) TypedefDecl(DC, L, Id, DInfo); + TypeSourceInfo *TInfo) { + return new (C) TypedefDecl(DC, L, Id, TInfo); } EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -195,9 +195,12 @@ void EnumDecl::Destroy(ASTContext& C) { Decl::Destroy(C); } -void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) { +void EnumDecl::completeDefinition(ASTContext &C, + QualType NewType, + QualType NewPromotionType) { assert(!isDefinition() && "Cannot redefine enums!"); IntegerType = NewType; + PromotionType = NewPromotionType; TagDecl::completeDefinition(); } @@ -535,9 +538,9 @@ SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const { //===----------------------------------------------------------------------===// VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S) { - return new (C) VarDecl(Var, DC, L, Id, T, DInfo, S); + return new (C) VarDecl(Var, DC, L, Id, T, TInfo, S); } void VarDecl::Destroy(ASTContext& C) { @@ -838,8 +841,20 @@ unsigned FunctionDecl::getMinRequiredArguments() const { } bool FunctionDecl::isInlined() const { - if (isInlineSpecified() || (isa<CXXMethodDecl>(this) && !isOutOfLine())) + // FIXME: This is not enough. Consider: + // + // inline void f(); + // void f() { } + // + // f is inlined, but does not have inline specified. + // To fix this we should add an 'inline' flag to FunctionDecl. + if (isInlineSpecified()) return true; + + if (isa<CXXMethodDecl>(this)) { + if (!isOutOfLine() || getCanonicalDecl()->isInlineSpecified()) + return true; + } switch (getTemplateSpecializationKind()) { case TSK_Undeclared: @@ -1199,7 +1214,7 @@ TagDecl* TagDecl::getDefinition(ASTContext& C) const { TagDecl::TagKind TagDecl::getTagKindForTypeSpec(unsigned TypeSpec) { switch (TypeSpec) { - default: llvm::llvm_unreachable("unexpected type specifier"); + default: 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; diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 2dcd80b..3afb4e4 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -190,7 +190,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case CXXConstructor: case CXXDestructor: case CXXConversion: - case OverloadedFunction: case Typedef: case EnumConstant: case Var: @@ -199,7 +198,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case NonTypeTemplateParm: case ObjCMethod: case ObjCContainer: - case ObjCCategory: case ObjCInterface: case ObjCProperty: case ObjCCompatibleAlias: @@ -221,8 +219,9 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ObjCImplementation: return IDNS_ObjCImplementation; + case ObjCCategory: case ObjCCategoryImpl: - return IDNS_ObjCCategoryImpl; + return IDNS_ObjCCategoryName; case Field: case ObjCAtDefsField: @@ -637,6 +636,46 @@ bool DeclContext::decls_empty() const { return !FirstDecl; } +void DeclContext::removeDecl(Decl *D) { + assert(D->getLexicalDeclContext() == this && + "decl being removed from non-lexical context"); + assert((D->NextDeclInContext || D == LastDecl) && + "decl is not in decls list"); + + // Remove D from the decl chain. This is O(n) but hopefully rare. + if (D == FirstDecl) { + if (D == LastDecl) + FirstDecl = LastDecl = 0; + else + FirstDecl = D->NextDeclInContext; + } else { + for (Decl *I = FirstDecl; true; I = I->NextDeclInContext) { + assert(I && "decl not found in linked list"); + if (I->NextDeclInContext == D) { + I->NextDeclInContext = D->NextDeclInContext; + if (D == LastDecl) LastDecl = I; + break; + } + } + } + + // Mark that D is no longer in the decl chain. + D->NextDeclInContext = 0; + + // Remove D from the lookup table if necessary. + if (isa<NamedDecl>(D)) { + NamedDecl *ND = cast<NamedDecl>(D); + + void *OpaqueMap = getPrimaryContext()->LookupPtr; + if (!OpaqueMap) return; + + StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(OpaqueMap); + StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName()); + assert(Pos != Map->end() && "no lookup entry for decl"); + Pos->second.remove(ND); + } +} + void DeclContext::addHiddenDecl(Decl *D) { assert(D->getLexicalDeclContext() == this && "Decl inserted into wrong lexical context"); @@ -742,6 +781,9 @@ void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) { // from being visible? if (isa<ClassTemplateSpecializationDecl>(D)) return; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + if (FD->isFunctionTemplateSpecialization()) + return; DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) { diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 4001988..292a3ed 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -15,6 +15,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" @@ -438,6 +439,18 @@ void CXXRecordDecl::addConversionFunction(FunctionTemplateDecl *ConvDecl) { Conversions.addDecl(ConvDecl); } + +void CXXRecordDecl::setMethodAsVirtual(FunctionDecl *Method) { + Method->setVirtualAsWritten(true); + setAggregate(false); + setPOD(false); + setEmpty(false); + setPolymorphic(true); + setHasTrivialConstructor(false); + setHasTrivialCopyConstructor(false); + setHasTrivialCopyAssignment(false); +} + CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const { if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) return cast<CXXRecordDecl>(MSInfo->getInstantiatedFrom()); @@ -459,8 +472,8 @@ CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD, = new (getASTContext()) MemberSpecializationInfo(RD, TSK); } -TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() { - if (ClassTemplateSpecializationDecl *Spec +TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() const{ + if (const ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(this)) return Spec->getSpecializationKind(); @@ -507,8 +520,7 @@ CXXRecordDecl::getDefaultConstructor(ASTContext &Context) { return 0; } -const CXXDestructorDecl * -CXXRecordDecl::getDestructor(ASTContext &Context) { +CXXDestructorDecl *CXXRecordDecl::getDestructor(ASTContext &Context) { QualType ClassType = Context.getTypeDeclType(this); DeclarationName Name @@ -519,7 +531,7 @@ CXXRecordDecl::getDestructor(ASTContext &Context) { llvm::tie(I, E) = lookup(Name); assert(I != E && "Did not find a destructor!"); - const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(*I); + CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(*I); assert(++I == E && "Found more than one destructor!"); return Dtor; @@ -528,9 +540,9 @@ CXXRecordDecl::getDestructor(ASTContext &Context) { CXXMethodDecl * CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, - QualType T, DeclaratorInfo *DInfo, + QualType T, TypeSourceInfo *TInfo, bool isStatic, bool isInline) { - return new (C) CXXMethodDecl(CXXMethod, RD, L, N, T, DInfo, + return new (C) CXXMethodDecl(CXXMethod, RD, L, N, T, TInfo, isStatic, isInline); } @@ -577,6 +589,8 @@ typedef llvm::DenseMap<const CXXMethodDecl*, static OverriddenMethodsMapTy *OverriddenMethods = 0; void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) { + assert(MD->isCanonicalDecl() && "Method is not canonical!"); + // FIXME: The CXXMethodDecl dtor needs to remove and free the entry. if (!OverriddenMethods) @@ -630,55 +644,107 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const { return C.getPointerType(ClassTy); } -CXXBaseOrMemberInitializer:: -CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs, - CXXConstructorDecl *C, - SourceLocation L, SourceLocation R) - : Args(0), NumArgs(0), CtorOrAnonUnion(), IdLoc(L), RParenLoc(R) { - BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr()); - assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer"); - BaseOrMember |= 0x01; +static bool MethodHasBody(const CXXMethodDecl *MD, const FunctionDecl *&fn) { + // Simple case: function has a body + if (MD->getBody(fn)) + return true; + // Complex case: function is an instantiation of a function which has a + // body, but the definition hasn't been instantiated. + const FunctionDecl *PatternDecl = MD->getTemplateInstantiationPattern(); + if (PatternDecl && PatternDecl->getBody(fn)) + return true; + + return false; +} + +bool CXXMethodDecl::hasInlineBody() const { + const FunctionDecl *fn; + return MethodHasBody(this, fn) && !fn->isOutOfLine(); +} + +CXXBaseOrMemberInitializer:: +CXXBaseOrMemberInitializer(ASTContext &Context, + TypeSourceInfo *TInfo, CXXConstructorDecl *C, + SourceLocation L, + Expr **Args, unsigned NumArgs, + SourceLocation R) + : BaseOrMember(TInfo), Args(0), NumArgs(0), CtorOrAnonUnion(C), + LParenLoc(L), RParenLoc(R) +{ if (NumArgs > 0) { this->NumArgs = NumArgs; - // FIXME. Allocation via Context - this->Args = new Stmt*[NumArgs]; + this->Args = new (Context) Stmt*[NumArgs]; for (unsigned Idx = 0; Idx < NumArgs; ++Idx) this->Args[Idx] = Args[Idx]; } - CtorOrAnonUnion = C; } CXXBaseOrMemberInitializer:: -CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, - CXXConstructorDecl *C, - SourceLocation L, SourceLocation R) - : Args(0), NumArgs(0), CtorOrAnonUnion(), IdLoc(L), RParenLoc(R) { - BaseOrMember = reinterpret_cast<uintptr_t>(Member); - assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer"); - +CXXBaseOrMemberInitializer(ASTContext &Context, + FieldDecl *Member, SourceLocation MemberLoc, + CXXConstructorDecl *C, SourceLocation L, + Expr **Args, unsigned NumArgs, + SourceLocation R) + : BaseOrMember(Member), MemberLocation(MemberLoc), Args(0), NumArgs(0), + CtorOrAnonUnion(C), LParenLoc(L), RParenLoc(R) +{ if (NumArgs > 0) { this->NumArgs = NumArgs; - this->Args = new Stmt*[NumArgs]; + this->Args = new (Context) Stmt*[NumArgs]; for (unsigned Idx = 0; Idx < NumArgs; ++Idx) this->Args[Idx] = Args[Idx]; } - CtorOrAnonUnion = C; } -CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() { - delete [] Args; +void CXXBaseOrMemberInitializer::Destroy(ASTContext &Context) { + for (unsigned I = 0; I != NumArgs; ++I) + Args[I]->Destroy(Context); + Context.Deallocate(Args); + this->~CXXBaseOrMemberInitializer(); +} + +TypeLoc CXXBaseOrMemberInitializer::getBaseClassLoc() const { + if (isBaseInitializer()) + return BaseOrMember.get<TypeSourceInfo*>()->getTypeLoc(); + else + return TypeLoc(); +} + +Type *CXXBaseOrMemberInitializer::getBaseClass() { + if (isBaseInitializer()) + return BaseOrMember.get<TypeSourceInfo*>()->getType().getTypePtr(); + else + return 0; +} + +const Type *CXXBaseOrMemberInitializer::getBaseClass() const { + if (isBaseInitializer()) + return BaseOrMember.get<TypeSourceInfo*>()->getType().getTypePtr(); + else + return 0; +} + +SourceLocation CXXBaseOrMemberInitializer::getSourceLocation() const { + if (isMemberInitializer()) + return getMemberLocation(); + + return getBaseClassLoc().getSourceRange().getBegin(); +} + +SourceRange CXXBaseOrMemberInitializer::getSourceRange() const { + return SourceRange(getSourceLocation(), getRParenLoc()); } CXXConstructorDecl * CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, - QualType T, DeclaratorInfo *DInfo, + QualType T, TypeSourceInfo *TInfo, bool isExplicit, bool isInline, bool isImplicitlyDeclared) { assert(N.getNameKind() == DeclarationName::CXXConstructorName && "Name must refer to a constructor"); - return new (C) CXXConstructorDecl(RD, L, N, T, DInfo, isExplicit, isInline, + return new (C) CXXConstructorDecl(RD, L, N, T, TInfo, isExplicit, isInline, isImplicitlyDeclared); } @@ -790,69 +856,11 @@ CXXConstructorDecl::Destroy(ASTContext& C) { CXXConversionDecl * CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, - QualType T, DeclaratorInfo *DInfo, + QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicit) { assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName && "Name must refer to a conversion function"); - return new (C) CXXConversionDecl(RD, L, N, T, DInfo, isInline, isExplicit); -} - -OverloadedFunctionDecl * -OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC, - DeclarationName N) { - return new (C) OverloadedFunctionDecl(DC, N); -} - -OverloadIterator::OverloadIterator(NamedDecl *ND) : D(0) { - if (!ND) - return; - - if (isa<FunctionDecl>(ND) || isa<FunctionTemplateDecl>(ND)) - D = ND; - else if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(ND)) { - if (Ovl->size() != 0) { - D = ND; - Iter = Ovl->function_begin(); - } - } -} - -void OverloadedFunctionDecl::addOverload(AnyFunctionDecl F) { - Functions.push_back(F); - this->setLocation(F.get()->getLocation()); -} - -OverloadIterator::reference OverloadIterator::operator*() const { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - return FD; - - if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D)) - return FTD; - - assert(isa<OverloadedFunctionDecl>(D)); - return *Iter; -} - -OverloadIterator &OverloadIterator::operator++() { - if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) { - D = 0; - return *this; - } - - if (++Iter == cast<OverloadedFunctionDecl>(D)->function_end()) - D = 0; - - return *this; -} - -bool OverloadIterator::Equals(const OverloadIterator &Other) const { - if (!D || !Other.D) - return D == Other.D; - - if (D != Other.D) - return false; - - return !isa<OverloadedFunctionDecl>(D) || Iter == Other.Iter; + return new (C) CXXConversionDecl(RD, L, N, T, TInfo, isInline, isExplicit); } FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index c33720f..2506f27 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -501,9 +501,9 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, DeclaratorInfo *DInfo, + QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW) { - return new (C) ObjCIvarDecl(DC, L, Id, T, DInfo, ac, BW); + return new (C) ObjCIvarDecl(DC, L, Id, T, TInfo, ac, BW); } diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index a5982cf..32ac53d 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -52,7 +52,6 @@ namespace { void VisitVarDecl(VarDecl *D); void VisitParmVarDecl(ParmVarDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); - void VisitOverloadedFunctionDecl(OverloadedFunctionDecl *D); void VisitNamespaceDecl(NamespaceDecl *D); void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); @@ -149,6 +148,17 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls, } } +void DeclContext::dumpDeclContext() const { + // Get the translation unit + const DeclContext *DC = this; + while (!DC->isTranslationUnit()) + DC = DC->getParent(); + + ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext(); + DeclPrinter Printer(llvm::errs(), Ctx, Ctx.PrintingPolicy, 0); + Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false); +} + void Decl::dump() const { print(llvm::errs()); } @@ -362,6 +372,24 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } Proto += ")"; + + if (FT && FT->hasExceptionSpec()) { + Proto += " throw("; + if (FT->hasAnyExceptionSpec()) + Proto += "..."; + else + for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) { + if (I) + Proto += ", "; + + + std::string ExceptionType; + FT->getExceptionType(I).getAsStringInternal(ExceptionType, SubPolicy); + Proto += ExceptionType; + } + Proto += ")"; + } + if (D->hasAttr<NoReturnAttr>()) Proto += " __attribute((noreturn))"; if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) { @@ -488,11 +516,6 @@ void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { //---------------------------------------------------------------------------- // C++ declarations //---------------------------------------------------------------------------- -void DeclPrinter::VisitOverloadedFunctionDecl(OverloadedFunctionDecl *D) { - assert(false && - "OverloadedFunctionDecls aren't really decls and are never printed"); -} - void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) { Out << "namespace " << D->getNameAsString() << " {\n"; VisitDeclContext(D); diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 902339e..75b3975 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -262,8 +262,8 @@ NonTypeTemplateParmDecl * NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, - DeclaratorInfo *DInfo) { - return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, DInfo); + TypeSourceInfo *TInfo) { + return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, TInfo); } SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const { diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp index 3471657..0ce03c2 100644 --- a/lib/AST/DeclarationName.cpp +++ b/lib/AST/DeclarationName.cpp @@ -338,7 +338,7 @@ void DeclarationName::setFETokenInfo(void *T) { DeclarationName DeclarationName::getUsingDirectiveName() { // Single instance of DeclarationNameExtra for using-directive - static DeclarationNameExtra UDirExtra = + static const DeclarationNameExtra UDirExtra = { DeclarationNameExtra::CXXUsingDirective }; uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra); diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 624a620..139e04b 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -110,7 +110,7 @@ void DeclRefExpr::computeDependence() { DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - NamedDecl *D, SourceLocation NameLoc, + ValueDecl *D, SourceLocation NameLoc, const TemplateArgumentListInfo *TemplateArgs, QualType T) : Expr(DeclRefExprClass, T, false, false), @@ -118,7 +118,6 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, (Qualifier? HasQualifierFlag : 0) | (TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)), Loc(NameLoc) { - assert(!isa<OverloadedFunctionDecl>(D)); if (Qualifier) { NameQualifier *NQ = getNameQualifier(); NQ->NNS = Qualifier; @@ -134,7 +133,7 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - NamedDecl *D, + ValueDecl *D, SourceLocation NameLoc, QualType T, const TemplateArgumentListInfo *TemplateArgs) { @@ -204,7 +203,8 @@ std::string PredefinedExpr::ComputeName(ASTContext &Context, IdentType IT, } Proto += ")"; - AFT->getResultType().getAsStringInternal(Proto, Policy); + if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD)) + AFT->getResultType().getAsStringInternal(Proto, Policy); Out << Proto; @@ -471,7 +471,7 @@ QualType CallExpr::getCallReturnType() const { } MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, - SourceRange qualrange, NamedDecl *memberdecl, + SourceRange qualrange, ValueDecl *memberdecl, SourceLocation l, const TemplateArgumentListInfo *targs, QualType ty) : Expr(MemberExprClass, ty, @@ -494,7 +494,7 @@ MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifier *qual, SourceRange qualrange, - NamedDecl *memberdecl, + ValueDecl *memberdecl, SourceLocation l, const TemplateArgumentListInfo *targs, QualType ty) { @@ -558,12 +558,40 @@ const char *CastExpr::getCastKindName() const { return "FloatingCast"; case CastExpr::CK_MemberPointerToBoolean: return "MemberPointerToBoolean"; + case CastExpr::CK_AnyPointerToObjCPointerCast: + return "AnyPointerToObjCPointerCast"; + case CastExpr::CK_AnyPointerToBlockPointerCast: + return "AnyPointerToBlockPointerCast"; } assert(0 && "Unhandled cast kind!"); return 0; } +Expr *CastExpr::getSubExprAsWritten() { + Expr *SubExpr = 0; + CastExpr *E = this; + do { + SubExpr = E->getSubExpr(); + + // Skip any temporary bindings; they're implicit. + if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(SubExpr)) + SubExpr = Binder->getSubExpr(); + + // Conversions by constructor and conversion functions have a + // subexpression describing the call; strip it off. + if (E->getCastKind() == CastExpr::CK_ConstructorConversion) + SubExpr = cast<CXXConstructExpr>(SubExpr)->getArg(0); + else if (E->getCastKind() == CastExpr::CK_UserDefinedConversion) + SubExpr = cast<CXXMemberCallExpr>(SubExpr)->getImplicitObjectArgument(); + + // If the subexpression we're left with is an implicit cast, look + // through that, too. + } while ((E = dyn_cast<ImplicitCastExpr>(SubExpr))); + + return SubExpr; +} + /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "<<=". const char *BinaryOperator::getOpcodeStr(Opcode Op) { @@ -944,8 +972,7 @@ static bool DeclCanBeLvalue(const NamedDecl *Decl, ASTContext &Ctx) { return isa<VarDecl>(Decl) || isa<FieldDecl>(Decl) || // C++ 3.10p2: An lvalue refers to an object or function. (Ctx.getLangOptions().CPlusPlus && - (isa<FunctionDecl>(Decl) || isa<OverloadedFunctionDecl>(Decl) || - isa<FunctionTemplateDecl>(Decl))); + (isa<FunctionDecl>(Decl) || isa<FunctionTemplateDecl>(Decl))); } /// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or an @@ -982,6 +1009,7 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { // Check whether the expression can be sanely treated like an l-value Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { switch (getStmtClass()) { + case ObjCIsaExprClass: case StringLiteralClass: // C99 6.5.1p4 case ObjCEncodeExprClass: // @encode behaves like its string in every way. return LV_Valid; @@ -1343,6 +1371,13 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { } } +bool Expr::isDefaultArgument() const { + const Expr *E = this; + while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) + E = ICE->getSubExprAsWritten(); + + return isa<CXXDefaultArgExpr>(E); +} /// hasAnyTypeDependentArguments - Determines if any of the expressions /// in Exprs is type-dependent. @@ -1598,13 +1633,18 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // constant expression (5.19). In that case, the member can appear // in integral constant expressions. if (Def->isOutOfLine()) { - Dcl->setInitKnownICE(Ctx, false); + Dcl->setInitKnownICE(false); + return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); + } + + if (Dcl->isCheckingICE()) { return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); } - + + Dcl->setCheckingICE(); ICEDiag Result = CheckICE(Init, Ctx); // Cache the result of the ICE test. - Dcl->setInitKnownICE(Ctx, Result.Val == 0); + Dcl->setInitKnownICE(Result.Val == 0); return Result; } } @@ -1804,7 +1844,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, } EvalResult EvalResult; if (!Evaluate(EvalResult, Ctx)) - llvm::llvm_unreachable("ICE cannot be evaluated!"); + llvm_unreachable("ICE cannot be evaluated!"); assert(!EvalResult.HasSideEffects && "ICE with side effects!"); assert(EvalResult.Val.isInt() && "ICE that isn't integer!"); Result = EvalResult.Val.getInt(); diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index d1a0390..a9f96ad 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -199,6 +199,7 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const { switch(UTT) { default: assert(false && "Unknown type trait or not implemented"); case UTT_IsPOD: return QueriedType->isPODType(); + case UTT_IsLiteral: return QueriedType->isLiteralType(); case UTT_IsClass: // Fallthrough case UTT_IsUnion: if (const RecordType *Record = QueriedType->getAs<RecordType>()) { @@ -518,7 +519,8 @@ Stmt::child_iterator CXXUnresolvedConstructExpr::child_end() { } CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, - Expr *Base, bool IsArrow, + Expr *Base, QualType BaseType, + bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, @@ -527,8 +529,8 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, SourceLocation MemberLoc, const TemplateArgumentListInfo *TemplateArgs) : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true), - Base(Base), IsArrow(IsArrow), - HasExplicitTemplateArgumentList(TemplateArgs), + Base(Base), BaseType(BaseType), IsArrow(IsArrow), + HasExplicitTemplateArgs(TemplateArgs != 0), OperatorLoc(OperatorLoc), Qualifier(Qualifier), QualifierRange(QualifierRange), FirstQualifierFoundInScope(FirstQualifierFoundInScope), @@ -539,7 +541,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, CXXDependentScopeMemberExpr * CXXDependentScopeMemberExpr::Create(ASTContext &C, - Expr *Base, bool IsArrow, + Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, @@ -548,22 +550,22 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C, SourceLocation MemberLoc, const TemplateArgumentListInfo *TemplateArgs) { if (!TemplateArgs) - return new (C) CXXDependentScopeMemberExpr(C, Base, IsArrow, OperatorLoc, - Qualifier, QualifierRange, - FirstQualifierFoundInScope, - Member, MemberLoc); + return new (C) CXXDependentScopeMemberExpr(C, Base, BaseType, + IsArrow, OperatorLoc, + Qualifier, QualifierRange, + FirstQualifierFoundInScope, + Member, MemberLoc); std::size_t size = sizeof(CXXDependentScopeMemberExpr); if (TemplateArgs) size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); void *Mem = C.Allocate(size, llvm::alignof<CXXDependentScopeMemberExpr>()); - return new (Mem) CXXDependentScopeMemberExpr(C, Base, IsArrow, OperatorLoc, - Qualifier, QualifierRange, - FirstQualifierFoundInScope, - Member, - MemberLoc, - TemplateArgs); + return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType, + IsArrow, OperatorLoc, + Qualifier, QualifierRange, + FirstQualifierFoundInScope, + Member, MemberLoc, TemplateArgs); } Stmt::child_iterator CXXDependentScopeMemberExpr::child_begin() { @@ -571,12 +573,15 @@ Stmt::child_iterator CXXDependentScopeMemberExpr::child_begin() { } Stmt::child_iterator CXXDependentScopeMemberExpr::child_end() { + if (isImplicitAccess()) + return child_iterator(&Base); return child_iterator(&Base + 1); } UnresolvedMemberExpr::UnresolvedMemberExpr(QualType T, bool Dependent, bool HasUnresolvedUsing, - Expr *Base, bool IsArrow, + Expr *Base, QualType BaseType, + bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, @@ -584,7 +589,8 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(QualType T, bool Dependent, SourceLocation MemberLoc, const TemplateArgumentListInfo *TemplateArgs) : Expr(UnresolvedMemberExprClass, T, Dependent, Dependent), - Base(Base), IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing), + Base(Base), BaseType(BaseType), IsArrow(IsArrow), + HasUnresolvedUsing(HasUnresolvedUsing), HasExplicitTemplateArgs(TemplateArgs != 0), OperatorLoc(OperatorLoc), Qualifier(Qualifier), QualifierRange(QualifierRange), @@ -596,7 +602,7 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(QualType T, bool Dependent, UnresolvedMemberExpr * UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent, bool HasUnresolvedUsing, - Expr *Base, bool IsArrow, + Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, @@ -610,8 +616,8 @@ UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent, void *Mem = C.Allocate(size, llvm::alignof<UnresolvedMemberExpr>()); return new (Mem) UnresolvedMemberExpr( Dependent ? C.DependentTy : C.OverloadTy, - Dependent, HasUnresolvedUsing, Base, IsArrow, - OperatorLoc, Qualifier, QualifierRange, + Dependent, HasUnresolvedUsing, Base, BaseType, + IsArrow, OperatorLoc, Qualifier, QualifierRange, Member, MemberLoc, TemplateArgs); } @@ -620,5 +626,7 @@ Stmt::child_iterator UnresolvedMemberExpr::child_begin() { } Stmt::child_iterator UnresolvedMemberExpr::child_end() { + if (isImplicitAccess()) + return child_iterator(&Base); return child_iterator(&Base + 1); } diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index a20e1cc..13831dc 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -848,16 +848,8 @@ static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) { bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { // Enums are integer constant exprs. - if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) { - // FIXME: This is an ugly hack around the fact that enums don't set their - // signedness consistently; see PR3173. - APSInt SI = ECD->getInitVal(); - SI.setIsUnsigned(!E->getType()->isSignedIntegerType()); - // FIXME: This is an ugly hack around the fact that enums don't - // set their width (!?!) consistently; see PR3173. - SI.extOrTrunc(Info.Ctx.getIntWidth(E->getType())); - return Success(SI, E); - } + if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) + return Success(ECD->getInitVal(), E); // In C++, const, non-volatile integers initialized with ICEs are ICEs. // In C, they can also be folded, although they are not ICEs. @@ -866,15 +858,24 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { const VarDecl *Def = 0; if (const Expr *Init = VD->getDefinition(Def)) { - if (APValue *V = VD->getEvaluatedValue()) - return Success(V->getInt(), E); - + if (APValue *V = VD->getEvaluatedValue()) { + if (V->isInt()) + return Success(V->getInt(), E); + return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + } + + if (VD->isEvaluatingValue()) + return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + + VD->setEvaluatingValue(); + if (Visit(const_cast<Expr*>(Init))) { // Cache the evaluated value in the variable declaration. - VD->setEvaluatedValue(Info.Ctx, Result); + VD->setEvaluatedValue(Result); return true; } + VD->setEvaluatedValue(APValue()); return false; } } @@ -1506,6 +1507,7 @@ public: bool VisitFloatingLiteral(const FloatingLiteral *E); bool VisitCastExpr(CastExpr *E); bool VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E); + bool VisitConditionalOperator(ConditionalOperator *E); bool VisitChooseExpr(const ChooseExpr *E) { return Visit(E->getChosenSubExpr(Info.Ctx)); } @@ -1513,8 +1515,7 @@ public: { return Visit(E->getSubExpr()); } // FIXME: Missing: __real__/__imag__, array subscript of vector, - // member of vector, ImplicitValueInitExpr, - // conditional ?: + // member of vector, ImplicitValueInitExpr }; } // end anonymous namespace @@ -1547,16 +1548,10 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { if (!S->isWide()) { const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType()); - llvm::SmallString<16> s; - s.append(S->getStrData(), S->getStrData() + S->getByteLength()); - s += '\0'; - long l; - char *endp; - l = strtol(&s[0], &endp, 0); - if (endp != s.end()-1) + unsigned Type = 0; + if (!S->getString().empty() && S->getString().getAsInteger(0, Type)) return false; - unsigned type = (unsigned int)l;; - Result = llvm::APFloat::getNaN(Sem, false, type); + Result = llvm::APFloat::getNaN(Sem, false, Type); return true; } } @@ -1673,6 +1668,14 @@ bool FloatExprEvaluator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) { return true; } +bool FloatExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) { + bool Cond; + if (!HandleConversionToBool(E->getCond(), Cond, Info)) + return false; + + return Visit(Cond ? E->getTrueExpr() : E->getFalseExpr()); +} + //===----------------------------------------------------------------------===// // Complex Evaluation (for float and integer) //===----------------------------------------------------------------------===// diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 326a1dc..c914f3f 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -663,31 +663,6 @@ void ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) { Alignment = NewAlignment; } -static const CXXMethodDecl *GetKeyFunction(const CXXRecordDecl *RD) { - if (!RD->isDynamicClass()) - return 0; - - for (CXXRecordDecl::method_iterator I = RD->method_begin(), - E = RD->method_end(); I != E; ++I) { - const CXXMethodDecl *MD = *I; - - if (!MD->isVirtual()) - continue; - - if (MD->isPure()) - continue; - - const FunctionDecl *fn; - if (MD->getBody(fn) && !fn->isOutOfLine()) - continue; - - // We found it. - return MD; - } - - return 0; -} - const ASTRecordLayout * ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, const RecordDecl *D) { @@ -711,8 +686,6 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, uint64_t NonVirtualSize = IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize; - const CXXMethodDecl *KeyFunction = GetKeyFunction(cast<CXXRecordDecl>(D)); - return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize, Builder.FieldOffsets.data(), Builder.FieldOffsets.size(), @@ -722,8 +695,7 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, Builder.Bases.data(), Builder.Bases.size(), Builder.VBases.data(), - Builder.VBases.size(), - KeyFunction); + Builder.VBases.size()); } const ASTRecordLayout * @@ -739,3 +711,51 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, Builder.FieldOffsets.data(), Builder.FieldOffsets.size()); } + +const CXXMethodDecl * +ASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) { + assert(RD->isDynamicClass() && "Class does not have any virtual methods!"); + + // If a class isnt' polymorphic it doesn't have a key function. + if (!RD->isPolymorphic()) + return 0; + + // A class template specialization or instantation does not have a key + // function. + if (RD->getTemplateSpecializationKind() != TSK_Undeclared) + return 0; + + // A class inside an anonymous namespace doesn't have a key function. (Or + // at least, there's no point to assigning a key function to such a class; + // this doesn't affect the ABI.) + if (RD->isInAnonymousNamespace()) + return 0; + + for (CXXRecordDecl::method_iterator I = RD->method_begin(), + E = RD->method_end(); I != E; ++I) { + const CXXMethodDecl *MD = *I; + + if (!MD->isVirtual()) + continue; + + if (MD->isPure()) + continue; + + if (MD->isInlineSpecified()) + continue; + + // Ignore implicit member functions, they are always marked as inline, but + // they don't have a body until they're defined. + if (MD->isImplicit()) + continue; + + if (MD->hasInlineBody()) + continue; + + // We found it. + return MD; + } + + return 0; +} + diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h index 69e0498..d4171d3 100644 --- a/lib/AST/RecordLayoutBuilder.h +++ b/lib/AST/RecordLayoutBuilder.h @@ -151,6 +151,7 @@ public: static const ASTRecordLayout *ComputeLayout(ASTContext &Ctx, const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl); + static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD); }; } // end namespace clang diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index bbe6a71..ae76526 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -17,7 +17,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/PrettyPrinter.h" #include "clang/Basic/SourceManager.h" -#include <cstdio> +#include "llvm/Support/raw_ostream.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -27,7 +27,7 @@ using namespace clang; namespace { class StmtDumper : public StmtVisitor<StmtDumper> { SourceManager *SM; - FILE *F; + llvm::raw_ostream &OS; unsigned IndentLevel; /// MaxDepth - When doing a normal dump (not dumpAll) we only want to dump @@ -41,8 +41,8 @@ namespace { unsigned LastLocLine; public: - StmtDumper(SourceManager *sm, FILE *f, unsigned maxDepth) - : SM(sm), F(f), IndentLevel(0-1), MaxDepth(maxDepth) { + StmtDumper(SourceManager *sm, llvm::raw_ostream &os, unsigned maxDepth) + : SM(sm), OS(os), IndentLevel(0-1), MaxDepth(maxDepth) { LastLocFilename = ""; LastLocLine = ~0U; } @@ -62,15 +62,15 @@ namespace { Stmt::child_iterator CI = S->child_begin(), CE = S->child_end(); if (CI != CE) { while (CI != CE) { - fprintf(F, "\n"); + OS << '\n'; DumpSubTree(*CI++); } } - fprintf(F, ")"); + OS << ')'; } } else { Indent(); - fprintf(F, "<<<NULL>>>"); + OS << "<<<NULL>>>"; } --IndentLevel; } @@ -79,27 +79,28 @@ namespace { void Indent() const { for (int i = 0, e = IndentLevel; i < e; ++i) - fprintf(F, " "); + OS << " "; } void DumpType(QualType T) { - fprintf(F, "'%s'", T.getAsString().c_str()); + OS << "'" << T.getAsString() << "'"; if (!T.isNull()) { // If the type is sugared, also dump a (shallow) desugared type. QualType Simplified = T.getDesugaredType(); if (Simplified != T) - fprintf(F, ":'%s'", Simplified.getAsString().c_str()); + OS << ":'" << Simplified.getAsString() << "'"; } } void DumpStmt(const Stmt *Node) { Indent(); - fprintf(F, "(%s %p", Node->getStmtClassName(), (void*)Node); + OS << "(" << Node->getStmtClassName() + << " " << (void*)Node; DumpSourceRange(Node); } void DumpExpr(const Expr *Node) { DumpStmt(Node); - fprintf(F, " "); + OS << ' '; DumpType(Node->getType()); } void DumpSourceRange(const Stmt *Node); @@ -138,6 +139,7 @@ namespace { void VisitCXXConstructExpr(CXXConstructExpr *Node); void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node); void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *Node); + void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node); void DumpCXXTemporary(CXXTemporary *Temporary); // ObjC @@ -161,7 +163,7 @@ void StmtDumper::DumpLocation(SourceLocation Loc) { SourceLocation SpellingLoc = SM->getSpellingLoc(Loc); if (SpellingLoc.isInvalid()) { - fprintf(stderr, "<invalid sloc>"); + OS << "<invalid sloc>"; return; } @@ -170,15 +172,16 @@ void StmtDumper::DumpLocation(SourceLocation Loc) { PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc); if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) { - fprintf(stderr, "%s:%u:%u", PLoc.getFilename(), PLoc.getLine(), - PLoc.getColumn()); + OS << PLoc.getFilename() << ':' << PLoc.getLine() + << ':' << PLoc.getColumn(); LastLocFilename = PLoc.getFilename(); LastLocLine = PLoc.getLine(); } else if (PLoc.getLine() != LastLocLine) { - fprintf(stderr, "line:%u:%u", PLoc.getLine(), PLoc.getColumn()); + OS << "line" << ':' << PLoc.getLine() + << ':' << PLoc.getColumn(); LastLocLine = PLoc.getLine(); } else { - fprintf(stderr, "col:%u", PLoc.getColumn()); + OS << "col" << ':' << PLoc.getColumn(); } } @@ -190,13 +193,13 @@ void StmtDumper::DumpSourceRange(const Stmt *Node) { // location. SourceRange R = Node->getSourceRange(); - fprintf(stderr, " <"); + OS << " <"; DumpLocation(R.getBegin()); if (R.getBegin() != R.getEnd()) { - fprintf(stderr, ", "); + OS << ", "; DumpLocation(R.getEnd()); } - fprintf(stderr, ">"); + OS << ">"; // <t2.c:123:421[blah], t2.c:412:321> @@ -215,31 +218,30 @@ void StmtDumper::DumpDeclarator(Decl *D) { // FIXME: Need to complete/beautify this... this code simply shows the // nodes are where they need to be. if (TypedefDecl *localType = dyn_cast<TypedefDecl>(D)) { - fprintf(F, "\"typedef %s %s\"", - localType->getUnderlyingType().getAsString().c_str(), - localType->getNameAsString().c_str()); + OS << "\"typedef " << localType->getUnderlyingType().getAsString() + << " " << localType->getNameAsString() << "\""; } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) { - fprintf(F, "\""); + OS << "\""; // Emit storage class for vardecls. if (VarDecl *V = dyn_cast<VarDecl>(VD)) { if (V->getStorageClass() != VarDecl::None) - fprintf(F, "%s ", - VarDecl::getStorageClassSpecifierString(V->getStorageClass())); + OS << VarDecl::getStorageClassSpecifierString(V->getStorageClass()) + << " "; } std::string Name = VD->getNameAsString(); VD->getType().getAsStringInternal(Name, PrintingPolicy(VD->getASTContext().getLangOptions())); - fprintf(F, "%s", Name.c_str()); + OS << Name; // If this is a vardecl with an initializer, emit it. if (VarDecl *V = dyn_cast<VarDecl>(VD)) { if (V->getInit()) { - fprintf(F, " =\n"); + OS << " =\n"; DumpSubTree(V->getInit()); } } - fprintf(F, "\""); + OS << '"'; } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { // print a free standing tag decl (e.g. "struct x;"). const char *tagname; @@ -247,7 +249,7 @@ void StmtDumper::DumpDeclarator(Decl *D) { tagname = II->getNameStart(); else tagname = "<anonymous>"; - fprintf(F, "\"%s %s;\"", TD->getKindName(), tagname); + OS << '"' << TD->getKindName() << ' ' << tagname << ";\""; // FIXME: print tag bodies. } else if (UsingDirectiveDecl *UD = dyn_cast<UsingDirectiveDecl>(D)) { // print using-directive decl (e.g. "using namespace x;") @@ -256,7 +258,7 @@ void StmtDumper::DumpDeclarator(Decl *D) { ns = II->getNameStart(); else ns = "<anonymous>"; - fprintf(F, "\"%s %s;\"",UD->getDeclKindName(), ns); + OS << '"' << UD->getDeclKindName() << ns << ";\""; } else { assert(0 && "Unexpected decl"); } @@ -264,28 +266,29 @@ void StmtDumper::DumpDeclarator(Decl *D) { void StmtDumper::VisitDeclStmt(DeclStmt *Node) { DumpStmt(Node); - fprintf(F,"\n"); + OS << "\n"; for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end(); DI != DE; ++DI) { Decl* D = *DI; ++IndentLevel; Indent(); - fprintf(F, "%p ", (void*) D); + OS << (void*) D << " "; DumpDeclarator(D); if (DI+1 != DE) - fprintf(F,"\n"); + OS << "\n"; --IndentLevel; } } void StmtDumper::VisitLabelStmt(LabelStmt *Node) { DumpStmt(Node); - fprintf(F, " '%s'", Node->getName()); + OS << " '" << Node->getName() << "'"; } void StmtDumper::VisitGotoStmt(GotoStmt *Node) { DumpStmt(Node); - fprintf(F, " '%s':%p", Node->getLabel()->getName(), (void*)Node->getLabel()); + OS << " '" << Node->getLabel()->getName() + << "':" << (void*)Node->getLabel(); } //===----------------------------------------------------------------------===// @@ -298,129 +301,130 @@ void StmtDumper::VisitExpr(Expr *Node) { void StmtDumper::VisitCastExpr(CastExpr *Node) { DumpExpr(Node); - fprintf(F, " <%s>", Node->getCastKindName()); + OS << " <" << Node->getCastKindName() << ">"; } void StmtDumper::VisitImplicitCastExpr(ImplicitCastExpr *Node) { VisitCastExpr(Node); if (Node->isLvalueCast()) - fprintf(F, " lvalue"); + OS << " lvalue"; } void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) { DumpExpr(Node); - fprintf(F, " "); + OS << " "; switch (Node->getDecl()->getKind()) { - default: fprintf(F,"Decl"); break; - case Decl::Function: fprintf(F,"FunctionDecl"); break; - case Decl::Var: fprintf(F,"Var"); break; - case Decl::ParmVar: fprintf(F,"ParmVar"); break; - case Decl::EnumConstant: fprintf(F,"EnumConstant"); break; - case Decl::Typedef: fprintf(F,"Typedef"); break; - case Decl::Record: fprintf(F,"Record"); break; - case Decl::Enum: fprintf(F,"Enum"); break; - case Decl::CXXRecord: fprintf(F,"CXXRecord"); break; - case Decl::ObjCInterface: fprintf(F,"ObjCInterface"); break; - case Decl::ObjCClass: fprintf(F,"ObjCClass"); break; + default: OS << "Decl"; break; + case Decl::Function: OS << "FunctionDecl"; break; + case Decl::Var: OS << "Var"; break; + case Decl::ParmVar: OS << "ParmVar"; break; + case Decl::EnumConstant: OS << "EnumConstant"; break; + case Decl::Typedef: OS << "Typedef"; break; + case Decl::Record: OS << "Record"; break; + case Decl::Enum: OS << "Enum"; break; + case Decl::CXXRecord: OS << "CXXRecord"; break; + case Decl::ObjCInterface: OS << "ObjCInterface"; break; + case Decl::ObjCClass: OS << "ObjCClass"; break; } - fprintf(F, "='%s' %p", Node->getDecl()->getNameAsString().c_str(), - (void*)Node->getDecl()); + OS << "='" << Node->getDecl()->getNameAsString() + << "' " << (void*)Node->getDecl(); +} + +void StmtDumper::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { + DumpExpr(Node); + OS << " ("; + if (!Node->requiresADL()) OS << "no "; + OS << "ADL) = '" << Node->getName().getAsString() << "'"; + + UnresolvedLookupExpr::decls_iterator + I = Node->decls_begin(), E = Node->decls_end(); + if (I == E) OS << " empty"; + for (; I != E; ++I) + OS << " " << (void*) *I; } void StmtDumper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { DumpExpr(Node); - fprintf(F, " %sDecl='%s' %p", Node->getDecl()->getDeclKindName(), - Node->getDecl()->getNameAsString().c_str(), (void*)Node->getDecl()); + OS << " " << Node->getDecl()->getDeclKindName() + << "Decl='" << Node->getDecl()->getNameAsString() + << "' " << (void*)Node->getDecl(); if (Node->isFreeIvar()) - fprintf(F, " isFreeIvar"); + OS << " isFreeIvar"; } void StmtDumper::VisitPredefinedExpr(PredefinedExpr *Node) { DumpExpr(Node); switch (Node->getIdentType()) { default: assert(0 && "unknown case"); - case PredefinedExpr::Func: fprintf(F, " __func__"); break; - case PredefinedExpr::Function: fprintf(F, " __FUNCTION__"); break; - case PredefinedExpr::PrettyFunction: fprintf(F, " __PRETTY_FUNCTION__");break; + case PredefinedExpr::Func: OS << " __func__"; break; + case PredefinedExpr::Function: OS << " __FUNCTION__"; break; + case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break; } } void StmtDumper::VisitCharacterLiteral(CharacterLiteral *Node) { DumpExpr(Node); - fprintf(F, " %d", Node->getValue()); + OS << Node->getValue(); } void StmtDumper::VisitIntegerLiteral(IntegerLiteral *Node) { DumpExpr(Node); bool isSigned = Node->getType()->isSignedIntegerType(); - fprintf(F, " %s", Node->getValue().toString(10, isSigned).c_str()); + OS << " " << Node->getValue().toString(10, isSigned); } void StmtDumper::VisitFloatingLiteral(FloatingLiteral *Node) { DumpExpr(Node); - fprintf(F, " %f", Node->getValueAsApproximateDouble()); + OS << " " << Node->getValueAsApproximateDouble(); } void StmtDumper::VisitStringLiteral(StringLiteral *Str) { DumpExpr(Str); // FIXME: this doesn't print wstrings right. - fprintf(F, " %s\"", Str->isWide() ? "L" : ""); - - for (unsigned i = 0, e = Str->getByteLength(); i != e; ++i) { - switch (char C = Str->getStrData()[i]) { - default: - if (isprint(C)) - fputc(C, F); - else - fprintf(F, "\\%03o", C); - break; - // Handle some common ones to make dumps prettier. - case '\\': fprintf(F, "\\\\"); break; - case '"': fprintf(F, "\\\""); break; - case '\n': fprintf(F, "\\n"); break; - case '\t': fprintf(F, "\\t"); break; - case '\a': fprintf(F, "\\a"); break; - case '\b': fprintf(F, "\\b"); break; - } - } - fprintf(F, "\""); + OS << " "; + if (Str->isWide()) + OS << "L"; + OS << '"'; + OS.write_escaped(llvm::StringRef(Str->getStrData(), + Str->getByteLength())); + OS << '"'; } void StmtDumper::VisitUnaryOperator(UnaryOperator *Node) { DumpExpr(Node); - fprintf(F, " %s '%s'", Node->isPostfix() ? "postfix" : "prefix", - UnaryOperator::getOpcodeStr(Node->getOpcode())); + OS << " " << (Node->isPostfix() ? "postfix" : "prefix") + << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; } void StmtDumper::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) { DumpExpr(Node); - fprintf(F, " %s ", Node->isSizeOf() ? "sizeof" : "alignof"); + OS << " " << (Node->isSizeOf() ? "sizeof" : "alignof") << " "; if (Node->isArgumentType()) DumpType(Node->getArgumentType()); } void StmtDumper::VisitMemberExpr(MemberExpr *Node) { DumpExpr(Node); - fprintf(F, " %s%s %p", Node->isArrow() ? "->" : ".", - Node->getMemberDecl()->getNameAsString().c_str(), - (void*)Node->getMemberDecl()); + OS << " " << (Node->isArrow() ? "->" : ".") + << Node->getMemberDecl()->getNameAsString() << " " + << (void*)Node->getMemberDecl(); } void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) { DumpExpr(Node); - fprintf(F, " %s", Node->getAccessor().getNameStart()); + OS << " " << Node->getAccessor().getNameStart(); } void StmtDumper::VisitBinaryOperator(BinaryOperator *Node) { DumpExpr(Node); - fprintf(F, " '%s'", BinaryOperator::getOpcodeStr(Node->getOpcode())); + OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; } void StmtDumper::VisitCompoundAssignOperator(CompoundAssignOperator *Node) { DumpExpr(Node); - fprintf(F, " '%s' ComputeLHSTy=", - BinaryOperator::getOpcodeStr(Node->getOpcode())); + OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) + << "' ComputeLHSTy="; DumpType(Node->getComputationLHSType()); - fprintf(F, " ComputeResultTy="); + OS << " ComputeResultTy="; DumpType(Node->getComputationResultType()); } @@ -428,14 +432,15 @@ void StmtDumper::VisitCompoundAssignOperator(CompoundAssignOperator *Node) { void StmtDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) { DumpExpr(Node); - fprintf(F, " %s %p", Node->getLabel()->getName(), (void*)Node->getLabel()); + OS << " " << Node->getLabel()->getName() + << " " << (void*)Node->getLabel(); } void StmtDumper::VisitTypesCompatibleExpr(TypesCompatibleExpr *Node) { DumpExpr(Node); - fprintf(F, " "); + OS << " "; DumpType(Node->getArgType1()); - fprintf(F, " "); + OS << " "; DumpType(Node->getArgType2()); } @@ -445,36 +450,35 @@ void StmtDumper::VisitTypesCompatibleExpr(TypesCompatibleExpr *Node) { void StmtDumper::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) { DumpExpr(Node); - fprintf(F, " %s<%s> <%s>", Node->getCastName(), - Node->getTypeAsWritten().getAsString().c_str(), - Node->getCastKindName()); + OS << " " << Node->getCastName() + << "<" << Node->getTypeAsWritten().getAsString() << ">" + << " <" << Node->getCastKindName() << ">"; } void StmtDumper::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) { DumpExpr(Node); - fprintf(F, " %s", Node->getValue() ? "true" : "false"); + OS << " " << (Node->getValue() ? "true" : "false"); } void StmtDumper::VisitCXXThisExpr(CXXThisExpr *Node) { DumpExpr(Node); - fprintf(F, " this"); + OS << " this"; } void StmtDumper::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) { DumpExpr(Node); - fprintf(F, " functional cast to %s", - Node->getTypeAsWritten().getAsString().c_str()); + OS << " functional cast to " << Node->getTypeAsWritten().getAsString(); } void StmtDumper::VisitCXXConstructExpr(CXXConstructExpr *Node) { DumpExpr(Node); if (Node->isElidable()) - fprintf(F, " elidable"); + OS << " elidable"; } void StmtDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) { DumpExpr(Node); - fprintf(F, " "); + OS << " "; DumpCXXTemporary(Node->getTemporary()); } @@ -482,7 +486,7 @@ void StmtDumper::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *Node) { DumpExpr(Node); ++IndentLevel; for (unsigned i = 0, e = Node->getNumTemporaries(); i != e; ++i) { - fprintf(F, "\n"); + OS << "\n"; Indent(); DumpCXXTemporary(Node->getTemporary(i)); } @@ -490,7 +494,7 @@ void StmtDumper::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *Node) { } void StmtDumper::DumpCXXTemporary(CXXTemporary *Temporary) { - fprintf(F, "(CXXTemporary %p)", (void *)Temporary); + OS << "(CXXTemporary " << (void *)Temporary << ")"; } //===----------------------------------------------------------------------===// @@ -499,37 +503,34 @@ void StmtDumper::DumpCXXTemporary(CXXTemporary *Temporary) { void StmtDumper::VisitObjCMessageExpr(ObjCMessageExpr* Node) { DumpExpr(Node); - fprintf(F, " selector=%s", Node->getSelector().getAsString().c_str()); - IdentifierInfo* clsName = Node->getClassName(); - if (clsName) fprintf(F, " class=%s", clsName->getNameStart()); + OS << " selector=" << Node->getSelector().getAsString(); + if (IdentifierInfo *clsName = Node->getClassName()) + OS << " class=" << clsName->getNameStart(); } void StmtDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { DumpExpr(Node); - - fprintf(F, " "); + OS << " "; DumpType(Node->getEncodedType()); } void StmtDumper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { DumpExpr(Node); - fprintf(F, " "); - fprintf(F, "%s", Node->getSelector().getAsString().c_str()); + OS << " " << Node->getSelector().getAsString(); } void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) { DumpExpr(Node); - fprintf(F, " "); - fprintf(F, "%s", Node->getProtocol()->getNameAsString().c_str()); + OS << " " << Node->getProtocol()->getNameAsString(); } void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) { DumpExpr(Node); - fprintf(F, " Kind=PropertyRef Property=\"%s\"", - Node->getProperty()->getNameAsString().c_str()); + OS << " Kind=PropertyRef Property=\"" + << Node->getProperty()->getNameAsString() << "\""; } void StmtDumper::VisitObjCImplicitSetterGetterRefExpr( @@ -538,14 +539,19 @@ void StmtDumper::VisitObjCImplicitSetterGetterRefExpr( ObjCMethodDecl *Getter = Node->getGetterMethod(); ObjCMethodDecl *Setter = Node->getSetterMethod(); - fprintf(F, " Kind=MethodRef Getter=\"%s\" Setter=\"%s\"", - Getter->getSelector().getAsString().c_str(), - Setter ? Setter->getSelector().getAsString().c_str() : "(null)"); + OS << " Kind=MethodRef Getter=\"" + << Getter->getSelector().getAsString() + << "\" Setter=\""; + if (Setter) + OS << Setter->getSelector().getAsString(); + else + OS << "(null)"; + OS << "\""; } void StmtDumper::VisitObjCSuperExpr(ObjCSuperExpr *Node) { DumpExpr(Node); - fprintf(F, " super"); + OS << " super"; } //===----------------------------------------------------------------------===// @@ -556,30 +562,30 @@ void StmtDumper::VisitObjCSuperExpr(ObjCSuperExpr *Node) { /// specified node and a few nodes underneath it, but not the whole subtree. /// This is useful in a debugger. void Stmt::dump(SourceManager &SM) const { - StmtDumper P(&SM, stderr, 4); + StmtDumper P(&SM, llvm::errs(), 4); P.DumpSubTree(const_cast<Stmt*>(this)); - fprintf(stderr, "\n"); + llvm::errs() << "\n"; } /// dump - This does a local dump of the specified AST fragment. It dumps the /// specified node and a few nodes underneath it, but not the whole subtree. /// This is useful in a debugger. void Stmt::dump() const { - StmtDumper P(0, stderr, 4); + StmtDumper P(0, llvm::errs(), 4); P.DumpSubTree(const_cast<Stmt*>(this)); - fprintf(stderr, "\n"); + llvm::errs() << "\n"; } /// dumpAll - This does a dump of the specified AST fragment and all subtrees. void Stmt::dumpAll(SourceManager &SM) const { - StmtDumper P(&SM, stderr, ~0U); + StmtDumper P(&SM, llvm::errs(), ~0U); P.DumpSubTree(const_cast<Stmt*>(this)); - fprintf(stderr, "\n"); + llvm::errs() << "\n"; } /// dumpAll - This does a dump of the specified AST fragment and all subtrees. void Stmt::dumpAll() const { - StmtDumper P(0, stderr, ~0U); + StmtDumper P(0, llvm::errs(), ~0U); P.DumpSubTree(const_cast<Stmt*>(this)); - fprintf(stderr, "\n"); + llvm::errs() << "\n"; } diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 205ea0d..a7e42af 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1145,17 +1145,19 @@ StmtPrinter::VisitCXXUnresolvedConstructExpr( void StmtPrinter::VisitCXXDependentScopeMemberExpr( CXXDependentScopeMemberExpr *Node) { - PrintExpr(Node->getBase()); - OS << (Node->isArrow() ? "->" : "."); + if (!Node->isImplicitAccess()) { + PrintExpr(Node->getBase()); + OS << (Node->isArrow() ? "->" : "."); + } if (NestedNameSpecifier *Qualifier = Node->getQualifier()) Qualifier->print(OS, Policy); - else if (Node->hasExplicitTemplateArgumentList()) + else if (Node->hasExplicitTemplateArgs()) // FIXME: Track use of "template" keyword explicitly? OS << "template "; OS << Node->getMember().getAsString(); - if (Node->hasExplicitTemplateArgumentList()) { + if (Node->hasExplicitTemplateArgs()) { OS << TemplateSpecializationType::PrintTemplateArgumentList( Node->getTemplateArgs(), Node->getNumTemplateArgs(), @@ -1164,8 +1166,10 @@ void StmtPrinter::VisitCXXDependentScopeMemberExpr( } void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { - PrintExpr(Node->getBase()); - OS << (Node->isArrow() ? "->" : "."); + if (!Node->isImplicitAccess()) { + PrintExpr(Node->getBase()); + OS << (Node->isArrow() ? "->" : "."); + } if (NestedNameSpecifier *Qualifier = Node->getQualifier()) Qualifier->print(OS, Policy); diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index d832a46..e2d772b 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -554,18 +554,24 @@ StmtProfiler::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *S) { void StmtProfiler::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *S) { - VisitExpr(S); - ID.AddBoolean(S->isArrow()); + ID.AddBoolean(S->isImplicitAccess()); + if (!S->isImplicitAccess()) { + VisitExpr(S); + ID.AddBoolean(S->isArrow()); + } VisitNestedNameSpecifier(S->getQualifier()); VisitName(S->getMember()); - ID.AddBoolean(S->hasExplicitTemplateArgumentList()); - if (S->hasExplicitTemplateArgumentList()) + ID.AddBoolean(S->hasExplicitTemplateArgs()); + if (S->hasExplicitTemplateArgs()) VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); } void StmtProfiler::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *S) { - VisitExpr(S); - ID.AddBoolean(S->isArrow()); + ID.AddBoolean(S->isImplicitAccess()); + if (!S->isImplicitAccess()) { + VisitExpr(S); + ID.AddBoolean(S->isArrow()); + } VisitNestedNameSpecifier(S->getQualifier()); VisitName(S->getMemberName()); ID.AddBoolean(S->hasExplicitTemplateArgs()); @@ -653,13 +659,6 @@ void StmtProfiler::VisitDecl(Decl *D) { ID.AddInteger(TTP->getIndex()); return; } - - if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) { - // The Itanium C++ ABI mangles references to a set of overloaded - // functions using just the function name, so we do the same here. - VisitName(Ovl->getDeclName()); - return; - } } ID.AddPointer(D? D->getCanonicalDecl() : 0); diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index f341b45..e9b1725 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -102,7 +102,7 @@ SourceRange TemplateArgumentLoc::getSourceRange() const { return getSourceDeclExpression()->getSourceRange(); case TemplateArgument::Type: - return getSourceDeclaratorInfo()->getTypeLoc().getFullSourceRange(); + return getTypeSourceInfo()->getTypeLoc().getFullSourceRange(); case TemplateArgument::Template: if (getTemplateQualifierRange().isValid()) diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp index 5b4cf0a..b56c0ceb 100644 --- a/lib/AST/TemplateName.cpp +++ b/lib/AST/TemplateName.cpp @@ -29,25 +29,14 @@ TemplateDecl *TemplateName::getAsTemplateDecl() const { return 0; } -OverloadedFunctionDecl *TemplateName::getAsOverloadedFunctionDecl() const { - if (OverloadedFunctionDecl *Ovl - = Storage.dyn_cast<OverloadedFunctionDecl *>()) - return Ovl; - - if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) - return QTN->getOverloadedFunctionDecl(); - - return 0; -} - bool TemplateName::isDependent() const { if (TemplateDecl *Template = getAsTemplateDecl()) { return isa<TemplateTemplateParmDecl>(Template) || Template->getDeclContext()->isDependentContext(); } - if (OverloadedFunctionDecl *Ovl = getAsOverloadedFunctionDecl()) - return Ovl->getDeclContext()->isDependentContext(); + assert(!getAsOverloadedTemplate() && + "overloaded templates shouldn't survive to here"); return true; } @@ -57,9 +46,6 @@ TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy, bool SuppressNNS) const { if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) OS << Template->getNameAsString(); - else if (OverloadedFunctionDecl *Ovl - = Storage.dyn_cast<OverloadedFunctionDecl *>()) - OS << Ovl->getNameAsString(); else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { if (!SuppressNNS) QTN->getQualifier()->print(OS, Policy); @@ -84,13 +70,3 @@ void TemplateName::dump() const { LO.Bool = true; print(llvm::errs(), PrintingPolicy(LO)); } - -TemplateDecl *QualifiedTemplateName::getTemplateDecl() const { - return dyn_cast<TemplateDecl>(Template); -} - -OverloadedFunctionDecl * -QualifiedTemplateName::getOverloadedFunctionDecl() const { - return dyn_cast<OverloadedFunctionDecl>(Template); -} - diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 5a2434d..687beae 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -434,6 +434,18 @@ bool Type::isWideCharType() const { return false; } +/// \brief Determine whether this type is any of the built-in character +/// types. +bool Type::isAnyCharacterType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + return (BT->getKind() >= BuiltinType::Char_U && + BT->getKind() <= BuiltinType::Char32) || + (BT->getKind() >= BuiltinType::Char_S && + BT->getKind() <= BuiltinType::WChar); + + return false; +} + /// isSignedIntegerType - Return true if this is an integer type that is /// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..], /// an enum decl which has a signed representation, or a vector of signed @@ -639,6 +651,40 @@ bool Type::isPODType() const { } } +bool Type::isLiteralType() const { + if (isIncompleteType()) + return false; + + // C++0x [basic.types]p10: + // A type is a literal type if it is: + switch (CanonicalType->getTypeClass()) { + // We're whitelisting + default: return false; + + // -- a scalar type + case Builtin: + case Complex: + case Pointer: + case MemberPointer: + case Vector: + case ExtVector: + case ObjCObjectPointer: + case Enum: + return true; + + // -- a class type with ... + case Record: + // FIXME: Do the tests + return false; + + // -- an array of literal type + // Extension: variable arrays cannot be literal types, since they're + // runtime-sized. + case ConstantArray: + return cast<ArrayType>(CanonicalType)->getElementType()->isLiteralType(); + } +} + bool Type::isPromotableIntegerType() const { if (const BuiltinType *BT = getAs<BuiltinType>()) switch (BT->getKind()) { diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index 50a5120..3ccb7a9 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -94,3 +94,32 @@ void TypeLoc::initializeImpl(TypeLoc TL, SourceLocation Loc) { TypeLocInitializer(Loc).Visit(TL); } while ((TL = TL.getNextTypeLoc())); } + +namespace { + struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> { + // Overload resolution does the real work for us. + static bool isTypeSpec(TypeSpecTypeLoc _) { return true; } + static bool isTypeSpec(TypeLoc _) { return false; } + +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ + return isTypeSpec(TyLoc); \ + } +#include "clang/AST/TypeLocNodes.def" + }; +} + + +/// \brief Determines if the given type loc corresponds to a +/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in +/// the type hierarchy, this is made somewhat complicated. +/// +/// There are a lot of types that currently use TypeSpecTypeLoc +/// because it's a convenient base class. Ideally we would not accept +/// those here, but ideally we would have better implementations for +/// them. +bool TypeSpecTypeLoc::classof(const TypeLoc *TL) { + if (TL->getType().hasLocalQualifiers()) return false; + return TSTChecker().Visit(*TL); +} diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 562e830..4a2b956 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -242,12 +242,13 @@ void TypePrinter::PrintDependentSizedExtVector( void TypePrinter::PrintVector(const VectorType *T, std::string &S) { // FIXME: We prefer to print the size directly here, but have no way // to get the size of the type. - S += " __attribute__((__vector_size__("; - S += llvm::utostr_32(T->getNumElements()); // convert back to bytes. + Print(T->getElementType(), S); + std::string V = "__attribute__((__vector_size__("; + V += llvm::utostr_32(T->getNumElements()); // convert back to bytes. std::string ET; Print(T->getElementType(), ET); - S += " * sizeof(" + ET + "))))"; - Print(T->getElementType(), S); + V += " * sizeof(" + ET + ")))) "; + S = V + S; } void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) { @@ -284,6 +285,23 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T, } S += ")"; + + if (T->hasExceptionSpec()) { + S += " throw("; + if (T->hasAnyExceptionSpec()) + S += "..."; + else + for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) { + if (I) + S += ", "; + + std::string ExceptionType; + Print(T->getExceptionType(I), ExceptionType); + S += ExceptionType; + } + S += ")"; + } + if (T->getNoReturnAttr()) S += " __attribute__((noreturn))"; Print(T->getResultType(), S); @@ -302,6 +320,15 @@ void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T, Print(T->getResultType(), S); } +void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T, + std::string &S) { + IdentifierInfo *II = T->getDecl()->getIdentifier(); + if (S.empty()) + S = II->getName().str(); + else + S = II->getName().str() + ' ' + S; +} + void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) { if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. S = ' ' + S; @@ -683,9 +710,8 @@ void QualType::dump(const char *msg) const { LangOptions LO; getAsStringInternal(R, PrintingPolicy(LO)); if (msg) - fprintf(stderr, "%s: %s\n", msg, R.c_str()); - else - fprintf(stderr, "%s\n", R.c_str()); + llvm::errs() << msg << ": "; + llvm::errs() << R << "\n"; } void QualType::dump() const { dump(""); |