diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST')
53 files changed, 6656 insertions, 3738 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/APValue.cpp b/contrib/llvm/tools/clang/lib/AST/APValue.cpp index 2d7c9bd..98e825b 100644 --- a/contrib/llvm/tools/clang/lib/AST/APValue.cpp +++ b/contrib/llvm/tools/clang/lib/AST/APValue.cpp @@ -19,8 +19,8 @@ #include "clang/AST/Type.h" #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/SmallString.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" using namespace clang; namespace { @@ -348,6 +348,8 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ bool IsReference = Ty->isReferenceType(); QualType InnerTy = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType(); + if (InnerTy.isNull()) + InnerTy = Ty; if (!hasLValuePath()) { // No lvalue path: just print the offset. diff --git a/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp b/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp index a4e17c0..55033b2 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTConsumer.h" -#include "clang/AST/DeclGroup.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclGroup.h" using namespace clang; bool ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) { diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index 74c68ae..7245c03 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -12,28 +12,29 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "CXXABI.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/Attr.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/Comment.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" -#include "clang/AST/TypeLoc.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExternalASTSource.h" -#include "clang/AST/ASTMutationListener.h" -#include "clang/AST/RecordLayout.h" #include "clang/AST/Mangle.h" -#include "clang/AST/Comment.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Capacity.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Capacity.h" -#include "CXXABI.h" #include <map> using namespace clang; @@ -84,6 +85,14 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { return NULL; } + if (const ClassTemplateSpecializationDecl *CTSD = + dyn_cast<ClassTemplateSpecializationDecl>(D)) { + TemplateSpecializationKind TSK = CTSD->getSpecializationKind(); + if (TSK == TSK_ImplicitInstantiation || + TSK == TSK_Undeclared) + return NULL; + } + if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) { if (ED->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) return NULL; @@ -364,10 +373,12 @@ static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod, if (!ID) return; // Add redeclared method here. - for (const ObjCCategoryDecl *ClsExtDecl = ID->getFirstClassExtension(); - ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = ID->known_extensions_begin(), + ExtEnd = ID->known_extensions_end(); + Ext != ExtEnd; ++Ext) { if (ObjCMethodDecl *RedeclaredMethod = - ClsExtDecl->getMethod(ObjCMethod->getSelector(), + Ext->getMethod(ObjCMethod->getSelector(), ObjCMethod->isInstanceMethod())) Redeclared.push_back(RedeclaredMethod); } @@ -412,15 +423,26 @@ comments::FullComment *ASTContext::getCommentForDecl( if (!RC) { if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) { SmallVector<const NamedDecl*, 8> Overridden; - if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) + const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D); + if (OMD && OMD->isPropertyAccessor()) + if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl()) + if (comments::FullComment *FC = getCommentForDecl(PDecl, PP)) + return cloneFullComment(FC, D); + if (OMD) addRedeclaredMethods(OMD, Overridden); getOverriddenMethods(dyn_cast<NamedDecl>(D), Overridden); - for (unsigned i = 0, e = Overridden.size(); i < e; i++) { - if (comments::FullComment *FC = getCommentForDecl(Overridden[i], PP)) { - comments::FullComment *CFC = cloneFullComment(FC, D); - return CFC; - } - } + for (unsigned i = 0, e = Overridden.size(); i < e; i++) + if (comments::FullComment *FC = getCommentForDecl(Overridden[i], PP)) + return cloneFullComment(FC, D); + } + else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { + // Attach any tag type's documentation to its typedef if latter + // does not have one of its own. + QualType QT = TD->getUnderlyingType(); + if (const TagType *TT = QT->getAs<TagType>()) + if (const Decl *TD = TT->getDecl()) + if (comments::FullComment *FC = getCommentForDecl(TD, PP)) + return cloneFullComment(FC, D); } return NULL; } @@ -571,12 +593,14 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { if (!LangOpts.CPlusPlus) return 0; - switch (T.getCXXABI()) { - case CXXABI_ARM: + switch (T.getCXXABI().getKind()) { + case TargetCXXABI::GenericARM: + case TargetCXXABI::iOS: return CreateARMCXXABI(*this); - case CXXABI_Itanium: + case TargetCXXABI::GenericAArch64: // Same as Itanium at this level + case TargetCXXABI::GenericItanium: return CreateItaniumCXXABI(*this); - case CXXABI_Microsoft: + case TargetCXXABI::Microsoft: return CreateMicrosoftCXXABI(*this); } llvm_unreachable("Invalid CXXABI type!"); @@ -630,9 +654,9 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, DeclarationNames(*this), ExternalSource(0), Listener(0), Comments(SM), CommentsLoaded(false), - CommentCommandTraits(BumpAlloc), + CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), LastSDM(0, 0), - UniqueBlockByRefTypeID(0) + UniqueBlockByRefTypeID(0) { if (size_reserve > 0) Types.reserve(size_reserve); TUDecl = TranslationUnitDecl::Create(*this); @@ -873,12 +897,26 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId); InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass); InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel); + + if (LangOpts.OpenCL) { + InitBuiltinType(OCLImage1dTy, BuiltinType::OCLImage1d); + InitBuiltinType(OCLImage1dArrayTy, BuiltinType::OCLImage1dArray); + InitBuiltinType(OCLImage1dBufferTy, BuiltinType::OCLImage1dBuffer); + InitBuiltinType(OCLImage2dTy, BuiltinType::OCLImage2d); + InitBuiltinType(OCLImage2dArrayTy, BuiltinType::OCLImage2dArray); + InitBuiltinType(OCLImage3dTy, BuiltinType::OCLImage3d); + + InitBuiltinType(OCLSamplerTy, BuiltinType::OCLSampler); + InitBuiltinType(OCLEventTy, BuiltinType::OCLEvent); + } // Builtin type for __objc_yes and __objc_no ObjCBuiltinBoolTy = (Target.useSignedCharForObjCBool() ? SignedCharTy : BoolTy); ObjCConstantStringType = QualType(); + + ObjCSuperType = QualType(); // void * type VoidPtrTy = getPointerType(VoidTy); @@ -1411,6 +1449,22 @@ ASTContext::getTypeInfoImpl(const Type *T) const { Width = Target->getPointerWidth(0); Align = Target->getPointerAlign(0); break; + case BuiltinType::OCLSampler: + // Samplers are modeled as integers. + Width = Target->getIntWidth(); + Align = Target->getIntAlign(); + break; + case BuiltinType::OCLEvent: + case BuiltinType::OCLImage1d: + case BuiltinType::OCLImage1dArray: + case BuiltinType::OCLImage1dBuffer: + case BuiltinType::OCLImage2d: + case BuiltinType::OCLImage2dArray: + case BuiltinType::OCLImage3d: + // Currently these types are pointers to opaque types. + Width = Target->getPointerWidth(0); + Align = Target->getPointerAlign(0); + break; } break; case Type::ObjCObjectPointer: @@ -1442,10 +1496,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: { @@ -1548,18 +1599,21 @@ ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::Atomic: { + // Start with the base type information. std::pair<uint64_t, unsigned> Info = getTypeInfo(cast<AtomicType>(T)->getValueType()); Width = Info.first; Align = Info.second; - if (Width != 0 && Width <= Target->getMaxAtomicPromoteWidth() && - llvm::isPowerOf2_64(Width)) { - // We can potentially perform lock-free atomic operations for this - // type; promote the alignment appropriately. - // FIXME: We could potentially promote the width here as well... - // is that worthwhile? (Non-struct atomic types generally have - // power-of-two size anyway, but structs might not. Requires a bit - // of implementation work to make sure we zero out the extra bits.) + + // If the size of the type doesn't exceed the platform's max + // atomic promotion width, make the size and alignment more + // favorable to atomic operations: + if (Width != 0 && Width <= Target->getMaxAtomicPromoteWidth()) { + // Round the size up to a power of 2. + if (!llvm::isPowerOf2_64(Width)) + Width = llvm::NextPowerOf2(Width); + + // Set the alignment equal to the size. Align = static_cast<unsigned>(Width); } } @@ -1658,9 +1712,13 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, } // Categories of this Interface. - for (const ObjCCategoryDecl *CDeclChain = OI->getCategoryList(); - CDeclChain; CDeclChain = CDeclChain->getNextClassCategory()) - CollectInheritedProtocols(CDeclChain, Protocols); + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = OI->visible_categories_begin(), + CatEnd = OI->visible_categories_end(); + Cat != CatEnd; ++Cat) { + CollectInheritedProtocols(*Cat, Protocols); + } + if (ObjCInterfaceDecl *SD = OI->getSuperClass()) while (SD) { CollectInheritedProtocols(SD, Protocols); @@ -1690,10 +1748,13 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const { unsigned count = 0; // Count ivars declared in class extension. - for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl; - CDecl = CDecl->getNextClassExtension()) - count += CDecl->ivar_size(); - + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = OI->known_extensions_begin(), + ExtEnd = OI->known_extensions_end(); + Ext != ExtEnd; ++Ext) { + count += Ext->ivar_size(); + } + // Count ivar defined in this class's implementation. This // includes synthesized ivars. if (ObjCImplementationDecl *ImplDecl = OI->getImplementation()) @@ -1750,12 +1811,16 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD, ObjCImpls[CatD] = ImplD; } -ObjCInterfaceDecl *ASTContext::getObjContainingInterface(NamedDecl *ND) const { - if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext())) +const ObjCInterfaceDecl *ASTContext::getObjContainingInterface( + const NamedDecl *ND) const { + if (const ObjCInterfaceDecl *ID = + dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext())) return ID; - if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ND->getDeclContext())) + if (const ObjCCategoryDecl *CD = + dyn_cast<ObjCCategoryDecl>(ND->getDeclContext())) return CD->getClassInterface(); - if (ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(ND->getDeclContext())) + if (const ObjCImplDecl *IMD = + dyn_cast<ObjCImplDecl>(ND->getDeclContext())) return IMD->getClassInterface(); return 0; @@ -1906,8 +1971,10 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, const FunctionProtoType *FPT = cast<FunctionProtoType>(T); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = Info; - Result = getFunctionType(FPT->getResultType(), FPT->arg_type_begin(), - FPT->getNumArgs(), EPI); + Result = getFunctionType(FPT->getResultType(), + ArrayRef<QualType>(FPT->arg_type_begin(), + FPT->getNumArgs()), + EPI); } return cast<FunctionType>(Result.getTypePtr()); @@ -2562,16 +2629,25 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy, return QualType(New, 0); } +/// \brief Determine whether \p T is canonical as the result type of a function. +static bool isCanonicalResultType(QualType T) { + return T.isCanonical() && + (T.getObjCLifetime() == Qualifiers::OCL_None || + T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone); +} + /// getFunctionType - Return a normal function type with a typed argument /// list. isVariadic indicates whether the argument list includes '...'. QualType -ASTContext::getFunctionType(QualType ResultTy, - const QualType *ArgArray, unsigned NumArgs, +ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, const FunctionProtoType::ExtProtoInfo &EPI) const { + size_t NumArgs = ArgArray.size(); + // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; - FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, EPI, *this); + FunctionProtoType::Profile(ID, ResultTy, ArgArray.begin(), NumArgs, EPI, + *this); void *InsertPos = 0; if (FunctionProtoType *FTP = @@ -2580,7 +2656,7 @@ ASTContext::getFunctionType(QualType ResultTy, // Determine whether the type being created is already canonical or not. bool isCanonical = - EPI.ExceptionSpecType == EST_None && ResultTy.isCanonical() && + EPI.ExceptionSpecType == EST_None && isCanonicalResultType(ResultTy) && !EPI.HasTrailingReturn; for (unsigned i = 0; i != NumArgs && isCanonical; ++i) if (!ArgArray[i].isCanonicalAsParam()) @@ -2606,9 +2682,15 @@ ASTContext::getFunctionType(QualType ResultTy, CanonicalEPI.ExtInfo = CanonicalEPI.ExtInfo.withCallingConv(getCanonicalCallConv(CallConv)); - Canonical = getFunctionType(getCanonicalType(ResultTy), - CanonicalArgs.data(), NumArgs, - CanonicalEPI); + // Result types do not have ARC lifetime qualifiers. + QualType CanResultTy = getCanonicalType(ResultTy); + if (ResultTy.getQualifiers().hasObjCLifetime()) { + Qualifiers Qs = CanResultTy.getQualifiers(); + Qs.removeObjCLifetime(); + CanResultTy = getQualifiedType(CanResultTy.getUnqualifiedType(), Qs); + } + + Canonical = getFunctionType(CanResultTy, CanonicalArgs, CanonicalEPI); // Get the new insert position for the node we care about. FunctionProtoType *NewIP = @@ -2641,7 +2723,7 @@ ASTContext::getFunctionType(QualType ResultTy, FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); FunctionProtoType::ExtProtoInfo newEPI = EPI; newEPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallConv); - new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, Canonical, newEPI); + new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI); Types.push_back(FTP); FunctionProtoTypes.InsertNode(FTP, InsertPos); return QualType(FTP, 0); @@ -2877,8 +2959,8 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name, QualType TST = getTemplateSpecializationType(Name, Args, Underlying); TypeSourceInfo *DI = CreateTypeSourceInfo(TST); - TemplateSpecializationTypeLoc TL - = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc()); + TemplateSpecializationTypeLoc TL = + DI->getTypeLoc().castAs<TemplateSpecializationTypeLoc>(); TL.setTemplateKeywordLoc(SourceLocation()); TL.setTemplateNameLoc(NameLoc); TL.setLAngleLoc(Args.getLAngleLoc()); @@ -3154,7 +3236,7 @@ ASTContext::getDependentTemplateSpecializationType( } QualType ASTContext::getPackExpansionType(QualType Pattern, - llvm::Optional<unsigned> NumExpansions) { + Optional<unsigned> NumExpansions) { llvm::FoldingSetNodeID ID; PackExpansionType::Profile(ID, Pattern, NumExpansions); @@ -3528,6 +3610,14 @@ QualType ASTContext::getUnsignedWCharType() const { return UnsignedIntTy; } +QualType ASTContext::getIntPtrType() const { + return getFromTargetType(Target->getIntPtrType()); +} + +QualType ASTContext::getUIntPtrType() const { + return getCorrespondingUnsignedType(getIntPtrType()); +} + /// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17) /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9). QualType ASTContext::getPointerDiffType() const { @@ -3993,7 +4083,8 @@ ASTContext::getConstantArrayElementCount(const ConstantArrayType *CA) const { uint64_t ElementCount = 1; do { ElementCount *= CA->getSize().getZExtValue(); - CA = dyn_cast<ConstantArrayType>(CA->getElementType()); + CA = dyn_cast_or_null<ConstantArrayType>( + CA->getElementType()->getAsArrayTypeUnsafe()); } while (CA); return ElementCount; } @@ -4032,7 +4123,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size, assert(Domain->isRealFloatingType() && "Unknown domain!"); switch (EltRank) { - case HalfRank: llvm_unreachable("Half ranks are not valid here"); + case HalfRank: return HalfTy; case FloatRank: return FloatTy; case DoubleRank: return DoubleTy; case LongDoubleRank: return LongDoubleTy; @@ -4159,8 +4250,8 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) const { // At this point, we should have a signed or unsigned integer type. if (Promotable->isSignedIntegerType()) return IntTy; - uint64_t PromotableSize = getTypeSize(Promotable); - uint64_t IntSize = getTypeSize(IntTy); + uint64_t PromotableSize = getIntWidth(Promotable); + uint64_t IntSize = getIntWidth(IntTy); assert(Promotable->isUnsignedIntegerType() && PromotableSize <= IntSize); return (PromotableSize != IntSize) ? IntTy : UnsignedIntTy; } @@ -4273,6 +4364,16 @@ QualType ASTContext::getCFConstantStringType() const { return getTagDeclType(CFConstantStringTypeDecl); } +QualType ASTContext::getObjCSuperType() const { + if (ObjCSuperType.isNull()) { + RecordDecl *ObjCSuperTypeDecl = + CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get("objc_super")); + TUDecl->addDecl(ObjCSuperTypeDecl); + ObjCSuperType = getTagDeclType(ObjCSuperTypeDecl); + } + return ObjCSuperType; +} + void ASTContext::setCFConstantStringType(QualType T) { const RecordType *Rec = T->getAs<RecordType>(); assert(Rec && "Invalid CFConstantStringType"); @@ -4361,78 +4462,68 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { return getTagDeclType(BlockDescriptorExtendedType); } -bool ASTContext::BlockRequiresCopying(QualType Ty) const { - if (Ty->isObjCRetainableType()) +/// BlockRequiresCopying - Returns true if byref variable "D" of type "Ty" +/// requires copy/dispose. Note that this must match the logic +/// in buildByrefHelpers. +bool ASTContext::BlockRequiresCopying(QualType Ty, + const VarDecl *D) { + if (const CXXRecordDecl *record = Ty->getAsCXXRecordDecl()) { + const Expr *copyExpr = getBlockVarCopyInits(D); + if (!copyExpr && record->hasTrivialDestructor()) return false; + return true; - if (getLangOpts().CPlusPlus) { - if (const RecordType *RT = Ty->getAs<RecordType>()) { - CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - return RD->hasConstCopyConstructor(); - + } + + if (!Ty->isObjCRetainableType()) return false; + + Qualifiers qs = Ty.getQualifiers(); + + // If we have lifetime, that dominates. + if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) { + assert(getLangOpts().ObjCAutoRefCount); + + switch (lifetime) { + case Qualifiers::OCL_None: llvm_unreachable("impossible"); + + // These are just bits as far as the runtime is concerned. + case Qualifiers::OCL_ExplicitNone: + case Qualifiers::OCL_Autoreleasing: + return false; + + // Tell the runtime that this is ARC __weak, called by the + // byref routines. + case Qualifiers::OCL_Weak: + // ARC __strong __block variables need to be retained. + case Qualifiers::OCL_Strong: + return true; } + llvm_unreachable("fell out of lifetime switch!"); } - return false; + return (Ty->isBlockPointerType() || isObjCNSObjectType(Ty) || + Ty->isObjCObjectPointerType()); } -QualType -ASTContext::BuildByRefType(StringRef DeclName, QualType Ty) const { - // type = struct __Block_byref_1_X { - // void *__isa; - // struct __Block_byref_1_X *__forwarding; - // unsigned int __flags; - // unsigned int __size; - // void *__copy_helper; // as needed - // void *__destroy_help // as needed - // int X; - // } * - - bool HasCopyAndDispose = BlockRequiresCopying(Ty); - - // FIXME: Move up - SmallString<36> Name; - llvm::raw_svector_ostream(Name) << "__Block_byref_" << - ++UniqueBlockByRefTypeID << '_' << DeclName; - RecordDecl *T; - T = CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get(Name.str())); - T->startDefinition(); - QualType Int32Ty = IntTy; - assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported"); - QualType FieldTypes[] = { - getPointerType(VoidPtrTy), - getPointerType(getTagDeclType(T)), - Int32Ty, - Int32Ty, - getPointerType(VoidPtrTy), - getPointerType(VoidPtrTy), - Ty - }; - - StringRef FieldNames[] = { - "__isa", - "__forwarding", - "__flags", - "__size", - "__copy_helper", - "__destroy_helper", - DeclName, - }; - - for (size_t i = 0; i < 7; ++i) { - if (!HasCopyAndDispose && i >=4 && i <= 5) - continue; - FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), - SourceLocation(), - &Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, /*Mutable=*/false, - ICIS_NoInit); - Field->setAccess(AS_public); - T->addDecl(Field); - } - - T->completeDefinition(); - - return getPointerType(getTagDeclType(T)); +bool ASTContext::getByrefLifetime(QualType Ty, + Qualifiers::ObjCLifetime &LifeTime, + bool &HasByrefExtendedLayout) const { + + if (!getLangOpts().ObjC1 || + getLangOpts().getGC() != LangOptions::NonGC) + return false; + + HasByrefExtendedLayout = false; + if (Ty->isRecordType()) { + HasByrefExtendedLayout = true; + LifeTime = Qualifiers::OCL_None; + } + else if (getLangOpts().ObjCAutoRefCount) + LifeTime = Ty.getObjCLifetime(); + // MRR. + else if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType()) + LifeTime = Qualifiers::OCL_ExplicitNone; + else + LifeTime = Qualifiers::OCL_None; + return true; } TypedefDecl *ASTContext::getObjCInstanceTypeDecl() { @@ -4793,17 +4884,19 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S, true /* outermost type */); } -static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) { - switch (T->getAs<BuiltinType>()->getKind()) { - default: llvm_unreachable("Unhandled builtin type kind"); +static char getObjCEncodingForPrimitiveKind(const ASTContext *C, + BuiltinType::Kind kind) { + switch (kind) { case BuiltinType::Void: return 'v'; case BuiltinType::Bool: return 'B'; case BuiltinType::Char_U: case BuiltinType::UChar: return 'C'; + case BuiltinType::Char16: case BuiltinType::UShort: return 'S'; + case BuiltinType::Char32: case BuiltinType::UInt: return 'I'; case BuiltinType::ULong: - return C->getIntWidth(T) == 32 ? 'L' : 'Q'; + return C->getTargetInfo().getLongWidth() == 32 ? 'L' : 'Q'; case BuiltinType::UInt128: return 'T'; case BuiltinType::ULongLong: return 'Q'; case BuiltinType::Char_S: @@ -4813,13 +4906,40 @@ static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) { case BuiltinType::WChar_U: case BuiltinType::Int: return 'i'; case BuiltinType::Long: - return C->getIntWidth(T) == 32 ? 'l' : 'q'; + return C->getTargetInfo().getLongWidth() == 32 ? 'l' : 'q'; case BuiltinType::LongLong: return 'q'; case BuiltinType::Int128: return 't'; case BuiltinType::Float: return 'f'; case BuiltinType::Double: return 'd'; case BuiltinType::LongDouble: return 'D'; + case BuiltinType::NullPtr: return '*'; // like char* + + case BuiltinType::Half: + // FIXME: potentially need @encodes for these! + return ' '; + + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + llvm_unreachable("@encoding ObjC primitive type"); + + // OpenCL and placeholder types don't need @encodings. + case BuiltinType::OCLImage1d: + case BuiltinType::OCLImage1dArray: + case BuiltinType::OCLImage1dBuffer: + case BuiltinType::OCLImage2d: + case BuiltinType::OCLImage2dArray: + case BuiltinType::OCLImage3d: + case BuiltinType::OCLEvent: + case BuiltinType::OCLSampler: + case BuiltinType::Dependent: +#define BUILTIN_TYPE(KIND, ID) +#define PLACEHOLDER_TYPE(KIND, ID) \ + case BuiltinType::KIND: +#include "clang/AST/BuiltinTypes.def" + llvm_unreachable("invalid builtin type for @encode"); } + llvm_unreachable("invalid BuiltinType::Kind value"); } static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) { @@ -4830,7 +4950,8 @@ static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) { return 'i'; // The encoding of a fixed enum type matches its fixed underlying type. - return ObjCEncodingForPrimitiveKind(C, Enum->getIntegerType()); + const BuiltinType *BT = Enum->getIntegerType()->castAs<BuiltinType>(); + return getObjCEncodingForPrimitiveKind(C, BT->getKind()); } static void EncodeBitField(const ASTContext *Ctx, std::string& S, @@ -4858,8 +4979,10 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S, S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex())); if (const EnumType *ET = T->getAs<EnumType>()) S += ObjCEncodingForEnumType(Ctx, ET); - else - S += ObjCEncodingForPrimitiveKind(Ctx, T); + else { + const BuiltinType *BT = T->castAs<BuiltinType>(); + S += getObjCEncodingForPrimitiveKind(Ctx, BT->getKind()); + } } S += llvm::utostr(FD->getBitWidthValue(*Ctx)); } @@ -4873,33 +4996,52 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, bool EncodingProperty, bool StructField, bool EncodeBlockParameters, - bool EncodeClassNames) const { - if (T->getAs<BuiltinType>()) { + bool EncodeClassNames, + bool EncodePointerToObjCTypedef) const { + CanQualType CT = getCanonicalType(T); + switch (CT->getTypeClass()) { + case Type::Builtin: + case Type::Enum: if (FD && FD->isBitField()) return EncodeBitField(this, S, T, FD); - S += ObjCEncodingForPrimitiveKind(this, T); + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CT)) + S += getObjCEncodingForPrimitiveKind(this, BT->getKind()); + else + S += ObjCEncodingForEnumType(this, cast<EnumType>(CT)); return; - } - if (const ComplexType *CT = T->getAs<ComplexType>()) { + case Type::Complex: { + const ComplexType *CT = T->castAs<ComplexType>(); S += 'j'; getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, 0, false, false); return; } - - // encoding for pointer or r3eference types. - QualType PointeeTy; - if (const PointerType *PT = T->getAs<PointerType>()) { - if (PT->isObjCSelType()) { - S += ':'; - return; - } - PointeeTy = PT->getPointeeType(); + + case Type::Atomic: { + const AtomicType *AT = T->castAs<AtomicType>(); + S += 'A'; + getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, 0, + false, false); + return; } - else if (const ReferenceType *RT = T->getAs<ReferenceType>()) - PointeeTy = RT->getPointeeType(); - if (!PointeeTy.isNull()) { + + // encoding for pointer or reference types. + case Type::Pointer: + case Type::LValueReference: + case Type::RValueReference: { + QualType PointeeTy; + if (isa<PointerType>(CT)) { + const PointerType *PT = T->castAs<PointerType>(); + if (PT->isObjCSelType()) { + S += ':'; + return; + } + PointeeTy = PT->getPointeeType(); + } else { + PointeeTy = T->castAs<ReferenceType>()->getPointeeType(); + } + bool isReadOnly = false; // For historical/compatibility reasons, the read-only qualifier of the // pointee gets emitted _before_ the '^'. The read-only qualifier of @@ -4954,10 +5096,12 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, NULL); return; } - - if (const ArrayType *AT = - // Ignore type qualifiers etc. - dyn_cast<ArrayType>(T->getCanonicalTypeInternal())) { + + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: { + const ArrayType *AT = cast<ArrayType>(CT); + if (isa<IncompleteArrayType>(AT) && !StructField) { // Incomplete arrays are encoded as a pointer to the array element. S += '^'; @@ -4986,13 +5130,13 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, return; } - if (T->getAs<FunctionType>()) { + case Type::FunctionNoProto: + case Type::FunctionProto: S += '?'; return; - } - if (const RecordType *RTy = T->getAs<RecordType>()) { - RecordDecl *RDecl = RTy->getDecl(); + case Type::Record: { + RecordDecl *RDecl = cast<RecordType>(CT)->getDecl(); S += RDecl->isUnion() ? '(' : '{'; // Anonymous structures print as '?' if (const IdentifierInfo *II = RDecl->getIdentifier()) { @@ -5000,13 +5144,11 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, if (ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(RDecl)) { const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - std::string TemplateArgsStr - = TemplateSpecializationType::PrintTemplateArgumentList( + llvm::raw_string_ostream OS(S); + TemplateSpecializationType::PrintTemplateArgumentList(OS, TemplateArgs.data(), TemplateArgs.size(), (*this).getPrintingPolicy()); - - S += TemplateArgsStr; } } else { S += '?'; @@ -5043,19 +5185,12 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += RDecl->isUnion() ? ')' : '}'; return; } - - if (const EnumType *ET = T->getAs<EnumType>()) { - if (FD && FD->isBitField()) - EncodeBitField(this, S, T, FD); - else - S += ObjCEncodingForEnumType(this, ET); - return; - } - if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) { + case Type::BlockPointer: { + const BlockPointerType *BT = T->castAs<BlockPointerType>(); S += "@?"; // Unlike a pointer-to-function, which is "^?". if (EncodeBlockParameters) { - const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>(); + const FunctionType *FT = BT->getPointeeType()->castAs<FunctionType>(); S += '<'; // Block return type @@ -5089,11 +5224,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, return; } - // Ignore protocol qualifiers when mangling at this level. - if (const ObjCObjectType *OT = T->getAs<ObjCObjectType>()) - T = OT->getBaseType(); + case Type::ObjCObject: + case Type::ObjCInterface: { + // Ignore protocol qualifiers when mangling at this level. + T = T->castAs<ObjCObjectType>()->getBaseType(); - if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) { + // The assumption seems to be that this assert will succeed + // because nested levels will have filtered out 'id' and 'Class'. + const ObjCInterfaceType *OIT = T->castAs<ObjCInterfaceType>(); // @encode(class_name) ObjCInterfaceDecl *OI = OIT->getDecl(); S += '{'; @@ -5107,13 +5245,16 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, if (Field->isBitField()) getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field); else - getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD); + getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD, + false, false, false, false, false, + EncodePointerToObjCTypedef); } S += '}'; return; } - if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) { + case Type::ObjCObjectPointer: { + const ObjCObjectPointerType *OPT = T->castAs<ObjCObjectPointerType>(); if (OPT->isObjCIdType()) { S += '@'; return; @@ -5148,14 +5289,17 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, QualType PointeeTy = OPT->getPointeeType(); if (!EncodingProperty && - isa<TypedefType>(PointeeTy.getTypePtr())) { + isa<TypedefType>(PointeeTy.getTypePtr()) && + !EncodePointerToObjCTypedef) { // Another historical/compatibility reason. // We encode the underlying type which comes out as // {...}; S += '^'; getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures, - NULL); + NULL, + false, false, false, false, false, + /*EncodePointerToObjCTypedef*/true); return; } @@ -5176,18 +5320,29 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } // gcc just blithely ignores member pointers. - // TODO: maybe there should be a mangling for these - if (T->getAs<MemberPointerType>()) + // FIXME: we shoul do better than that. 'M' is available. + case Type::MemberPointer: return; - if (T->isVectorType()) { + case Type::Vector: + case Type::ExtVector: // This matches gcc's encoding, even though technically it is // insufficient. // FIXME. We should do a better job than gcc. return; + +#define ABSTRACT_TYPE(KIND, BASE) +#define TYPE(KIND, BASE) +#define DEPENDENT_TYPE(KIND, BASE) \ + case Type::KIND: +#define NON_CANONICAL_TYPE(KIND, BASE) \ + case Type::KIND: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(KIND, BASE) \ + case Type::KIND: +#include "clang/AST/TypeNodes.def" + llvm_unreachable("@encode for dependent type!"); } - - llvm_unreachable("@encode for type not implemented!"); + llvm_unreachable("bad type kind!"); } void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, @@ -5426,6 +5581,85 @@ static TypedefDecl *CreateVoidPtrBuiltinVaListDecl(const ASTContext *Context) { return VaListTypeDecl; } +static TypedefDecl * +CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) { + RecordDecl *VaListTagDecl; + if (Context->getLangOpts().CPlusPlus) { + // namespace std { struct __va_list { + NamespaceDecl *NS; + NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context), + Context->getTranslationUnitDecl(), + /*Inline*/false, SourceLocation(), + SourceLocation(), &Context->Idents.get("std"), + /*PrevDecl*/0); + + VaListTagDecl = CXXRecordDecl::Create(*Context, TTK_Struct, + Context->getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + &Context->Idents.get("__va_list")); + VaListTagDecl->setDeclContext(NS); + } else { + // struct __va_list + VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct, + Context->getTranslationUnitDecl(), + &Context->Idents.get("__va_list")); + } + + VaListTagDecl->startDefinition(); + + const size_t NumFields = 5; + QualType FieldTypes[NumFields]; + const char *FieldNames[NumFields]; + + // void *__stack; + FieldTypes[0] = Context->getPointerType(Context->VoidTy); + FieldNames[0] = "__stack"; + + // void *__gr_top; + FieldTypes[1] = Context->getPointerType(Context->VoidTy); + FieldNames[1] = "__gr_top"; + + // void *__vr_top; + FieldTypes[2] = Context->getPointerType(Context->VoidTy); + FieldNames[2] = "__vr_top"; + + // int __gr_offs; + FieldTypes[3] = Context->IntTy; + FieldNames[3] = "__gr_offs"; + + // int __vr_offs; + FieldTypes[4] = Context->IntTy; + FieldNames[4] = "__vr_offs"; + + // 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; + + // } __builtin_va_list; + TypedefDecl *VaListTypedefDecl + = TypedefDecl::Create(const_cast<ASTContext &>(*Context), + Context->getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + &Context->Idents.get("__builtin_va_list"), + Context->getTrivialTypeSourceInfo(VaListTagType)); + + return VaListTypedefDecl; +} + static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) { // typedef struct __va_list_tag { RecordDecl *VaListTagDecl; @@ -5659,6 +5893,8 @@ static TypedefDecl *CreateVaListDecl(const ASTContext *Context, return CreateCharPtrBuiltinVaListDecl(Context); case TargetInfo::VoidPtrBuiltinVaList: return CreateVoidPtrBuiltinVaListDecl(Context); + case TargetInfo::AArch64ABIBuiltinVaList: + return CreateAArch64ABIBuiltinVaListDecl(Context); case TargetInfo::PowerABIBuiltinVaList: return CreatePowerABIBuiltinVaListDecl(Context); case TargetInfo::X86_64ABIBuiltinVaList: @@ -6496,14 +6732,14 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult()) return QualType(); - // functypes which return are preferred over those that do not. - if (lbaseInfo.getNoReturn() && !rbaseInfo.getNoReturn()) - allLTypes = false; - else if (!lbaseInfo.getNoReturn() && rbaseInfo.getNoReturn()) - allRTypes = false; // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'. bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn(); + if (lbaseInfo.getNoReturn() != NoReturn) + allLTypes = false; + if (rbaseInfo.getNoReturn() != NoReturn) + allRTypes = false; + FunctionType::ExtInfo einfo = lbaseInfo.withNoReturn(NoReturn); if (lproto && rproto) { // two C99 style function prototypes @@ -6557,7 +6793,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, FunctionProtoType::ExtProtoInfo EPI = lproto->getExtProtoInfo(); EPI.ExtInfo = einfo; - return getFunctionType(retType, types.begin(), types.size(), EPI); + return getFunctionType(retType, types, EPI); } if (lproto) allRTypes = false; @@ -6594,8 +6830,10 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, FunctionProtoType::ExtProtoInfo EPI = proto->getExtProtoInfo(); EPI.ExtInfo = einfo; - return getFunctionType(retType, proto->arg_type_begin(), - proto->getNumArgs(), EPI); + return getFunctionType(retType, + ArrayRef<QualType>(proto->arg_type_begin(), + proto->getNumArgs()), + EPI); } if (allLTypes) return lhs; @@ -6603,6 +6841,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) { @@ -6684,19 +6943,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) { @@ -6928,8 +7181,10 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = getFunctionExtInfo(LHS); QualType ResultType - = getFunctionType(OldReturnType, FPT->arg_type_begin(), - FPT->getNumArgs(), EPI); + = getFunctionType(OldReturnType, + ArrayRef<QualType>(FPT->arg_type_begin(), + FPT->getNumArgs()), + EPI); return ResultType; } } @@ -7137,6 +7392,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, case 'H': Type = Context.getObjCSelType(); break; + case 'M': + Type = Context.getObjCSuperType(); + break; case 'a': Type = Context.getBuiltinVaListType(); assert(!Type.isNull() && "builtin va list type not initialized!"); @@ -7318,7 +7576,7 @@ QualType ASTContext::GetBuiltinType(unsigned Id, EPI.ExtInfo = EI; EPI.Variadic = Variadic; - return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(), EPI); + return getFunctionType(ResType, ArgTypes, EPI); } GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) { @@ -7383,9 +7641,6 @@ GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { TSK = VD->getTemplateSpecializationKind(); Linkage L = VD->getLinkage(); - if (L == ExternalLinkage && getLangOpts().CPlusPlus && - VD->getType()->getLinkage() == UniqueExternalLinkage) - L = UniqueExternalLinkage; switch (L) { case NoLinkage: @@ -7418,7 +7673,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. @@ -7438,13 +7701,16 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>()) return true; - // The key function for a class is required. - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { - const CXXRecordDecl *RD = MD->getParent(); - if (MD->isOutOfLine() && RD->isDynamicClass()) { - const CXXMethodDecl *KeyFunc = getKeyFunction(RD); - if (KeyFunc && KeyFunc->getCanonicalDecl() == MD->getCanonicalDecl()) - return true; + // The key function for a class is required. This rule only comes + // into play when inline functions can be key functions, though. + if (getTargetInfo().getCXXABI().canKeyFunctionBeInline()) { + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { + const CXXRecordDecl *RD = MD->getParent(); + if (MD->isOutOfLine() && RD->isDynamicClass()) { + const CXXMethodDecl *KeyFunc = getCurrentKeyFunction(RD); + if (KeyFunc && KeyFunc->getCanonicalDecl() == MD->getCanonicalDecl()) + return true; + } } } @@ -7465,27 +7731,20 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly) return false; - // Structs that have non-trivial constructors or destructors are required. + // Variables that can be needed in other TUs are required. + GVALinkage L = GetGVALinkageForVariable(VD); + if (L != GVA_Internal && L != GVA_TemplateInstantiation) + return true; - // FIXME: Handle references. - // FIXME: Be more selective about which constructors we care about. - if (const RecordType *RT = VD->getType()->getAs<RecordType>()) { - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { - if (RD->hasDefinition() && !(RD->hasTrivialDefaultConstructor() && - RD->hasTrivialCopyConstructor() && - RD->hasTrivialMoveConstructor() && - RD->hasTrivialDestructor())) - return true; - } - } + // Variables that have destruction with side-effects are required. + if (VD->getType().isDestructedType()) + return true; - GVALinkage L = GetGVALinkageForVariable(VD); - if (L == GVA_Internal || L == GVA_TemplateInstantiation) { - if (!(VD->getInit() && VD->getInit()->HasSideEffects(*this))) - return false; - } + // Variables that have initialization with side-effects are required. + if (VD->getInit() && VD->getInit()->HasSideEffects(*this)) + return true; - return true; + return false; } CallingConv ASTContext::getDefaultCXXMethodCallConv(bool isVariadic) { @@ -7494,7 +7753,8 @@ CallingConv ASTContext::getDefaultCXXMethodCallConv(bool isVariadic) { } CallingConv ASTContext::getCanonicalCallConv(CallingConv CC) const { - if (CC == CC_C && !LangOpts.MRTD && getTargetInfo().getCXXABI() != CXXABI_Microsoft) + if (CC == CC_C && !LangOpts.MRTD && + getTargetInfo().getCXXABI().isMemberFunctionCCDefault()) return CC_Default; return CC; } @@ -7505,11 +7765,13 @@ bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const { } MangleContext *ASTContext::createMangleContext() { - switch (Target->getCXXABI()) { - case CXXABI_ARM: - case CXXABI_Itanium: + switch (Target->getCXXABI().getKind()) { + case TargetCXXABI::GenericAArch64: + case TargetCXXABI::GenericItanium: + case TargetCXXABI::GenericARM: + case TargetCXXABI::iOS: return createItaniumMangleContext(*this, getDiagnostics()); - case CXXABI_Microsoft: + case TargetCXXABI::Microsoft: return createMicrosoftMangleContext(*this, getDiagnostics()); } llvm_unreachable("Unsupported ABI"); @@ -7534,6 +7796,23 @@ size_t ASTContext::getSideTableAllocatedMemory() const { + llvm::capacity_in_bytes(ClassScopeSpecializationPattern); } +void ASTContext::addUnnamedTag(const TagDecl *Tag) { + // FIXME: This mangling should be applied to function local classes too + if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl() || + !isa<CXXRecordDecl>(Tag->getParent()) || Tag->getLinkage() != ExternalLinkage) + return; + + std::pair<llvm::DenseMap<const DeclContext *, unsigned>::iterator, bool> P = + UnnamedMangleContexts.insert(std::make_pair(Tag->getParent(), 0)); + UnnamedMangleNumbers.insert(std::make_pair(Tag, P.first->second++)); +} + +int ASTContext::getUnnamedTagManglingNumber(const TagDecl *Tag) const { + llvm::DenseMap<const TagDecl *, unsigned>::const_iterator I = + UnnamedMangleNumbers.find(Tag); + return I != UnnamedMangleNumbers.end() ? I->second : -1; +} + unsigned ASTContext::getLambdaManglingNumber(CXXMethodDecl *CallOperator) { CXXRecordDecl *Lambda = CallOperator->getParent(); return LambdaMangleContexts[Lambda->getDeclContext()] diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp index 0b9c524..1ed65e4 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp @@ -11,12 +11,11 @@ // //===----------------------------------------------------------------------===// #include "clang/AST/ASTDiagnostic.h" - #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/ExprCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" @@ -232,7 +231,7 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, QualType ToType, bool PrintTree, bool PrintFromType, bool ElideType, - bool ShowColors, std::string &S); + bool ShowColors, raw_ostream &OS); void clang::FormatASTNodeDiagnosticArgument( DiagnosticsEngine::ArgumentKind Kind, @@ -248,7 +247,8 @@ void clang::FormatASTNodeDiagnosticArgument( ArrayRef<intptr_t> QualTypeVals) { ASTContext &Context = *static_cast<ASTContext*>(Cookie); - std::string S; + size_t OldEnd = Output.size(); + llvm::raw_svector_ostream OS(Output); bool NeedQuotes = true; switch (Kind) { @@ -262,7 +262,7 @@ void clang::FormatASTNodeDiagnosticArgument( if (FormatTemplateTypeDiff(Context, FromType, ToType, TDT.PrintTree, TDT.PrintFromType, TDT.ElideType, - TDT.ShowColors, S)) { + TDT.ShowColors, OS)) { NeedQuotes = !TDT.PrintTree; TDT.TemplateDiffUsed = true; break; @@ -273,7 +273,7 @@ void clang::FormatASTNodeDiagnosticArgument( if (TDT.PrintTree) return; - // Attempting to do a templete diff on non-templates. Set the variables + // Attempting to do a template diff on non-templates. Set the variables // and continue with regular type printing of the appropriate type. Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType; ModLen = 0; @@ -285,23 +285,23 @@ void clang::FormatASTNodeDiagnosticArgument( "Invalid modifier for QualType argument"); QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val))); - S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs, - QualTypeVals); + OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs, + QualTypeVals); NeedQuotes = false; break; } case DiagnosticsEngine::ak_declarationname: { - DeclarationName N = DeclarationName::getFromOpaqueInteger(Val); - S = N.getAsString(); - if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0) - S = '+' + S; + OS << '+'; else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12) && ArgLen==0) - S = '-' + S; + OS << '-'; else assert(ModLen == 0 && ArgLen == 0 && "Invalid modifier for DeclarationName argument"); + + DeclarationName N = DeclarationName::getFromOpaqueInteger(Val); + N.printName(OS); break; } case DiagnosticsEngine::ak_nameddecl: { @@ -314,13 +314,12 @@ void clang::FormatASTNodeDiagnosticArgument( Qualified = false; } const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val); - ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), Qualified); + ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), Qualified); break; } case DiagnosticsEngine::ak_nestednamespec: { - llvm::raw_string_ostream OS(S); - reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS, - Context.getPrintingPolicy()); + NestedNameSpecifier *NNS = reinterpret_cast<NestedNameSpecifier*>(Val); + NNS->print(OS, Context.getPrintingPolicy()); NeedQuotes = false; break; } @@ -331,39 +330,39 @@ void clang::FormatASTNodeDiagnosticArgument( if (DC->isTranslationUnit()) { // FIXME: Get these strings from some localized place if (Context.getLangOpts().CPlusPlus) - S = "the global namespace"; + OS << "the global namespace"; else - S = "the global scope"; + OS << "the global scope"; } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) { - S = ConvertTypeToDiagnosticString(Context, - Context.getTypeDeclType(Type), - PrevArgs, NumPrevArgs, QualTypeVals); + OS << ConvertTypeToDiagnosticString(Context, + Context.getTypeDeclType(Type), + PrevArgs, NumPrevArgs, + QualTypeVals); } else { // FIXME: Get these strings from some localized place NamedDecl *ND = cast<NamedDecl>(DC); if (isa<NamespaceDecl>(ND)) - S += "namespace "; + OS << "namespace "; else if (isa<ObjCMethodDecl>(ND)) - S += "method "; + OS << "method "; else if (isa<FunctionDecl>(ND)) - S += "function "; - - S += "'"; - ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), true); - S += "'"; + OS << "function "; + + OS << '\''; + ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true); + OS << '\''; } NeedQuotes = false; break; } } - - if (NeedQuotes) - Output.push_back('\''); - - Output.append(S.begin(), S.end()); - - if (NeedQuotes) + + OS.flush(); + + if (NeedQuotes) { + Output.insert(Output.begin()+OldEnd, '\''); Output.push_back('\''); + } } /// TemplateDiff - A class that constructs a pretty string for a pair of @@ -396,21 +395,39 @@ class TemplateDiff { /// will this type be outputed. QualType ToType; - /// Str - Storage for the output stream. - llvm::SmallString<128> Str; - /// OS - The stream used to construct the output strings. - llvm::raw_svector_ostream OS; + raw_ostream &OS; /// IsBold - Keeps track of the bold formatting for the output string. bool IsBold; /// DiffTree - A tree representation the differences between two types. class DiffTree { + public: + /// DiffKind - The difference in a DiffNode and which fields are used. + enum DiffKind { + /// Incomplete or invalid node. + Invalid, + /// Another level of templates, uses TemplateDecl and Qualifiers + Template, + /// Type difference, uses QualType + Type, + /// Expression difference, uses Expr + Expression, + /// Template argument difference, uses TemplateDecl + TemplateTemplate, + /// Integer difference, uses APSInt and Expr + Integer, + /// Declaration difference, uses ValueDecl + Declaration + }; + private: /// DiffNode - The root node stores the original type. Each child node /// stores template arguments of their parents. For templated types, the /// template decl is also stored. struct DiffNode { + DiffKind Kind; + /// NextNode - The index of the next sibling node or 0. unsigned NextNode; @@ -439,6 +456,9 @@ class TemplateDiff { /// IsValidFromInt, IsValidToInt - Whether the APSInt's are valid. bool IsValidFromInt, IsValidToInt; + /// FromValueDecl, ToValueDecl - Whether the argument is a decl. + ValueDecl *FromValueDecl, *ToValueDecl; + /// FromDefault, ToDefault - Whether the argument is a default argument. bool FromDefault, ToDefault; @@ -446,13 +466,14 @@ class TemplateDiff { bool Same; DiffNode(unsigned ParentNode = 0) - : NextNode(0), ChildNode(0), ParentNode(ParentNode), + : Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode), FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0), - FromDefault(false), ToDefault(false), Same(false) { } + IsValidFromInt(false), IsValidToInt(false), FromValueDecl(0), + ToValueDecl(0), FromDefault(false), ToDefault(false), Same(false) { } }; /// FlatTree - A flattened tree used to store the DiffNodes. - llvm::SmallVector<DiffNode, 16> FlatTree; + SmallVector<DiffNode, 16> FlatTree; /// CurrentNode - The index of the current node being used. unsigned CurrentNode; @@ -504,6 +525,12 @@ class TemplateDiff { FlatTree[CurrentNode].ToQual = ToQual; } + /// SetNode - Set FromValueDecl and ToValueDecl of the current node. + void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl) { + FlatTree[CurrentNode].FromValueDecl = FromValueDecl; + FlatTree[CurrentNode].ToValueDecl = ToValueDecl; + } + /// SetSame - Sets the same flag of the current node. void SetSame(bool Same) { FlatTree[CurrentNode].Same = Same; @@ -515,6 +542,11 @@ class TemplateDiff { FlatTree[CurrentNode].ToDefault = ToDefault; } + /// SetKind - Sets the current node's type. + void SetKind(DiffKind Kind) { + FlatTree[CurrentNode].Kind = Kind; + } + /// Up - Changes the node to the parent of the current node. void Up() { CurrentNode = FlatTree[CurrentNode].ParentNode; @@ -554,39 +586,6 @@ class TemplateDiff { ReadNode = FlatTree[ReadNode].ParentNode; } - /// NodeIsTemplate - Returns true if a template decl is set, and types are - /// set. - bool NodeIsTemplate() { - return (FlatTree[ReadNode].FromTD && - !FlatTree[ReadNode].ToType.isNull()) || - (FlatTree[ReadNode].ToTD && !FlatTree[ReadNode].ToType.isNull()); - } - - /// NodeIsQualType - Returns true if a Qualtype is set. - bool NodeIsQualType() { - return !FlatTree[ReadNode].FromType.isNull() || - !FlatTree[ReadNode].ToType.isNull(); - } - - /// NodeIsExpr - Returns true if an expr is set. - bool NodeIsExpr() { - return FlatTree[ReadNode].FromExpr || FlatTree[ReadNode].ToExpr; - } - - /// NodeIsTemplateTemplate - Returns true if the argument is a template - /// template type. - bool NodeIsTemplateTemplate() { - return FlatTree[ReadNode].FromType.isNull() && - FlatTree[ReadNode].ToType.isNull() && - (FlatTree[ReadNode].FromTD || FlatTree[ReadNode].ToTD); - } - - /// NodeIsAPSInt - Returns true if the arugments are stored in APSInt's. - bool NodeIsAPSInt() { - return FlatTree[ReadNode].IsValidFromInt || - FlatTree[ReadNode].IsValidToInt; - } - /// GetNode - Gets the FromType and ToType. void GetNode(QualType &FromType, QualType &ToType) { FromType = FlatTree[ReadNode].FromType; @@ -620,6 +619,12 @@ class TemplateDiff { ToQual = FlatTree[ReadNode].ToQual; } + /// GetNode - Gets the FromValueDecl and ToValueDecl. + void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl) { + FromValueDecl = FlatTree[ReadNode].FromValueDecl; + ToValueDecl = FlatTree[ReadNode].ToValueDecl; + } + /// NodeIsSame - Returns true the arguments are the same. bool NodeIsSame() { return FlatTree[ReadNode].Same; @@ -662,9 +667,12 @@ class TemplateDiff { /// Empty - Returns true if the tree has no information. bool Empty() { - return !FlatTree[0].FromTD && !FlatTree[0].ToTD && - !FlatTree[0].FromExpr && !FlatTree[0].ToExpr && - FlatTree[0].FromType.isNull() && FlatTree[0].ToType.isNull(); + return GetKind() == Invalid; + } + + /// GetKind - Returns the current node's type. + DiffKind GetKind() { + return FlatTree[ReadNode].Kind; } }; @@ -681,6 +689,10 @@ class TemplateDiff { /// traverse over. const TemplateSpecializationType *TST; + /// DesugarTST - desugared template specialization used to extract + /// default argument information + const TemplateSpecializationType *DesugarTST; + /// Index - the index of the template argument in TST. unsigned Index; @@ -693,8 +705,10 @@ class TemplateDiff { /// TSTiterator - Constructs an iterator and sets it to the first template /// argument. - TSTiterator(const TemplateSpecializationType *TST) - : TST(TST), Index(0), CurrentTA(0), EndTA(0) { + TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST) + : TST(TST), + DesugarTST(GetTemplateSpecializationType(Context, TST->desugar())), + Index(0), CurrentTA(0), EndTA(0) { if (isEnd()) return; // Set to first template argument. If not a parameter pack, done. @@ -715,12 +729,17 @@ class TemplateDiff { /// isEnd - Returns true if the iterator is one past the end. bool isEnd() const { - return Index == TST->getNumArgs(); + return Index >= TST->getNumArgs(); } /// &operator++ - Increment the iterator to the next template argument. TSTiterator &operator++() { - assert(!isEnd() && "Iterator incremented past end of arguments."); + // After the end, Index should be the default argument position in + // DesugarTST, if it exists. + if (isEnd()) { + ++Index; + return *this; + } // If in a parameter pack, advance in the parameter pack. if (CurrentTA != EndTA) { @@ -761,6 +780,11 @@ class TemplateDiff { pointer operator->() const { return &operator*(); } + + /// getDesugar - Returns the deduced template argument from DesguarTST + reference getDesugar() const { + return DesugarTST->getArg(Index); + } }; // These functions build up the template diff tree, including functions to @@ -787,7 +811,7 @@ class TemplateDiff { TemplateName(CTSD->getSpecializedTemplate()), CTSD->getTemplateArgs().data(), CTSD->getTemplateArgs().size(), - Ty.getCanonicalType()); + Ty.getLocalUnqualifiedType().getCanonicalType()); return Ty->getAs<TemplateSpecializationType>(); } @@ -800,7 +824,7 @@ class TemplateDiff { TemplateParameterList *Params = FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters(); unsigned TotalArgs = 0; - for (TSTiterator FromIter(FromTST), ToIter(ToTST); + for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST); !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) { Tree.AddNode(); @@ -814,11 +838,12 @@ class TemplateDiff { if (TemplateTypeParmDecl *DefaultTTPD = dyn_cast<TemplateTypeParmDecl>(ParamND)) { QualType FromType, ToType; - GetType(FromIter, DefaultTTPD, FromType); - GetType(ToIter, DefaultTTPD, ToType); + FromType = GetType(FromIter, DefaultTTPD); + ToType = GetType(ToIter, DefaultTTPD); Tree.SetNode(FromType, ToType); Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(), ToIter.isEnd() && !ToType.isNull()); + Tree.SetKind(DiffTree::Type); if (!FromType.isNull() && !ToType.isNull()) { if (Context.hasSameType(FromType, ToType)) { Tree.SetSame(true); @@ -837,6 +862,7 @@ class TemplateDiff { Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(), ToArgTST->getTemplateName().getAsTemplateDecl()); Tree.SetNode(FromQual, ToQual); + Tree.SetKind(DiffTree::Template); DiffTemplate(FromArgTST, ToArgTST); } } @@ -846,41 +872,83 @@ class TemplateDiff { // Handle Expressions if (NonTypeTemplateParmDecl *DefaultNTTPD = dyn_cast<NonTypeTemplateParmDecl>(ParamND)) { - Expr *FromExpr, *ToExpr; + Expr *FromExpr = 0, *ToExpr = 0; llvm::APSInt FromInt, ToInt; + ValueDecl *FromValueDecl = 0, *ToValueDecl = 0; + unsigned ParamWidth = 128; // Safe default + if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) + ParamWidth = Context.getIntWidth(DefaultNTTPD->getType()); bool HasFromInt = !FromIter.isEnd() && FromIter->getKind() == TemplateArgument::Integral; bool HasToInt = !ToIter.isEnd() && ToIter->getKind() == TemplateArgument::Integral; - //bool IsValidFromInt = false, IsValidToInt = false; + bool HasFromValueDecl = + !FromIter.isEnd() && + FromIter->getKind() == TemplateArgument::Declaration; + bool HasToValueDecl = + !ToIter.isEnd() && + ToIter->getKind() == TemplateArgument::Declaration; + + assert(((!HasFromInt && !HasToInt) || + (!HasFromValueDecl && !HasToValueDecl)) && + "Template argument cannot be both integer and declaration"); + if (HasFromInt) FromInt = FromIter->getAsIntegral(); + else if (HasFromValueDecl) + FromValueDecl = FromIter->getAsDecl(); else - GetExpr(FromIter, DefaultNTTPD, FromExpr); + FromExpr = GetExpr(FromIter, DefaultNTTPD); if (HasToInt) ToInt = ToIter->getAsIntegral(); + else if (HasToValueDecl) + ToValueDecl = ToIter->getAsDecl(); else - GetExpr(ToIter, DefaultNTTPD, ToExpr); + ToExpr = GetExpr(ToIter, DefaultNTTPD); - if (!HasFromInt && !HasToInt) { + if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) { Tree.SetNode(FromExpr, ToExpr); - Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr)); Tree.SetDefault(FromIter.isEnd() && FromExpr, ToIter.isEnd() && ToExpr); - } else { + if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) { + if (FromExpr) + FromInt = GetInt(FromIter, FromExpr); + if (ToExpr) + ToInt = GetInt(ToIter, ToExpr); + Tree.SetNode(FromInt, ToInt, FromExpr, ToExpr); + Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); + Tree.SetKind(DiffTree::Integer); + } else { + Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr)); + Tree.SetKind(DiffTree::Expression); + } + } else if (HasFromInt || HasToInt) { if (!HasFromInt && FromExpr) { - FromInt = FromExpr->EvaluateKnownConstInt(Context); + FromInt = GetInt(FromIter, FromExpr); HasFromInt = true; } if (!HasToInt && ToExpr) { - ToInt = ToExpr->EvaluateKnownConstInt(Context); + ToInt = GetInt(ToIter, ToExpr); HasToInt = true; } Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); - Tree.SetSame(llvm::APSInt::isSameValue(FromInt, ToInt)); + Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); Tree.SetDefault(FromIter.isEnd() && HasFromInt, ToIter.isEnd() && HasToInt); + Tree.SetKind(DiffTree::Integer); + } else { + if (!HasFromValueDecl && FromExpr) + FromValueDecl = GetValueDecl(FromIter, FromExpr); + if (!HasToValueDecl && ToExpr) + ToValueDecl = GetValueDecl(ToIter, ToExpr); + Tree.SetNode(FromValueDecl, ToValueDecl); + Tree.SetSame(FromValueDecl && ToValueDecl && + FromValueDecl->getCanonicalDecl() == + ToValueDecl->getCanonicalDecl()); + Tree.SetDefault(FromIter.isEnd() && FromValueDecl, + ToIter.isEnd() && ToValueDecl); + Tree.SetKind(DiffTree::Declaration); } } @@ -888,15 +956,17 @@ class TemplateDiff { if (TemplateTemplateParmDecl *DefaultTTPD = dyn_cast<TemplateTemplateParmDecl>(ParamND)) { TemplateDecl *FromDecl, *ToDecl; - GetTemplateDecl(FromIter, DefaultTTPD, FromDecl); - GetTemplateDecl(ToIter, DefaultTTPD, ToDecl); + FromDecl = GetTemplateDecl(FromIter, DefaultTTPD); + ToDecl = GetTemplateDecl(ToIter, DefaultTTPD); Tree.SetNode(FromDecl, ToDecl); - Tree.SetSame(FromDecl && ToDecl && - FromDecl->getIdentifier() == ToDecl->getIdentifier()); + Tree.SetSame( + FromDecl && ToDecl && + FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl()); + Tree.SetKind(DiffTree::TemplateTemplate); } - if (!FromIter.isEnd()) ++FromIter; - if (!ToIter.isEnd()) ++ToIter; + ++FromIter; + ++ToIter; Tree.Up(); } } @@ -917,8 +987,8 @@ class TemplateDiff { /// even if the template arguments are not. static bool hasSameBaseTemplate(const TemplateSpecializationType *FromTST, const TemplateSpecializationType *ToTST) { - return FromTST->getTemplateName().getAsTemplateDecl()->getIdentifier() == - ToTST->getTemplateName().getAsTemplateDecl()->getIdentifier(); + return FromTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl() == + ToTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl(); } /// hasSameTemplate - Returns true if both types are specialized from the @@ -962,22 +1032,21 @@ class TemplateDiff { /// GetType - Retrieves the template type arguments, including default /// arguments. - void GetType(const TSTiterator &Iter, TemplateTypeParmDecl *DefaultTTPD, - QualType &ArgType) { - ArgType = QualType(); + QualType GetType(const TSTiterator &Iter, TemplateTypeParmDecl *DefaultTTPD) { bool isVariadic = DefaultTTPD->isParameterPack(); if (!Iter.isEnd()) - ArgType = Iter->getAsType(); - else if (!isVariadic) - ArgType = DefaultTTPD->getDefaultArgument(); + return Iter->getAsType(); + if (!isVariadic) + return DefaultTTPD->getDefaultArgument(); + + return QualType(); } /// GetExpr - Retrieves the template expression argument, including default /// arguments. - void GetExpr(const TSTiterator &Iter, NonTypeTemplateParmDecl *DefaultNTTPD, - Expr *&ArgExpr) { - ArgExpr = 0; + Expr *GetExpr(const TSTiterator &Iter, NonTypeTemplateParmDecl *DefaultNTTPD) { + Expr *ArgExpr = 0; bool isVariadic = DefaultNTTPD->isParameterPack(); if (!Iter.isEnd()) @@ -989,14 +1058,50 @@ class TemplateDiff { while (SubstNonTypeTemplateParmExpr *SNTTPE = dyn_cast<SubstNonTypeTemplateParmExpr>(ArgExpr)) ArgExpr = SNTTPE->getReplacement(); + + return ArgExpr; + } + + /// GetInt - Retrieves the template integer argument, including evaluating + /// default arguments. + llvm::APInt GetInt(const TSTiterator &Iter, Expr *ArgExpr) { + // Default, value-depenedent expressions require fetching + // from the desugared TemplateArgument + if (Iter.isEnd() && ArgExpr->isValueDependent()) + switch (Iter.getDesugar().getKind()) { + case TemplateArgument::Integral: + return Iter.getDesugar().getAsIntegral(); + case TemplateArgument::Expression: + ArgExpr = Iter.getDesugar().getAsExpr(); + return ArgExpr->EvaluateKnownConstInt(Context); + default: + assert(0 && "Unexpected template argument kind"); + } + return ArgExpr->EvaluateKnownConstInt(Context); + } + + /// GetValueDecl - Retrieves the template integer argument, including + /// default expression argument. + ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) { + // Default, value-depenedent expressions require fetching + // from the desugared TemplateArgument + if (Iter.isEnd() && ArgExpr->isValueDependent()) + switch (Iter.getDesugar().getKind()) { + case TemplateArgument::Declaration: + return Iter.getDesugar().getAsDecl(); + case TemplateArgument::Expression: + ArgExpr = Iter.getDesugar().getAsExpr(); + return cast<DeclRefExpr>(ArgExpr)->getDecl(); + default: + assert(0 && "Unexpected template argument kind"); + } + return cast<DeclRefExpr>(ArgExpr)->getDecl(); } /// GetTemplateDecl - Retrieves the template template arguments, including /// default arguments. - void GetTemplateDecl(const TSTiterator &Iter, - TemplateTemplateParmDecl *DefaultTTPD, - TemplateDecl *&ArgDecl) { - ArgDecl = 0; + TemplateDecl *GetTemplateDecl(const TSTiterator &Iter, + TemplateTemplateParmDecl *DefaultTTPD) { bool isVariadic = DefaultTTPD->isParameterPack(); TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument(); @@ -1005,13 +1110,25 @@ class TemplateDiff { DefaultTD = TA.getAsTemplate().getAsTemplateDecl(); if (!Iter.isEnd()) - ArgDecl = Iter->getAsTemplate().getAsTemplateDecl(); - else if (!isVariadic) - ArgDecl = DefaultTD; + return Iter->getAsTemplate().getAsTemplateDecl(); + if (!isVariadic) + return DefaultTD; + + return 0; + } + + /// IsSameConvertedInt - Returns true if both integers are equal when + /// converted to an integer type with the given width. + static bool IsSameConvertedInt(unsigned Width, const llvm::APSInt &X, + const llvm::APSInt &Y) { + llvm::APInt ConvertedX = X.extOrTrunc(Width); + llvm::APInt ConvertedY = Y.extOrTrunc(Width); + return ConvertedX == ConvertedY; } /// IsEqualExpr - Returns true if the expressions evaluate to the same value. - static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) { + static bool IsEqualExpr(ASTContext &Context, unsigned ParamWidth, + Expr *FromExpr, Expr *ToExpr) { if (FromExpr == ToExpr) return true; @@ -1033,7 +1150,7 @@ class TemplateDiff { Expr::EvalResult FromResult, ToResult; if (!FromExpr->EvaluateAsRValue(FromResult, Context) || !ToExpr->EvaluateAsRValue(ToResult, Context)) - assert(0 && "Template arguments must be known at compile time."); + return false; APValue &FromVal = FromResult.Val; APValue &ToVal = ToResult.Val; @@ -1042,7 +1159,7 @@ class TemplateDiff { switch (FromVal.getKind()) { case APValue::Int: - return FromVal.getInt() == ToVal.getInt(); + return IsSameConvertedInt(ParamWidth, FromVal.getInt(), ToVal.getInt()); case APValue::LValue: { APValue::LValueBase FromBase = FromVal.getLValueBase(); APValue::LValueBase ToBase = ToVal.getLValueBase(); @@ -1068,81 +1185,97 @@ class TemplateDiff { void TreeToString(int Indent = 1) { if (PrintTree) { OS << '\n'; - for (int i = 0; i < Indent; ++i) - OS << " "; + OS.indent(2 * Indent); ++Indent; } // Handle cases where the difference is not templates with different // arguments. - if (!Tree.NodeIsTemplate()) { - if (Tree.NodeIsQualType()) { + switch (Tree.GetKind()) { + case DiffTree::Invalid: + llvm_unreachable("Template diffing failed with bad DiffNode"); + case DiffTree::Type: { QualType FromType, ToType; Tree.GetNode(FromType, ToType); PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); return; } - if (Tree.NodeIsExpr()) { + case DiffTree::Expression: { Expr *FromExpr, *ToExpr; Tree.GetNode(FromExpr, ToExpr); PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); return; } - if (Tree.NodeIsTemplateTemplate()) { + case DiffTree::TemplateTemplate: { TemplateDecl *FromTD, *ToTD; Tree.GetNode(FromTD, ToTD); PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); return; } - - if (Tree.NodeIsAPSInt()) { + case DiffTree::Integer: { llvm::APSInt FromInt, ToInt; + Expr *FromExpr, *ToExpr; bool IsValidFromInt, IsValidToInt; + Tree.GetNode(FromExpr, ToExpr); Tree.GetNode(FromInt, ToInt, IsValidFromInt, IsValidToInt); PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, - Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); + FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(), + Tree.NodeIsSame()); return; } - llvm_unreachable("Unable to deduce template difference."); - } - - // Node is root of template. Recurse on children. - TemplateDecl *FromTD, *ToTD; - Tree.GetNode(FromTD, ToTD); - - assert(Tree.HasChildren() && "Template difference not found in diff tree."); - - Qualifiers FromQual, ToQual; - Tree.GetNode(FromQual, ToQual); - PrintQualifiers(FromQual, ToQual); + case DiffTree::Declaration: { + ValueDecl *FromValueDecl, *ToValueDecl; + Tree.GetNode(FromValueDecl, ToValueDecl); + PrintValueDecl(FromValueDecl, ToValueDecl, Tree.FromDefault(), + Tree.ToDefault(), Tree.NodeIsSame()); + return; + } + case DiffTree::Template: { + // Node is root of template. Recurse on children. + TemplateDecl *FromTD, *ToTD; + Tree.GetNode(FromTD, ToTD); - OS << FromTD->getNameAsString() << '<'; - Tree.MoveToChild(); - unsigned NumElideArgs = 0; - do { - if (ElideType) { - if (Tree.NodeIsSame()) { - ++NumElideArgs; - continue; + if (!Tree.HasChildren()) { + // If we're dealing with a template specialization with zero + // arguments, there are no children; special-case this. + OS << FromTD->getNameAsString() << "<>"; + return; } - if (NumElideArgs > 0) { + + Qualifiers FromQual, ToQual; + Tree.GetNode(FromQual, ToQual); + PrintQualifiers(FromQual, ToQual); + + OS << FromTD->getNameAsString() << '<'; + Tree.MoveToChild(); + unsigned NumElideArgs = 0; + do { + if (ElideType) { + if (Tree.NodeIsSame()) { + ++NumElideArgs; + continue; + } + if (NumElideArgs > 0) { + PrintElideArgs(NumElideArgs, Indent); + NumElideArgs = 0; + OS << ", "; + } + } + TreeToString(Indent); + if (Tree.HasNextSibling()) + OS << ", "; + } while (Tree.AdvanceSibling()); + if (NumElideArgs > 0) PrintElideArgs(NumElideArgs, Indent); - NumElideArgs = 0; - OS << ", "; - } + + Tree.Parent(); + OS << ">"; + return; } - TreeToString(Indent); - if (Tree.HasNextSibling()) - OS << ", "; - } while (Tree.AdvanceSibling()); - if (NumElideArgs > 0) - PrintElideArgs(NumElideArgs, Indent); - - Tree.Parent(); - OS << ">"; + } } // To signal to the text printer that a certain text needs to be bolded, @@ -1260,21 +1393,29 @@ class TemplateDiff { void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD, bool FromDefault, bool ToDefault, bool Same) { assert((FromTD || ToTD) && "Only one template argument may be missing."); + + std::string FromName = FromTD ? FromTD->getName() : "(no argument)"; + std::string ToName = ToTD ? ToTD->getName() : "(no argument)"; + if (FromTD && ToTD && FromName == ToName) { + FromName = FromTD->getQualifiedNameAsString(); + ToName = ToTD->getQualifiedNameAsString(); + } + if (Same) { OS << "template " << FromTD->getNameAsString(); } else if (!PrintTree) { OS << (FromDefault ? "(default) template " : "template "); Bold(); - OS << (FromTD ? FromTD->getNameAsString() : "(no argument)"); + OS << FromName; Unbold(); } else { OS << (FromDefault ? "[(default) template " : "[template "); Bold(); - OS << (FromTD ? FromTD->getNameAsString() : "(no argument)"); + OS << FromName; Unbold(); OS << " != " << (ToDefault ? "(default) template " : "template "); Bold(); - OS << (ToTD ? ToTD->getNameAsString() : "(no argument)"); + OS << ToName; Unbold(); OS << ']'; } @@ -1283,8 +1424,8 @@ class TemplateDiff { /// PrintAPSInt - Handles printing of integral arguments, highlighting /// argument differences. void PrintAPSInt(llvm::APSInt FromInt, llvm::APSInt ToInt, - bool IsValidFromInt, bool IsValidToInt, bool FromDefault, - bool ToDefault, bool Same) { + bool IsValidFromInt, bool IsValidToInt, Expr *FromExpr, + Expr *ToExpr, bool FromDefault, bool ToDefault, bool Same) { assert((IsValidFromInt || IsValidToInt) && "Only one integral argument may be missing."); @@ -1292,20 +1433,74 @@ class TemplateDiff { OS << FromInt.toString(10); } else if (!PrintTree) { OS << (FromDefault ? "(default) " : ""); + PrintAPSInt(FromInt, FromExpr, IsValidFromInt); + } else { + OS << (FromDefault ? "[(default) " : "["); + PrintAPSInt(FromInt, FromExpr, IsValidFromInt); + OS << " != " << (ToDefault ? "(default) " : ""); + PrintAPSInt(ToInt, ToExpr, IsValidToInt); + OS << ']'; + } + } + + /// PrintAPSInt - If valid, print the APSInt. If the expression is + /// gives more information, print it too. + void PrintAPSInt(llvm::APSInt Val, Expr *E, bool Valid) { + Bold(); + if (Valid) { + if (HasExtraInfo(E)) { + PrintExpr(E); + Unbold(); + OS << " aka "; + Bold(); + } + OS << Val.toString(10); + } else { + OS << "(no argument)"; + } + Unbold(); + } + + /// HasExtraInfo - Returns true if E is not an integer literal or the + /// negation of an integer literal + bool HasExtraInfo(Expr *E) { + if (!E) return false; + if (isa<IntegerLiteral>(E)) return false; + + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) + if (UO->getOpcode() == UO_Minus) + if (isa<IntegerLiteral>(UO->getSubExpr())) + return false; + + return true; + } + + /// PrintDecl - Handles printing of Decl arguments, highlighting + /// argument differences. + void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, + bool FromDefault, bool ToDefault, bool Same) { + assert((FromValueDecl || ToValueDecl) && + "Only one Decl argument may be NULL"); + + if (Same) { + OS << FromValueDecl->getName(); + } else if (!PrintTree) { + OS << (FromDefault ? "(default) " : ""); Bold(); - OS << (IsValidFromInt ? FromInt.toString(10) : "(no argument)"); + OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); Unbold(); } else { OS << (FromDefault ? "[(default) " : "["); Bold(); - OS << (IsValidFromInt ? FromInt.toString(10) : "(no argument)"); + OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); Unbold(); OS << " != " << (ToDefault ? "(default) " : ""); Bold(); - OS << (IsValidToInt ? ToInt.toString(10) : "(no argument)"); + OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)"); Unbold(); OS << ']'; } + } // Prints the appropriate placeholder for elided template arguments. @@ -1386,9 +1581,9 @@ class TemplateDiff { public: - TemplateDiff(ASTContext &Context, QualType FromType, QualType ToType, - bool PrintTree, bool PrintFromType, bool ElideType, - bool ShowColor) + TemplateDiff(raw_ostream &OS, ASTContext &Context, QualType FromType, + QualType ToType, bool PrintTree, bool PrintFromType, + bool ElideType, bool ShowColor) : Context(Context), Policy(Context.getLangOpts()), ElideType(ElideType), @@ -1397,7 +1592,7 @@ public: // When printing a single type, the FromType is the one printed. FromType(PrintFromType ? FromType : ToType), ToType(PrintFromType ? ToType : FromType), - OS(Str), + OS(OS), IsBold(false) { } @@ -1424,6 +1619,7 @@ public: ToQual -= QualType(ToOrigTST, 0).getQualifiers(); Tree.SetNode(FromType, ToType); Tree.SetNode(FromQual, ToQual); + Tree.SetKind(DiffTree::Template); // Same base template, but different arguments. Tree.SetNode(FromOrigTST->getTemplateName().getAsTemplateDecl(), @@ -1432,17 +1628,16 @@ public: DiffTemplate(FromOrigTST, ToOrigTST); } - /// MakeString - When the two types given are templated types with the same + /// Emit - When the two types given are templated types with the same /// base template, a string representation of the type difference will be - /// loaded into S and return true. Otherwise, return false. - bool MakeString(std::string &S) { + /// emitted to the stream and return true. Otherwise, return false. + bool Emit() { Tree.StartTraverse(); if (Tree.Empty()) return false; TreeToString(); assert(!IsBold && "Bold is applied to end of string."); - S = OS.str(); return true; } }; // end class TemplateDiff @@ -1454,11 +1649,11 @@ public: static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, QualType ToType, bool PrintTree, bool PrintFromType, bool ElideType, - bool ShowColors, std::string &S) { + bool ShowColors, raw_ostream &OS) { if (PrintTree) PrintFromType = true; - TemplateDiff TD(Context, FromType, ToType, PrintTree, PrintFromType, + TemplateDiff TD(OS, Context, FromType, ToType, PrintTree, PrintFromType, ElideType, ShowColors); TD.DiffTemplate(); - return TD.MakeString(S); + return TD.Emit(); } diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp new file mode 100644 index 0000000..b1d174b --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp @@ -0,0 +1,1996 @@ +//===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the AST dump methods, which dump out the +// AST in a form that exposes type details and other fields. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" +#include "clang/AST/CommentVisitor.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/Basic/Module.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/Support/raw_ostream.h" +using namespace clang; +using namespace clang::comments; + +//===----------------------------------------------------------------------===// +// ASTDumper Visitor +//===----------------------------------------------------------------------===// + +namespace { + // Colors used for various parts of the AST dump + + struct TerminalColor { + raw_ostream::Colors Color; + bool Bold; + }; + + // Decl kind names (VarDecl, FunctionDecl, etc) + static const TerminalColor DeclKindNameColor = { raw_ostream::GREEN, true }; + // Attr names (CleanupAttr, GuardedByAttr, etc) + static const TerminalColor AttrColor = { raw_ostream::BLUE, true }; + // Statement names (DeclStmt, ImplicitCastExpr, etc) + static const TerminalColor StmtColor = { raw_ostream::MAGENTA, true }; + // Comment names (FullComment, ParagraphComment, TextComment, etc) + static const TerminalColor CommentColor = { raw_ostream::YELLOW, true }; + + // Type names (int, float, etc, plus user defined types) + static const TerminalColor TypeColor = { raw_ostream::GREEN, false }; + + // Pointer address + static const TerminalColor AddressColor = { raw_ostream::YELLOW, false }; + // Source locations + static const TerminalColor LocationColor = { raw_ostream::YELLOW, false }; + + // lvalue/xvalue + static const TerminalColor ValueKindColor = { raw_ostream::CYAN, false }; + // bitfield/objcproperty/objcsubscript/vectorcomponent + static const TerminalColor ObjectKindColor = { raw_ostream::CYAN, false }; + + // Null statements + static const TerminalColor NullColor = { raw_ostream::BLUE, false }; + + // CastKind from CastExpr's + static const TerminalColor CastColor = { raw_ostream::RED, false }; + + // Value of the statement + static const TerminalColor ValueColor = { raw_ostream::CYAN, true }; + // Decl names + static const TerminalColor DeclNameColor = { raw_ostream::CYAN, true }; + + // Indents ( `, -. | ) + static const TerminalColor IndentColor = { raw_ostream::BLUE, false }; + + class ASTDumper + : public ConstDeclVisitor<ASTDumper>, public ConstStmtVisitor<ASTDumper>, + public ConstCommentVisitor<ASTDumper> { + raw_ostream &OS; + const CommandTraits *Traits; + const SourceManager *SM; + bool IsFirstLine; + + // Indicates whether more child are expected at the current tree depth + enum IndentType { IT_Child, IT_LastChild }; + + /// Indents[i] indicates if another child exists at level i. + /// Used by Indent() to print the tree structure. + llvm::SmallVector<IndentType, 32> Indents; + + /// Indicates that more children will be needed at this indent level. + /// If true, prevents lastChild() from marking the node as the last child. + /// This is used when there are multiple collections of children to be + /// dumped as well as during conditional node dumping. + bool MoreChildren; + + /// Keep track of the last location we print out so that we can + /// print out deltas from then on out. + const char *LastLocFilename; + unsigned LastLocLine; + + /// The \c FullComment parent of the comment being dumped. + const FullComment *FC; + + bool ShowColors; + + class IndentScope { + ASTDumper &Dumper; + // Preserve the Dumper's MoreChildren value from the previous IndentScope + bool MoreChildren; + public: + IndentScope(ASTDumper &Dumper) : Dumper(Dumper) { + MoreChildren = Dumper.hasMoreChildren(); + Dumper.setMoreChildren(false); + Dumper.indent(); + } + ~IndentScope() { + Dumper.setMoreChildren(MoreChildren); + Dumper.unindent(); + } + }; + + class ColorScope { + ASTDumper &Dumper; + public: + ColorScope(ASTDumper &Dumper, TerminalColor Color) + : Dumper(Dumper) { + if (Dumper.ShowColors) + Dumper.OS.changeColor(Color.Color, Color.Bold); + } + ~ColorScope() { + if (Dumper.ShowColors) + Dumper.OS.resetColor(); + } + }; + + public: + ASTDumper(raw_ostream &OS, const CommandTraits *Traits, + const SourceManager *SM) + : OS(OS), Traits(Traits), SM(SM), IsFirstLine(true), MoreChildren(false), + LastLocFilename(""), LastLocLine(~0U), FC(0), + ShowColors(SM && SM->getDiagnostics().getShowColors()) { } + + ASTDumper(raw_ostream &OS, const CommandTraits *Traits, + const SourceManager *SM, bool ShowColors) + : OS(OS), Traits(Traits), SM(SM), IsFirstLine(true), MoreChildren(false), + LastLocFilename(""), LastLocLine(~0U), + ShowColors(ShowColors) { } + + ~ASTDumper() { + OS << "\n"; + } + + void dumpDecl(const Decl *D); + void dumpStmt(const Stmt *S); + void dumpFullComment(const FullComment *C); + + // Formatting + void indent(); + void unindent(); + void lastChild(); + bool hasMoreChildren(); + void setMoreChildren(bool Value); + + // Utilities + void dumpPointer(const void *Ptr); + void dumpSourceRange(SourceRange R); + void dumpLocation(SourceLocation Loc); + void dumpBareType(QualType T); + void dumpType(QualType T); + void dumpBareDeclRef(const Decl *Node); + void dumpDeclRef(const Decl *Node, const char *Label = 0); + void dumpName(const NamedDecl *D); + bool hasNodes(const DeclContext *DC); + void dumpDeclContext(const DeclContext *DC); + void dumpAttr(const Attr *A); + + // C++ Utilities + void dumpAccessSpecifier(AccessSpecifier AS); + void dumpCXXCtorInitializer(const CXXCtorInitializer *Init); + void dumpTemplateParameters(const TemplateParameterList *TPL); + void dumpTemplateArgumentListInfo(const TemplateArgumentListInfo &TALI); + void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A); + void dumpTemplateArgumentList(const TemplateArgumentList &TAL); + void dumpTemplateArgument(const TemplateArgument &A, + SourceRange R = SourceRange()); + + // Decls + void VisitLabelDecl(const LabelDecl *D); + void VisitTypedefDecl(const TypedefDecl *D); + void VisitEnumDecl(const EnumDecl *D); + void VisitRecordDecl(const RecordDecl *D); + void VisitEnumConstantDecl(const EnumConstantDecl *D); + void VisitIndirectFieldDecl(const IndirectFieldDecl *D); + void VisitFunctionDecl(const FunctionDecl *D); + void VisitFieldDecl(const FieldDecl *D); + void VisitVarDecl(const VarDecl *D); + void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D); + void VisitImportDecl(const ImportDecl *D); + + // C++ Decls + void VisitNamespaceDecl(const NamespaceDecl *D); + void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D); + void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D); + void VisitTypeAliasDecl(const TypeAliasDecl *D); + void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D); + void VisitCXXRecordDecl(const CXXRecordDecl *D); + void VisitStaticAssertDecl(const StaticAssertDecl *D); + void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); + void VisitClassTemplateDecl(const ClassTemplateDecl *D); + void VisitClassTemplateSpecializationDecl( + const ClassTemplateSpecializationDecl *D); + void VisitClassTemplatePartialSpecializationDecl( + const ClassTemplatePartialSpecializationDecl *D); + void VisitClassScopeFunctionSpecializationDecl( + const ClassScopeFunctionSpecializationDecl *D); + void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); + void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); + void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); + void VisitUsingDecl(const UsingDecl *D); + void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D); + void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D); + void VisitUsingShadowDecl(const UsingShadowDecl *D); + void VisitLinkageSpecDecl(const LinkageSpecDecl *D); + void VisitAccessSpecDecl(const AccessSpecDecl *D); + void VisitFriendDecl(const FriendDecl *D); + + // ObjC Decls + void VisitObjCIvarDecl(const ObjCIvarDecl *D); + void VisitObjCMethodDecl(const ObjCMethodDecl *D); + void VisitObjCCategoryDecl(const ObjCCategoryDecl *D); + void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D); + void VisitObjCProtocolDecl(const ObjCProtocolDecl *D); + void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D); + void VisitObjCImplementationDecl(const ObjCImplementationDecl *D); + void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D); + void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); + void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); + void VisitBlockDecl(const BlockDecl *D); + + // Stmts. + void VisitStmt(const Stmt *Node); + void VisitDeclStmt(const DeclStmt *Node); + void VisitAttributedStmt(const AttributedStmt *Node); + void VisitLabelStmt(const LabelStmt *Node); + void VisitGotoStmt(const GotoStmt *Node); + + // Exprs + void VisitExpr(const Expr *Node); + void VisitCastExpr(const CastExpr *Node); + void VisitDeclRefExpr(const DeclRefExpr *Node); + void VisitPredefinedExpr(const PredefinedExpr *Node); + void VisitCharacterLiteral(const CharacterLiteral *Node); + void VisitIntegerLiteral(const IntegerLiteral *Node); + void VisitFloatingLiteral(const FloatingLiteral *Node); + void VisitStringLiteral(const StringLiteral *Str); + void VisitUnaryOperator(const UnaryOperator *Node); + void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node); + void VisitMemberExpr(const MemberExpr *Node); + void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node); + void VisitBinaryOperator(const BinaryOperator *Node); + void VisitCompoundAssignOperator(const CompoundAssignOperator *Node); + void VisitAddrLabelExpr(const AddrLabelExpr *Node); + void VisitBlockExpr(const BlockExpr *Node); + void VisitOpaqueValueExpr(const OpaqueValueExpr *Node); + + // C++ + void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node); + void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node); + void VisitCXXThisExpr(const CXXThisExpr *Node); + void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node); + void VisitCXXConstructExpr(const CXXConstructExpr *Node); + void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node); + void VisitExprWithCleanups(const ExprWithCleanups *Node); + void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node); + void dumpCXXTemporary(const CXXTemporary *Temporary); + + // ObjC + void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node); + void VisitObjCEncodeExpr(const ObjCEncodeExpr *Node); + void VisitObjCMessageExpr(const ObjCMessageExpr *Node); + void VisitObjCBoxedExpr(const ObjCBoxedExpr *Node); + void VisitObjCSelectorExpr(const ObjCSelectorExpr *Node); + void VisitObjCProtocolExpr(const ObjCProtocolExpr *Node); + void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node); + void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node); + void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node); + void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node); + + // Comments. + const char *getCommandName(unsigned CommandID); + void dumpComment(const Comment *C); + + // Inline comments. + void visitTextComment(const TextComment *C); + void visitInlineCommandComment(const InlineCommandComment *C); + void visitHTMLStartTagComment(const HTMLStartTagComment *C); + void visitHTMLEndTagComment(const HTMLEndTagComment *C); + + // Block comments. + void visitBlockCommandComment(const BlockCommandComment *C); + void visitParamCommandComment(const ParamCommandComment *C); + void visitTParamCommandComment(const TParamCommandComment *C); + void visitVerbatimBlockComment(const VerbatimBlockComment *C); + void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C); + void visitVerbatimLineComment(const VerbatimLineComment *C); + }; +} + +//===----------------------------------------------------------------------===// +// Utilities +//===----------------------------------------------------------------------===// + +// Print out the appropriate tree structure using the Indents vector. +// Example of tree and the Indents vector at each level. +// A { } +// |-B { IT_Child } +// | `-C { IT_Child, IT_LastChild } +// `-D { IT_LastChild } +// |-E { IT_LastChild, IT_Child } +// `-F { IT_LastChild, IT_LastChild } +// Type non-last element, last element +// IT_Child "| " "|-" +// IT_LastChild " " "`-" +void ASTDumper::indent() { + if (IsFirstLine) + IsFirstLine = false; + else + OS << "\n"; + + ColorScope Color(*this, IndentColor); + for (llvm::SmallVector<IndentType, 32>::const_iterator I = Indents.begin(), + E = Indents.end(); + I != E; ++I) { + switch (*I) { + case IT_Child: + if (I == E - 1) + OS << "|-"; + else + OS << "| "; + continue; + case IT_LastChild: + if (I == E - 1) + OS << "`-"; + else + OS << " "; + continue; + } + llvm_unreachable("Invalid IndentType"); + } + Indents.push_back(IT_Child); +} + +void ASTDumper::unindent() { + Indents.pop_back(); +} + +// Call before each potential last child node is to be dumped. If MoreChildren +// is false, then this is the last child, otherwise treat as a regular node. +void ASTDumper::lastChild() { + if (!hasMoreChildren()) + Indents.back() = IT_LastChild; +} + +// MoreChildren should be set before calling another function that may print +// additional nodes to prevent conflicting final child nodes. +bool ASTDumper::hasMoreChildren() { + return MoreChildren; +} + +void ASTDumper::setMoreChildren(bool Value) { + MoreChildren = Value; +} + +void ASTDumper::dumpPointer(const void *Ptr) { + ColorScope Color(*this, AddressColor); + OS << ' ' << Ptr; +} + +void ASTDumper::dumpLocation(SourceLocation Loc) { + ColorScope Color(*this, LocationColor); + SourceLocation SpellingLoc = SM->getSpellingLoc(Loc); + + // The general format we print out is filename:line:col, but we drop pieces + // that haven't changed since the last loc printed. + PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc); + + if (PLoc.isInvalid()) { + OS << "<invalid sloc>"; + return; + } + + if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) { + OS << PLoc.getFilename() << ':' << PLoc.getLine() + << ':' << PLoc.getColumn(); + LastLocFilename = PLoc.getFilename(); + LastLocLine = PLoc.getLine(); + } else if (PLoc.getLine() != LastLocLine) { + OS << "line" << ':' << PLoc.getLine() + << ':' << PLoc.getColumn(); + LastLocLine = PLoc.getLine(); + } else { + OS << "col" << ':' << PLoc.getColumn(); + } +} + +void ASTDumper::dumpSourceRange(SourceRange R) { + // Can't translate locations if a SourceManager isn't available. + if (!SM) + return; + + OS << " <"; + dumpLocation(R.getBegin()); + if (R.getBegin() != R.getEnd()) { + OS << ", "; + dumpLocation(R.getEnd()); + } + OS << ">"; + + // <t2.c:123:421[blah], t2.c:412:321> + +} + +void ASTDumper::dumpBareType(QualType T) { + ColorScope Color(*this, TypeColor); + + SplitQualType T_split = T.split(); + OS << "'" << QualType::getAsString(T_split) << "'"; + + if (!T.isNull()) { + // If the type is sugared, also dump a (shallow) desugared type. + SplitQualType D_split = T.getSplitDesugaredType(); + if (T_split != D_split) + OS << ":'" << QualType::getAsString(D_split) << "'"; + } +} + +void ASTDumper::dumpType(QualType T) { + OS << ' '; + dumpBareType(T); +} + +void ASTDumper::dumpBareDeclRef(const Decl *D) { + { + ColorScope Color(*this, DeclKindNameColor); + OS << D->getDeclKindName(); + } + dumpPointer(D); + + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { + ColorScope Color(*this, DeclNameColor); + OS << " '"; + ND->getDeclName().printName(OS); + OS << "'"; + } + + if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) + dumpType(VD->getType()); +} + +void ASTDumper::dumpDeclRef(const Decl *D, const char *Label) { + if (!D) + return; + + IndentScope Indent(*this); + if (Label) + OS << Label << ' '; + dumpBareDeclRef(D); +} + +void ASTDumper::dumpName(const NamedDecl *ND) { + if (ND->getDeclName()) { + ColorScope Color(*this, DeclNameColor); + OS << ' ' << ND->getNameAsString(); + } +} + +bool ASTDumper::hasNodes(const DeclContext *DC) { + if (!DC) + return false; + + return DC->decls_begin() != DC->decls_end(); +} + +void ASTDumper::dumpDeclContext(const DeclContext *DC) { + if (!DC) + return; + for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end(); + I != E; ++I) { + DeclContext::decl_iterator Next = I; + ++Next; + if (Next == E) + lastChild(); + dumpDecl(*I); + } +} + +void ASTDumper::dumpAttr(const Attr *A) { + IndentScope Indent(*this); + { + ColorScope Color(*this, AttrColor); + switch (A->getKind()) { +#define ATTR(X) case attr::X: OS << #X; break; +#include "clang/Basic/AttrList.inc" + default: llvm_unreachable("unexpected attribute kind"); + } + OS << "Attr"; + } + dumpPointer(A); + dumpSourceRange(A->getRange()); +#include "clang/AST/AttrDump.inc" +} + +static Decl *getPreviousDeclImpl(...) { + return 0; +} + +template<typename T> +static const Decl *getPreviousDeclImpl(const Redeclarable<T> *D) { + return D->getPreviousDecl(); +} + +/// Get the previous declaration in the redeclaration chain for a declaration. +static const Decl *getPreviousDecl(const Decl *D) { + switch (D->getKind()) { +#define DECL(DERIVED, BASE) \ + case Decl::DERIVED: \ + return getPreviousDeclImpl(cast<DERIVED##Decl>(D)); +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" + } + llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); +} + +//===----------------------------------------------------------------------===// +// C++ Utilities +//===----------------------------------------------------------------------===// + +void ASTDumper::dumpAccessSpecifier(AccessSpecifier AS) { + switch (AS) { + case AS_none: + break; + case AS_public: + OS << "public"; + break; + case AS_protected: + OS << "protected"; + break; + case AS_private: + OS << "private"; + break; + } +} + +void ASTDumper::dumpCXXCtorInitializer(const CXXCtorInitializer *Init) { + IndentScope Indent(*this); + OS << "CXXCtorInitializer"; + if (Init->isAnyMemberInitializer()) { + OS << ' '; + dumpBareDeclRef(Init->getAnyMember()); + } else { + dumpType(QualType(Init->getBaseClass(), 0)); + } + dumpStmt(Init->getInit()); +} + +void ASTDumper::dumpTemplateParameters(const TemplateParameterList *TPL) { + if (!TPL) + return; + + for (TemplateParameterList::const_iterator I = TPL->begin(), E = TPL->end(); + I != E; ++I) + dumpDecl(*I); +} + +void ASTDumper::dumpTemplateArgumentListInfo( + const TemplateArgumentListInfo &TALI) { + for (unsigned i = 0, e = TALI.size(); i < e; ++i) { + if (i + 1 == e) + lastChild(); + dumpTemplateArgumentLoc(TALI[i]); + } +} + +void ASTDumper::dumpTemplateArgumentLoc(const TemplateArgumentLoc &A) { + dumpTemplateArgument(A.getArgument(), A.getSourceRange()); +} + +void ASTDumper::dumpTemplateArgumentList(const TemplateArgumentList &TAL) { + for (unsigned i = 0, e = TAL.size(); i < e; ++i) + dumpTemplateArgument(TAL[i]); +} + +void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) { + IndentScope Indent(*this); + OS << "TemplateArgument"; + if (R.isValid()) + dumpSourceRange(R); + + switch (A.getKind()) { + case TemplateArgument::Null: + OS << " null"; + break; + case TemplateArgument::Type: + OS << " type"; + lastChild(); + dumpType(A.getAsType()); + break; + case TemplateArgument::Declaration: + OS << " decl"; + lastChild(); + dumpDeclRef(A.getAsDecl()); + break; + case TemplateArgument::NullPtr: + OS << " nullptr"; + break; + case TemplateArgument::Integral: + OS << " integral " << A.getAsIntegral(); + break; + case TemplateArgument::Template: + OS << " template "; + A.getAsTemplate().dump(OS); + break; + case TemplateArgument::TemplateExpansion: + OS << " template expansion"; + A.getAsTemplateOrTemplatePattern().dump(OS); + break; + case TemplateArgument::Expression: + OS << " expr"; + lastChild(); + dumpStmt(A.getAsExpr()); + break; + case TemplateArgument::Pack: + OS << " pack"; + for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpTemplateArgument(*I); + } + break; + } +} + +//===----------------------------------------------------------------------===// +// Decl dumping methods. +//===----------------------------------------------------------------------===// + +void ASTDumper::dumpDecl(const Decl *D) { + IndentScope Indent(*this); + + if (!D) { + ColorScope Color(*this, NullColor); + OS << "<<<NULL>>>"; + return; + } + + { + ColorScope Color(*this, DeclKindNameColor); + OS << D->getDeclKindName() << "Decl"; + } + dumpPointer(D); + if (D->getLexicalDeclContext() != D->getDeclContext()) + OS << " parent " << cast<Decl>(D->getDeclContext()); + if (const Decl *Prev = getPreviousDecl(D)) + OS << " prev " << Prev; + dumpSourceRange(D->getSourceRange()); + + bool HasAttrs = D->attr_begin() != D->attr_end(); + bool HasComment = D->getASTContext().getCommentForDecl(D, 0); + // Decls within functions are visited by the body + bool HasDeclContext = !isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D) && + hasNodes(dyn_cast<DeclContext>(D)); + + setMoreChildren(HasAttrs || HasComment || HasDeclContext); + ConstDeclVisitor<ASTDumper>::Visit(D); + + setMoreChildren(HasComment || HasDeclContext); + for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpAttr(*I); + } + + setMoreChildren(HasDeclContext); + lastChild(); + dumpFullComment(D->getASTContext().getCommentForDecl(D, 0)); + + setMoreChildren(false); + if (HasDeclContext) + dumpDeclContext(cast<DeclContext>(D)); +} + +void ASTDumper::VisitLabelDecl(const LabelDecl *D) { + dumpName(D); +} + +void ASTDumper::VisitTypedefDecl(const TypedefDecl *D) { + dumpName(D); + dumpType(D->getUnderlyingType()); + if (D->isModulePrivate()) + OS << " __module_private__"; +} + +void ASTDumper::VisitEnumDecl(const EnumDecl *D) { + if (D->isScoped()) { + if (D->isScopedUsingClassTag()) + OS << " class"; + else + OS << " struct"; + } + dumpName(D); + if (D->isModulePrivate()) + OS << " __module_private__"; + if (D->isFixed()) + dumpType(D->getIntegerType()); +} + +void ASTDumper::VisitRecordDecl(const RecordDecl *D) { + OS << ' ' << D->getKindName(); + dumpName(D); + if (D->isModulePrivate()) + OS << " __module_private__"; +} + +void ASTDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) { + dumpName(D); + dumpType(D->getType()); + if (const Expr *Init = D->getInitExpr()) { + lastChild(); + dumpStmt(Init); + } +} + +void ASTDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) { + dumpName(D); + dumpType(D->getType()); + for (IndirectFieldDecl::chain_iterator I = D->chain_begin(), + E = D->chain_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDeclRef(*I); + } +} + +void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { + dumpName(D); + dumpType(D->getType()); + + StorageClass SC = D->getStorageClass(); + if (SC != SC_None) + OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); + if (D->isInlineSpecified()) + OS << " inline"; + if (D->isVirtualAsWritten()) + OS << " virtual"; + if (D->isModulePrivate()) + OS << " __module_private__"; + + if (D->isPure()) + OS << " pure"; + else if (D->isDeletedAsWritten()) + OS << " delete"; + + bool OldMoreChildren = hasMoreChildren(); + const FunctionTemplateSpecializationInfo *FTSI = + D->getTemplateSpecializationInfo(); + bool HasTemplateSpecialization = FTSI; + + bool HasNamedDecls = D->getDeclsInPrototypeScope().begin() != + D->getDeclsInPrototypeScope().end(); + + bool HasFunctionDecls = D->param_begin() != D->param_end(); + + const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D); + bool HasCtorInitializers = C && C->init_begin() != C->init_end(); + + bool HasDeclarationBody = D->doesThisDeclarationHaveABody(); + + setMoreChildren(OldMoreChildren || HasNamedDecls || HasFunctionDecls || + HasCtorInitializers || HasDeclarationBody); + if (HasTemplateSpecialization) { + lastChild(); + dumpTemplateArgumentList(*FTSI->TemplateArguments); + } + + setMoreChildren(OldMoreChildren || HasFunctionDecls || + HasCtorInitializers || HasDeclarationBody); + for (ArrayRef<NamedDecl *>::iterator + I = D->getDeclsInPrototypeScope().begin(), + E = D->getDeclsInPrototypeScope().end(); I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDecl(*I); + } + + setMoreChildren(OldMoreChildren || HasCtorInitializers || HasDeclarationBody); + for (FunctionDecl::param_const_iterator I = D->param_begin(), + E = D->param_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDecl(*I); + } + + setMoreChildren(OldMoreChildren || HasDeclarationBody); + if (HasCtorInitializers) + for (CXXConstructorDecl::init_const_iterator I = C->init_begin(), + E = C->init_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpCXXCtorInitializer(*I); + } + + setMoreChildren(OldMoreChildren); + if (HasDeclarationBody) { + lastChild(); + dumpStmt(D->getBody()); + } +} + +void ASTDumper::VisitFieldDecl(const FieldDecl *D) { + dumpName(D); + dumpType(D->getType()); + if (D->isMutable()) + OS << " mutable"; + if (D->isModulePrivate()) + OS << " __module_private__"; + + bool OldMoreChildren = hasMoreChildren(); + bool IsBitField = D->isBitField(); + Expr *Init = D->getInClassInitializer(); + bool HasInit = Init; + + setMoreChildren(OldMoreChildren || HasInit); + if (IsBitField) { + lastChild(); + dumpStmt(D->getBitWidth()); + } + setMoreChildren(OldMoreChildren); + if (HasInit) { + lastChild(); + dumpStmt(Init); + } +} + +void ASTDumper::VisitVarDecl(const VarDecl *D) { + dumpName(D); + dumpType(D->getType()); + StorageClass SC = D->getStorageClass(); + if (SC != SC_None) + OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); + if (D->isThreadSpecified()) + OS << " __thread"; + if (D->isModulePrivate()) + OS << " __module_private__"; + if (D->isNRVOVariable()) + OS << " nrvo"; + if (D->hasInit()) { + lastChild(); + dumpStmt(D->getInit()); + } +} + +void ASTDumper::VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) { + lastChild(); + dumpStmt(D->getAsmString()); +} + +void ASTDumper::VisitImportDecl(const ImportDecl *D) { + OS << ' ' << D->getImportedModule()->getFullModuleName(); +} + +//===----------------------------------------------------------------------===// +// C++ Declarations +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitNamespaceDecl(const NamespaceDecl *D) { + dumpName(D); + if (D->isInline()) + OS << " inline"; + if (!D->isOriginalNamespace()) + dumpDeclRef(D->getOriginalNamespace(), "original"); +} + +void ASTDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { + OS << ' '; + dumpBareDeclRef(D->getNominatedNamespace()); +} + +void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { + dumpName(D); + dumpDeclRef(D->getAliasedNamespace()); +} + +void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) { + dumpName(D); + dumpType(D->getUnderlyingType()); +} + +void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); + dumpDecl(D->getTemplatedDecl()); +} + +void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { + VisitRecordDecl(D); + if (!D->isCompleteDefinition()) + return; + + for (CXXRecordDecl::base_class_const_iterator I = D->bases_begin(), + E = D->bases_end(); + I != E; ++I) { + IndentScope Indent(*this); + if (I->isVirtual()) + OS << "virtual "; + dumpAccessSpecifier(I->getAccessSpecifier()); + dumpType(I->getType()); + if (I->isPackExpansion()) + OS << "..."; + } +} + +void ASTDumper::VisitStaticAssertDecl(const StaticAssertDecl *D) { + dumpStmt(D->getAssertExpr()); + lastChild(); + dumpStmt(D->getMessage()); +} + +void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); + dumpDecl(D->getTemplatedDecl()); + for (FunctionTemplateDecl::spec_iterator I = D->spec_begin(), + E = D->spec_end(); + I != E; ++I) { + FunctionTemplateDecl::spec_iterator Next = I; + ++Next; + if (Next == E) + lastChild(); + switch (I->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + if (D == D->getCanonicalDecl()) + dumpDecl(*I); + else + dumpDeclRef(*I); + break; + case TSK_ExplicitSpecialization: + dumpDeclRef(*I); + break; + } + } +} + +void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) { + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); + + ClassTemplateDecl::spec_iterator I = D->spec_begin(); + ClassTemplateDecl::spec_iterator E = D->spec_end(); + if (I == E) + lastChild(); + dumpDecl(D->getTemplatedDecl()); + for (; I != E; ++I) { + ClassTemplateDecl::spec_iterator Next = I; + ++Next; + if (Next == E) + lastChild(); + switch (I->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + if (D == D->getCanonicalDecl()) + dumpDecl(*I); + else + dumpDeclRef(*I); + break; + case TSK_ExplicitSpecialization: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + dumpDeclRef(*I); + break; + } + } +} + +void ASTDumper::VisitClassTemplateSpecializationDecl( + const ClassTemplateSpecializationDecl *D) { + VisitCXXRecordDecl(D); + dumpTemplateArgumentList(D->getTemplateArgs()); +} + +void ASTDumper::VisitClassTemplatePartialSpecializationDecl( + const ClassTemplatePartialSpecializationDecl *D) { + VisitClassTemplateSpecializationDecl(D); + dumpTemplateParameters(D->getTemplateParameters()); +} + +void ASTDumper::VisitClassScopeFunctionSpecializationDecl( + const ClassScopeFunctionSpecializationDecl *D) { + dumpDeclRef(D->getSpecialization()); + if (D->hasExplicitTemplateArgs()) + dumpTemplateArgumentListInfo(D->templateArgs()); +} + +void ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { + if (D->wasDeclaredWithTypename()) + OS << " typename"; + else + OS << " class"; + if (D->isParameterPack()) + OS << " ..."; + dumpName(D); + if (D->hasDefaultArgument()) + dumpType(D->getDefaultArgument()); +} + +void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { + dumpType(D->getType()); + if (D->isParameterPack()) + OS << " ..."; + dumpName(D); + if (D->hasDefaultArgument()) + dumpStmt(D->getDefaultArgument()); +} + +void ASTDumper::VisitTemplateTemplateParmDecl( + const TemplateTemplateParmDecl *D) { + if (D->isParameterPack()) + OS << " ..."; + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); + if (D->hasDefaultArgument()) + dumpTemplateArgumentLoc(D->getDefaultArgument()); +} + +void ASTDumper::VisitUsingDecl(const UsingDecl *D) { + OS << ' '; + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + OS << D->getNameAsString(); +} + +void ASTDumper::VisitUnresolvedUsingTypenameDecl( + const UnresolvedUsingTypenameDecl *D) { + OS << ' '; + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + OS << D->getNameAsString(); +} + +void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { + OS << ' '; + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + OS << D->getNameAsString(); + dumpType(D->getType()); +} + +void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) { + OS << ' '; + dumpBareDeclRef(D->getTargetDecl()); +} + +void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) { + switch (D->getLanguage()) { + case LinkageSpecDecl::lang_c: OS << " C"; break; + case LinkageSpecDecl::lang_cxx: OS << " C++"; break; + } +} + +void ASTDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) { + OS << ' '; + dumpAccessSpecifier(D->getAccess()); +} + +void ASTDumper::VisitFriendDecl(const FriendDecl *D) { + lastChild(); + if (TypeSourceInfo *T = D->getFriendType()) + dumpType(T->getType()); + else + dumpDecl(D->getFriendDecl()); +} + +//===----------------------------------------------------------------------===// +// Obj-C Declarations +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) { + dumpName(D); + dumpType(D->getType()); + if (D->getSynthesize()) + OS << " synthesize"; + + switch (D->getAccessControl()) { + case ObjCIvarDecl::None: + OS << " none"; + break; + case ObjCIvarDecl::Private: + OS << " private"; + break; + case ObjCIvarDecl::Protected: + OS << " protected"; + break; + case ObjCIvarDecl::Public: + OS << " public"; + break; + case ObjCIvarDecl::Package: + OS << " package"; + break; + } +} + +void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) { + if (D->isInstanceMethod()) + OS << " -"; + else + OS << " +"; + dumpName(D); + dumpType(D->getResultType()); + + bool OldMoreChildren = hasMoreChildren(); + bool IsVariadic = D->isVariadic(); + bool HasBody = D->hasBody(); + + setMoreChildren(OldMoreChildren || IsVariadic || HasBody); + if (D->isThisDeclarationADefinition()) { + lastChild(); + dumpDeclContext(D); + } else { + for (ObjCMethodDecl::param_const_iterator I = D->param_begin(), + E = D->param_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDecl(*I); + } + } + + setMoreChildren(OldMoreChildren || HasBody); + if (IsVariadic) { + lastChild(); + IndentScope Indent(*this); + OS << "..."; + } + + setMoreChildren(OldMoreChildren); + if (HasBody) { + lastChild(); + dumpStmt(D->getBody()); + } +} + +void ASTDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { + dumpName(D); + dumpDeclRef(D->getClassInterface()); + if (D->protocol_begin() == D->protocol_end()) + lastChild(); + dumpDeclRef(D->getImplementation()); + for (ObjCCategoryDecl::protocol_iterator I = D->protocol_begin(), + E = D->protocol_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDeclRef(*I); + } +} + +void ASTDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { + dumpName(D); + dumpDeclRef(D->getClassInterface()); + lastChild(); + dumpDeclRef(D->getCategoryDecl()); +} + +void ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { + dumpName(D); + for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(), + E = D->protocol_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDeclRef(*I); + } +} + +void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { + dumpName(D); + dumpDeclRef(D->getSuperClass(), "super"); + if (D->protocol_begin() == D->protocol_end()) + lastChild(); + dumpDeclRef(D->getImplementation()); + for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(), + E = D->protocol_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDeclRef(*I); + } +} + +void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { + dumpName(D); + dumpDeclRef(D->getSuperClass(), "super"); + if (D->init_begin() == D->init_end()) + lastChild(); + dumpDeclRef(D->getClassInterface()); + for (ObjCImplementationDecl::init_const_iterator I = D->init_begin(), + E = D->init_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpCXXCtorInitializer(*I); + } +} + +void ASTDumper::VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D) { + dumpName(D); + lastChild(); + dumpDeclRef(D->getClassInterface()); +} + +void ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { + dumpName(D); + dumpType(D->getType()); + + if (D->getPropertyImplementation() == ObjCPropertyDecl::Required) + OS << " required"; + else if (D->getPropertyImplementation() == ObjCPropertyDecl::Optional) + OS << " optional"; + + ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes(); + if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) { + if (Attrs & ObjCPropertyDecl::OBJC_PR_readonly) + OS << " readonly"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_assign) + OS << " assign"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_readwrite) + OS << " readwrite"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_retain) + OS << " retain"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_copy) + OS << " copy"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic) + OS << " nonatomic"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_atomic) + OS << " atomic"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_weak) + OS << " weak"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_strong) + OS << " strong"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) + OS << " unsafe_unretained"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) { + if (!(Attrs & ObjCPropertyDecl::OBJC_PR_setter)) + lastChild(); + dumpDeclRef(D->getGetterMethodDecl(), "getter"); + } + if (Attrs & ObjCPropertyDecl::OBJC_PR_setter) { + lastChild(); + dumpDeclRef(D->getSetterMethodDecl(), "setter"); + } + } +} + +void ASTDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { + dumpName(D->getPropertyDecl()); + if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) + OS << " synthesize"; + else + OS << " dynamic"; + dumpDeclRef(D->getPropertyDecl()); + lastChild(); + dumpDeclRef(D->getPropertyIvarDecl()); +} + +void ASTDumper::VisitBlockDecl(const BlockDecl *D) { + for (BlockDecl::param_const_iterator I = D->param_begin(), E = D->param_end(); + I != E; ++I) + dumpDecl(*I); + + if (D->isVariadic()) { + IndentScope Indent(*this); + OS << "..."; + } + + if (D->capturesCXXThis()) { + IndentScope Indent(*this); + OS << "capture this"; + } + for (BlockDecl::capture_iterator I = D->capture_begin(), E = D->capture_end(); + I != E; ++I) { + IndentScope Indent(*this); + OS << "capture"; + if (I->isByRef()) + OS << " byref"; + if (I->isNested()) + OS << " nested"; + if (I->getVariable()) { + OS << ' '; + dumpBareDeclRef(I->getVariable()); + } + if (I->hasCopyExpr()) + dumpStmt(I->getCopyExpr()); + } + lastChild(); + dumpStmt(D->getBody()); +} + +//===----------------------------------------------------------------------===// +// Stmt dumping methods. +//===----------------------------------------------------------------------===// + +void ASTDumper::dumpStmt(const Stmt *S) { + IndentScope Indent(*this); + + if (!S) { + ColorScope Color(*this, NullColor); + OS << "<<<NULL>>>"; + return; + } + + if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) { + VisitDeclStmt(DS); + return; + } + + setMoreChildren(S->children()); + ConstStmtVisitor<ASTDumper>::Visit(S); + setMoreChildren(false); + for (Stmt::const_child_range CI = S->children(); CI; ++CI) { + Stmt::const_child_range Next = CI; + ++Next; + if (!Next) + lastChild(); + dumpStmt(*CI); + } +} + +void ASTDumper::VisitStmt(const Stmt *Node) { + { + ColorScope Color(*this, StmtColor); + OS << Node->getStmtClassName(); + } + dumpPointer(Node); + dumpSourceRange(Node->getSourceRange()); +} + +void ASTDumper::VisitDeclStmt(const DeclStmt *Node) { + VisitStmt(Node); + for (DeclStmt::const_decl_iterator I = Node->decl_begin(), + E = Node->decl_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDecl(*I); + } +} + +void ASTDumper::VisitAttributedStmt(const AttributedStmt *Node) { + VisitStmt(Node); + for (ArrayRef<const Attr *>::iterator I = Node->getAttrs().begin(), + E = Node->getAttrs().end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpAttr(*I); + } +} + +void ASTDumper::VisitLabelStmt(const LabelStmt *Node) { + VisitStmt(Node); + OS << " '" << Node->getName() << "'"; +} + +void ASTDumper::VisitGotoStmt(const GotoStmt *Node) { + VisitStmt(Node); + OS << " '" << Node->getLabel()->getName() << "'"; + dumpPointer(Node->getLabel()); +} + +//===----------------------------------------------------------------------===// +// Expr dumping methods. +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitExpr(const Expr *Node) { + VisitStmt(Node); + dumpType(Node->getType()); + + { + ColorScope Color(*this, ValueKindColor); + switch (Node->getValueKind()) { + case VK_RValue: + break; + case VK_LValue: + OS << " lvalue"; + break; + case VK_XValue: + OS << " xvalue"; + break; + } + } + + { + ColorScope Color(*this, ObjectKindColor); + switch (Node->getObjectKind()) { + case OK_Ordinary: + break; + case OK_BitField: + OS << " bitfield"; + break; + case OK_ObjCProperty: + OS << " objcproperty"; + break; + case OK_ObjCSubscript: + OS << " objcsubscript"; + break; + case OK_VectorComponent: + OS << " vectorcomponent"; + break; + } + } +} + +static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) { + if (Node->path_empty()) + return; + + OS << " ("; + bool First = true; + for (CastExpr::path_const_iterator I = Node->path_begin(), + E = Node->path_end(); + I != E; ++I) { + const CXXBaseSpecifier *Base = *I; + if (!First) + OS << " -> "; + + const CXXRecordDecl *RD = + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + + if (Base->isVirtual()) + OS << "virtual "; + OS << RD->getName(); + First = false; + } + + OS << ')'; +} + +void ASTDumper::VisitCastExpr(const CastExpr *Node) { + VisitExpr(Node); + OS << " <"; + { + ColorScope Color(*this, CastColor); + OS << Node->getCastKindName(); + } + dumpBasePath(OS, Node); + OS << ">"; +} + +void ASTDumper::VisitDeclRefExpr(const DeclRefExpr *Node) { + VisitExpr(Node); + + OS << " "; + dumpBareDeclRef(Node->getDecl()); + if (Node->getDecl() != Node->getFoundDecl()) { + OS << " ("; + dumpBareDeclRef(Node->getFoundDecl()); + OS << ")"; + } +} + +void ASTDumper::VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node) { + VisitExpr(Node); + OS << " ("; + if (!Node->requiresADL()) + OS << "no "; + OS << "ADL) = '" << Node->getName() << '\''; + + UnresolvedLookupExpr::decls_iterator + I = Node->decls_begin(), E = Node->decls_end(); + if (I == E) + OS << " empty"; + for (; I != E; ++I) + dumpPointer(*I); +} + +void ASTDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) { + VisitExpr(Node); + + { + ColorScope Color(*this, DeclKindNameColor); + OS << " " << Node->getDecl()->getDeclKindName() << "Decl"; + } + OS << "='" << *Node->getDecl() << "'"; + dumpPointer(Node->getDecl()); + if (Node->isFreeIvar()) + OS << " isFreeIvar"; +} + +void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) { + VisitExpr(Node); + switch (Node->getIdentType()) { + default: llvm_unreachable("unknown case"); + case PredefinedExpr::Func: OS << " __func__"; break; + case PredefinedExpr::Function: OS << " __FUNCTION__"; break; + case PredefinedExpr::LFunction: OS << " L__FUNCTION__"; break; + case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break; + } +} + +void ASTDumper::VisitCharacterLiteral(const CharacterLiteral *Node) { + VisitExpr(Node); + ColorScope Color(*this, ValueColor); + OS << " " << Node->getValue(); +} + +void ASTDumper::VisitIntegerLiteral(const IntegerLiteral *Node) { + VisitExpr(Node); + + bool isSigned = Node->getType()->isSignedIntegerType(); + ColorScope Color(*this, ValueColor); + OS << " " << Node->getValue().toString(10, isSigned); +} + +void ASTDumper::VisitFloatingLiteral(const FloatingLiteral *Node) { + VisitExpr(Node); + ColorScope Color(*this, ValueColor); + OS << " " << Node->getValueAsApproximateDouble(); +} + +void ASTDumper::VisitStringLiteral(const StringLiteral *Str) { + VisitExpr(Str); + ColorScope Color(*this, ValueColor); + OS << " "; + Str->outputString(OS); +} + +void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) { + VisitExpr(Node); + OS << " " << (Node->isPostfix() ? "postfix" : "prefix") + << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; +} + +void ASTDumper::VisitUnaryExprOrTypeTraitExpr( + const UnaryExprOrTypeTraitExpr *Node) { + VisitExpr(Node); + switch(Node->getKind()) { + case UETT_SizeOf: + OS << " sizeof"; + break; + case UETT_AlignOf: + OS << " alignof"; + break; + case UETT_VecStep: + OS << " vec_step"; + break; + } + if (Node->isArgumentType()) + dumpType(Node->getArgumentType()); +} + +void ASTDumper::VisitMemberExpr(const MemberExpr *Node) { + VisitExpr(Node); + OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl(); + dumpPointer(Node->getMemberDecl()); +} + +void ASTDumper::VisitExtVectorElementExpr(const ExtVectorElementExpr *Node) { + VisitExpr(Node); + OS << " " << Node->getAccessor().getNameStart(); +} + +void ASTDumper::VisitBinaryOperator(const BinaryOperator *Node) { + VisitExpr(Node); + OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; +} + +void ASTDumper::VisitCompoundAssignOperator( + const CompoundAssignOperator *Node) { + VisitExpr(Node); + OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) + << "' ComputeLHSTy="; + dumpBareType(Node->getComputationLHSType()); + OS << " ComputeResultTy="; + dumpBareType(Node->getComputationResultType()); +} + +void ASTDumper::VisitBlockExpr(const BlockExpr *Node) { + VisitExpr(Node); + dumpDecl(Node->getBlockDecl()); +} + +void ASTDumper::VisitOpaqueValueExpr(const OpaqueValueExpr *Node) { + VisitExpr(Node); + + if (Expr *Source = Node->getSourceExpr()) { + lastChild(); + dumpStmt(Source); + } +} + +// GNU extensions. + +void ASTDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) { + VisitExpr(Node); + OS << " " << Node->getLabel()->getName(); + dumpPointer(Node->getLabel()); +} + +//===----------------------------------------------------------------------===// +// C++ Expressions +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) { + VisitExpr(Node); + OS << " " << Node->getCastName() + << "<" << Node->getTypeAsWritten().getAsString() << ">" + << " <" << Node->getCastKindName(); + dumpBasePath(OS, Node); + OS << ">"; +} + +void ASTDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) { + VisitExpr(Node); + OS << " " << (Node->getValue() ? "true" : "false"); +} + +void ASTDumper::VisitCXXThisExpr(const CXXThisExpr *Node) { + VisitExpr(Node); + OS << " this"; +} + +void ASTDumper::VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node) { + VisitExpr(Node); + OS << " functional cast to " << Node->getTypeAsWritten().getAsString() + << " <" << Node->getCastKindName() << ">"; +} + +void ASTDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) { + VisitExpr(Node); + CXXConstructorDecl *Ctor = Node->getConstructor(); + dumpType(Ctor->getType()); + if (Node->isElidable()) + OS << " elidable"; + if (Node->requiresZeroInitialization()) + OS << " zeroing"; +} + +void ASTDumper::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node) { + VisitExpr(Node); + OS << " "; + dumpCXXTemporary(Node->getTemporary()); +} + +void ASTDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) { + VisitExpr(Node); + for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) + dumpDeclRef(Node->getObject(i), "cleanup"); +} + +void ASTDumper::dumpCXXTemporary(const CXXTemporary *Temporary) { + OS << "(CXXTemporary"; + dumpPointer(Temporary); + OS << ")"; +} + +//===----------------------------------------------------------------------===// +// Obj-C Expressions +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) { + VisitExpr(Node); + OS << " selector=" << Node->getSelector().getAsString(); + switch (Node->getReceiverKind()) { + case ObjCMessageExpr::Instance: + break; + + case ObjCMessageExpr::Class: + OS << " class="; + dumpBareType(Node->getClassReceiver()); + break; + + case ObjCMessageExpr::SuperInstance: + OS << " super (instance)"; + break; + + case ObjCMessageExpr::SuperClass: + OS << " super (class)"; + break; + } +} + +void ASTDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) { + VisitExpr(Node); + OS << " selector=" << Node->getBoxingMethod()->getSelector().getAsString(); +} + +void ASTDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { + VisitStmt(Node); + if (const VarDecl *CatchParam = Node->getCatchParamDecl()) + dumpDecl(CatchParam); + else + OS << " catch all"; +} + +void ASTDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) { + VisitExpr(Node); + dumpType(Node->getEncodedType()); +} + +void ASTDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) { + VisitExpr(Node); + + OS << " " << Node->getSelector().getAsString(); +} + +void ASTDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) { + VisitExpr(Node); + + OS << ' ' << *Node->getProtocol(); +} + +void ASTDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) { + VisitExpr(Node); + if (Node->isImplicitProperty()) { + OS << " Kind=MethodRef Getter=\""; + if (Node->getImplicitPropertyGetter()) + OS << Node->getImplicitPropertyGetter()->getSelector().getAsString(); + else + OS << "(null)"; + + OS << "\" Setter=\""; + if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter()) + OS << Setter->getSelector().getAsString(); + else + OS << "(null)"; + OS << "\""; + } else { + OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() <<'"'; + } + + if (Node->isSuperReceiver()) + OS << " super"; + + OS << " Messaging="; + if (Node->isMessagingGetter() && Node->isMessagingSetter()) + OS << "Getter&Setter"; + else if (Node->isMessagingGetter()) + OS << "Getter"; + else if (Node->isMessagingSetter()) + OS << "Setter"; +} + +void ASTDumper::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node) { + VisitExpr(Node); + if (Node->isArraySubscriptRefExpr()) + OS << " Kind=ArraySubscript GetterForArray=\""; + else + OS << " Kind=DictionarySubscript GetterForDictionary=\""; + if (Node->getAtIndexMethodDecl()) + OS << Node->getAtIndexMethodDecl()->getSelector().getAsString(); + else + OS << "(null)"; + + if (Node->isArraySubscriptRefExpr()) + OS << "\" SetterForArray=\""; + else + OS << "\" SetterForDictionary=\""; + if (Node->setAtIndexMethodDecl()) + OS << Node->setAtIndexMethodDecl()->getSelector().getAsString(); + else + OS << "(null)"; +} + +void ASTDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) { + VisitExpr(Node); + OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no"); +} + +//===----------------------------------------------------------------------===// +// Comments +//===----------------------------------------------------------------------===// + +const char *ASTDumper::getCommandName(unsigned CommandID) { + if (Traits) + return Traits->getCommandInfo(CommandID)->Name; + const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID); + if (Info) + return Info->Name; + return "<not a builtin command>"; +} + +void ASTDumper::dumpFullComment(const FullComment *C) { + if (!C) + return; + + FC = C; + dumpComment(C); + FC = 0; +} + +void ASTDumper::dumpComment(const Comment *C) { + IndentScope Indent(*this); + + if (!C) { + ColorScope Color(*this, NullColor); + OS << "<<<NULL>>>"; + return; + } + + { + ColorScope Color(*this, CommentColor); + OS << C->getCommentKindName(); + } + dumpPointer(C); + dumpSourceRange(C->getSourceRange()); + ConstCommentVisitor<ASTDumper>::visit(C); + for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpComment(*I); + } +} + +void ASTDumper::visitTextComment(const TextComment *C) { + OS << " Text=\"" << C->getText() << "\""; +} + +void ASTDumper::visitInlineCommandComment(const InlineCommandComment *C) { + OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; + switch (C->getRenderKind()) { + case InlineCommandComment::RenderNormal: + OS << " RenderNormal"; + break; + case InlineCommandComment::RenderBold: + OS << " RenderBold"; + break; + case InlineCommandComment::RenderMonospaced: + OS << " RenderMonospaced"; + break; + case InlineCommandComment::RenderEmphasized: + OS << " RenderEmphasized"; + break; + } + + for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) + OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\""; +} + +void ASTDumper::visitHTMLStartTagComment(const HTMLStartTagComment *C) { + OS << " Name=\"" << C->getTagName() << "\""; + if (C->getNumAttrs() != 0) { + OS << " Attrs: "; + for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) { + const HTMLStartTagComment::Attribute &Attr = C->getAttr(i); + OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\""; + } + } + if (C->isSelfClosing()) + OS << " SelfClosing"; +} + +void ASTDumper::visitHTMLEndTagComment(const HTMLEndTagComment *C) { + OS << " Name=\"" << C->getTagName() << "\""; +} + +void ASTDumper::visitBlockCommandComment(const BlockCommandComment *C) { + OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; + for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) + OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\""; +} + +void ASTDumper::visitParamCommandComment(const ParamCommandComment *C) { + OS << " " << ParamCommandComment::getDirectionAsString(C->getDirection()); + + if (C->isDirectionExplicit()) + OS << " explicitly"; + else + OS << " implicitly"; + + if (C->hasParamName()) { + if (C->isParamIndexValid()) + OS << " Param=\"" << C->getParamName(FC) << "\""; + else + OS << " Param=\"" << C->getParamNameAsWritten() << "\""; + } + + if (C->isParamIndexValid()) + OS << " ParamIndex=" << C->getParamIndex(); +} + +void ASTDumper::visitTParamCommandComment(const TParamCommandComment *C) { + if (C->hasParamName()) { + if (C->isPositionValid()) + OS << " Param=\"" << C->getParamName(FC) << "\""; + else + OS << " Param=\"" << C->getParamNameAsWritten() << "\""; + } + + if (C->isPositionValid()) { + OS << " Position=<"; + for (unsigned i = 0, e = C->getDepth(); i != e; ++i) { + OS << C->getIndex(i); + if (i != e - 1) + OS << ", "; + } + OS << ">"; + } +} + +void ASTDumper::visitVerbatimBlockComment(const VerbatimBlockComment *C) { + OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"" + " CloseName=\"" << C->getCloseName() << "\""; +} + +void ASTDumper::visitVerbatimBlockLineComment( + const VerbatimBlockLineComment *C) { + OS << " Text=\"" << C->getText() << "\""; +} + +void ASTDumper::visitVerbatimLineComment(const VerbatimLineComment *C) { + OS << " Text=\"" << C->getText() << "\""; +} + +//===----------------------------------------------------------------------===// +// Decl method implementations +//===----------------------------------------------------------------------===// + +void Decl::dump() const { + dump(llvm::errs()); +} + +void Decl::dump(raw_ostream &OS) const { + ASTDumper P(OS, &getASTContext().getCommentCommandTraits(), + &getASTContext().getSourceManager()); + P.dumpDecl(this); +} + +void Decl::dumpColor() const { + ASTDumper P(llvm::errs(), &getASTContext().getCommentCommandTraits(), + &getASTContext().getSourceManager(), /*ShowColors*/true); + P.dumpDecl(this); +} +//===----------------------------------------------------------------------===// +// Stmt method implementations +//===----------------------------------------------------------------------===// + +void Stmt::dump(SourceManager &SM) const { + dump(llvm::errs(), SM); +} + +void Stmt::dump(raw_ostream &OS, SourceManager &SM) const { + ASTDumper P(OS, 0, &SM); + P.dumpStmt(this); +} + +void Stmt::dump() const { + ASTDumper P(llvm::errs(), 0, 0); + P.dumpStmt(this); +} + +void Stmt::dumpColor() const { + ASTDumper P(llvm::errs(), 0, 0, /*ShowColors*/true); + P.dumpStmt(this); +} + +//===----------------------------------------------------------------------===// +// Comment method implementations +//===----------------------------------------------------------------------===// + +void Comment::dump() const { + dump(llvm::errs(), 0, 0); +} + +void Comment::dump(const ASTContext &Context) const { + dump(llvm::errs(), &Context.getCommentCommandTraits(), + &Context.getSourceManager()); +} + +void Comment::dump(raw_ostream &OS, const CommandTraits *Traits, + const SourceManager *SM) const { + const FullComment *FC = dyn_cast<FullComment>(this); + ASTDumper D(OS, Traits, SM); + D.dumpFullComment(FC); +} + +void Comment::dumpColor() const { + const FullComment *FC = dyn_cast<FullComment>(this); + ASTDumper D(llvm::errs(), 0, 0, /*ShowColors*/true); + D.dumpFullComment(FC); +} diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index 0d4f303..d2e6d29 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// #include "clang/AST/ASTImporter.h" - #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/DeclCXX.h" @@ -122,6 +121,7 @@ namespace clang { bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, bool Complain = true); bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord); + bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC); bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); Decl *VisitDecl(Decl *D); Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); @@ -206,12 +206,16 @@ namespace { /// \brief Whether to complain about failures. bool Complain; + /// \brief \c true if the last diagnostic came from C2. + bool LastDiagFromC2; + StructuralEquivalenceContext(ASTContext &C1, ASTContext &C2, llvm::DenseSet<std::pair<Decl *, Decl *> > &NonEquivalentDecls, bool StrictTypeSpelling = false, bool Complain = true) : C1(C1), C2(C2), NonEquivalentDecls(NonEquivalentDecls), - StrictTypeSpelling(StrictTypeSpelling), Complain(Complain) { } + StrictTypeSpelling(StrictTypeSpelling), Complain(Complain), + LastDiagFromC2(false) {} /// \brief Determine whether the two declarations are structurally /// equivalent. @@ -229,11 +233,17 @@ namespace { public: DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID) { assert(Complain && "Not allowed to complain"); + if (LastDiagFromC2) + C1.getDiagnostics().notePriorDiagnosticFrom(C2.getDiagnostics()); + LastDiagFromC2 = false; return C1.getDiagnostics().Report(Loc, DiagID); } DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID) { assert(Complain && "Not allowed to complain"); + if (!LastDiagFromC2) + C2.getDiagnostics().notePriorDiagnosticFrom(C1.getDiagnostics()); + LastDiagFromC2 = true; return C2.getDiagnostics().Report(Loc, DiagID); } }; @@ -892,14 +902,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, /// including the next assigned index (if none of them match). Returns an /// empty option if the context is not a record, i.e.. if the anonymous /// struct/union is at namespace or block scope. -static llvm::Optional<unsigned> -findAnonymousStructOrUnionIndex(RecordDecl *Anon) { +static Optional<unsigned> findAnonymousStructOrUnionIndex(RecordDecl *Anon) { ASTContext &Context = Anon->getASTContext(); QualType AnonTy = Context.getRecordType(Anon); RecordDecl *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext()); if (!Owner) - return llvm::Optional<unsigned>(); + return None; unsigned Index = 0; for (DeclContext::decl_iterator D = Owner->noload_decls_begin(), @@ -934,10 +943,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (D1->isAnonymousStructOrUnion() && D2->isAnonymousStructOrUnion()) { // If both anonymous structs/unions are in a record context, make sure // they occur in the same location in the context records. - if (llvm::Optional<unsigned> Index1 - = findAnonymousStructOrUnionIndex(D1)) { - if (llvm::Optional<unsigned> Index2 - = findAnonymousStructOrUnionIndex(D2)) { + if (Optional<unsigned> Index1 = findAnonymousStructOrUnionIndex(D1)) { + if (Optional<unsigned> Index2 = findAnonymousStructOrUnionIndex(D2)) { if (*Index1 != *Index2) return false; } @@ -1612,8 +1619,7 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { ToEPI.ExceptionSpecTemplate = cast_or_null<FunctionDecl>( Importer.Import(FromEPI.ExceptionSpecTemplate)); - return Importer.getToContext().getFunctionType(ToResultType, ArgTypes.data(), - ArgTypes.size(), ToEPI); + return Importer.getToContext().getFunctionType(ToResultType, ArgTypes, ToEPI); } QualType ASTNodeImporter::VisitParenType(const ParenType *T) { @@ -1825,7 +1831,7 @@ void ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) { if (RecordDecl *FromRecord = dyn_cast<RecordDecl>(FromD)) { if (RecordDecl *ToRecord = cast_or_null<RecordDecl>(ToD)) { - if (FromRecord->getDefinition() && !ToRecord->getDefinition()) { + if (FromRecord->getDefinition() && FromRecord->isCompleteDefinition() && !ToRecord->getDefinition()) { ImportDefinition(FromRecord, ToRecord); } } @@ -1907,11 +1913,7 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data(); struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data(); ToData.UserDeclaredConstructor = FromData.UserDeclaredConstructor; - ToData.UserDeclaredCopyConstructor = FromData.UserDeclaredCopyConstructor; - ToData.UserDeclaredMoveConstructor = FromData.UserDeclaredMoveConstructor; - ToData.UserDeclaredCopyAssignment = FromData.UserDeclaredCopyAssignment; - ToData.UserDeclaredMoveAssignment = FromData.UserDeclaredMoveAssignment; - ToData.UserDeclaredDestructor = FromData.UserDeclaredDestructor; + ToData.UserDeclaredSpecialMembers = FromData.UserDeclaredSpecialMembers; ToData.Aggregate = FromData.Aggregate; ToData.PlainOldData = FromData.PlainOldData; ToData.Empty = FromData.Empty; @@ -1925,30 +1927,41 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToData.HasMutableFields = FromData.HasMutableFields; ToData.HasOnlyCMembers = FromData.HasOnlyCMembers; ToData.HasInClassInitializer = FromData.HasInClassInitializer; - ToData.HasTrivialDefaultConstructor = FromData.HasTrivialDefaultConstructor; + ToData.HasUninitializedReferenceMember + = FromData.HasUninitializedReferenceMember; + ToData.NeedOverloadResolutionForMoveConstructor + = FromData.NeedOverloadResolutionForMoveConstructor; + ToData.NeedOverloadResolutionForMoveAssignment + = FromData.NeedOverloadResolutionForMoveAssignment; + ToData.NeedOverloadResolutionForDestructor + = FromData.NeedOverloadResolutionForDestructor; + ToData.DefaultedMoveConstructorIsDeleted + = FromData.DefaultedMoveConstructorIsDeleted; + ToData.DefaultedMoveAssignmentIsDeleted + = FromData.DefaultedMoveAssignmentIsDeleted; + ToData.DefaultedDestructorIsDeleted = FromData.DefaultedDestructorIsDeleted; + ToData.HasTrivialSpecialMembers = FromData.HasTrivialSpecialMembers; + ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor; ToData.HasConstexprNonCopyMoveConstructor = FromData.HasConstexprNonCopyMoveConstructor; ToData.DefaultedDefaultConstructorIsConstexpr = FromData.DefaultedDefaultConstructorIsConstexpr; ToData.HasConstexprDefaultConstructor = FromData.HasConstexprDefaultConstructor; - ToData.HasTrivialCopyConstructor = FromData.HasTrivialCopyConstructor; - ToData.HasTrivialMoveConstructor = FromData.HasTrivialMoveConstructor; - ToData.HasTrivialCopyAssignment = FromData.HasTrivialCopyAssignment; - ToData.HasTrivialMoveAssignment = FromData.HasTrivialMoveAssignment; - ToData.HasTrivialDestructor = FromData.HasTrivialDestructor; - ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor; ToData.HasNonLiteralTypeFieldsOrBases = FromData.HasNonLiteralTypeFieldsOrBases; // ComputedVisibleConversions not imported. ToData.UserProvidedDefaultConstructor = FromData.UserProvidedDefaultConstructor; - ToData.DeclaredDefaultConstructor = FromData.DeclaredDefaultConstructor; - ToData.DeclaredCopyConstructor = FromData.DeclaredCopyConstructor; - ToData.DeclaredMoveConstructor = FromData.DeclaredMoveConstructor; - ToData.DeclaredCopyAssignment = FromData.DeclaredCopyAssignment; - ToData.DeclaredMoveAssignment = FromData.DeclaredMoveAssignment; - ToData.DeclaredDestructor = FromData.DeclaredDestructor; + ToData.DeclaredSpecialMembers = FromData.DeclaredSpecialMembers; + ToData.ImplicitCopyConstructorHasConstParam + = FromData.ImplicitCopyConstructorHasConstParam; + ToData.ImplicitCopyAssignmentHasConstParam + = FromData.ImplicitCopyAssignmentHasConstParam; + ToData.HasDeclaredCopyConstructorWithConstParam + = FromData.HasDeclaredCopyConstructorWithConstParam; + ToData.HasDeclaredCopyAssignmentWithConstParam + = FromData.HasDeclaredCopyAssignmentWithConstParam; ToData.FailedImplicitMoveConstructor = FromData.FailedImplicitMoveConstructor; ToData.FailedImplicitMoveAssignment = FromData.FailedImplicitMoveAssignment; @@ -2143,7 +2156,18 @@ bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) { return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum); } -bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From, +bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC, + EnumConstantDecl *ToEC) +{ + const llvm::APSInt &FromVal = FromEC->getInitVal(); + const llvm::APSInt &ToVal = ToEC->getInitVal(); + + return FromVal.isSigned() == ToVal.isSigned() && + FromVal.getBitWidth() == ToVal.getBitWidth() && + FromVal == ToVal; +} + +bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To) { StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), @@ -2185,7 +2209,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { MergeWithNamespace = cast<NamespaceDecl>(DC)->getAnonymousNamespace(); } else { SmallVector<NamedDecl *, 4> ConflictingDecls; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Namespace)) @@ -2248,7 +2272,7 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) @@ -2328,7 +2352,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // We may already have an enum of the same name; try to find and match it. if (!DC->isFunctionOrMethod() && SearchName) { SmallVector<NamedDecl *, 4> ConflictingDecls; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(SearchName, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) @@ -2414,7 +2438,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { RecordDecl *AdoptDecl = 0; if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(SearchName, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) @@ -2431,10 +2455,10 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { FoundRecord->isAnonymousStructOrUnion()) { // If both anonymous structs/unions are in a record context, make sure // they occur in the same location in the context records. - if (llvm::Optional<unsigned> Index1 + if (Optional<unsigned> Index1 = findAnonymousStructOrUnionIndex(D)) { - if (llvm::Optional<unsigned> Index2 - = findAnonymousStructOrUnionIndex(FoundRecord)) { + if (Optional<unsigned> Index2 = + findAnonymousStructOrUnionIndex(FoundRecord)) { if (*Index1 != *Index2) continue; } @@ -2521,12 +2545,18 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { if (!LexicalDC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - + + if (EnumConstantDecl *FoundEnumConstant + = dyn_cast<EnumConstantDecl>(FoundDecls[I])) { + if (IsStructuralMatch(D, FoundEnumConstant)) + return Importer.Imported(D, FoundEnumConstant); + } + ConflictingDecls.push_back(FoundDecls[I]); } @@ -2567,7 +2597,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (!LexicalDC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) @@ -2629,8 +2659,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { FunctionProtoType::ExtProtoInfo DefaultEPI; FromTy = Importer.getFromContext().getFunctionType( FromFPT->getResultType(), - FromFPT->arg_type_begin(), - FromFPT->arg_type_end() - FromFPT->arg_type_begin(), + ArrayRef<QualType>(FromFPT->arg_type_begin(), + FromFPT->getNumArgs()), DefaultEPI); usedDifferentExceptionSpec = true; } @@ -2686,8 +2716,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { cast<CXXRecordDecl>(DC), D->getInnerLocStart(), NameInfo, T, TInfo, - Method->isStatic(), - Method->getStorageClassAsWritten(), + Method->getStorageClass(), Method->isInlineSpecified(), D->isConstexpr(), Importer.Import(D->getLocEnd())); @@ -2695,7 +2724,6 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, D->getInnerLocStart(), NameInfo, T, TInfo, D->getStorageClass(), - D->getStorageClassAsWritten(), D->isInlineSpecified(), D->hasWrittenPrototype(), D->isConstexpr()); @@ -2777,7 +2805,7 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { return 0; // Determine whether we've already imported this field. - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecls[I])) { @@ -2833,7 +2861,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { return 0; // Determine whether we've already imported this field. - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (IndirectFieldDecl *FoundField @@ -2898,7 +2926,7 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { return 0; // Determine whether we've already imported this ivar - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecls[I])) { @@ -2953,7 +2981,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { VarDecl *MergeWithVar = 0; SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) @@ -3046,8 +3074,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, - D->getStorageClass(), - D->getStorageClassAsWritten()); + D->getStorageClass()); ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc())); ToVar->setAccess(D->getAccess()); ToVar->setLexicalDeclContext(LexicalDC); @@ -3115,7 +3142,6 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass(), - D->getStorageClassAsWritten(), /*FIXME: Default argument*/ 0); ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg()); return Importer.Imported(D, ToParm); @@ -3129,7 +3155,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) return 0; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (ObjCMethodDecl *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecls[I])) { @@ -3376,7 +3402,7 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { return 0; ObjCProtocolDecl *MergeWithProtocol = 0; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol)) @@ -3480,10 +3506,13 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, // Import categories. When the categories themselves are imported, they'll // hook themselves into this interface. - for (ObjCCategoryDecl *FromCat = From->getCategoryList(); FromCat; - FromCat = FromCat->getNextClassCategory()) - Importer.Import(FromCat); - + for (ObjCInterfaceDecl::known_categories_iterator + Cat = From->known_categories_begin(), + CatEnd = From->known_categories_end(); + Cat != CatEnd; ++Cat) { + Importer.Import(*Cat); + } + // If we have an @implementation, import it as well. if (From->getImplementation()) { ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>( @@ -3523,7 +3552,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { // Look for an existing interface with the same name. ObjCInterfaceDecl *MergeWithIface = 0; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary)) @@ -3675,7 +3704,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { return 0; // Check whether we have already imported this property. - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (ObjCPropertyDecl *FoundProp @@ -3908,7 +3937,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { // We may already have a template of the same name; try to find and match it. if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; - llvm::SmallVector<NamedDecl *, 2> FoundDecls; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary)) @@ -4295,7 +4324,7 @@ ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, bool MinimalImport) : ToContext(ToContext), FromContext(FromContext), ToFileManager(ToFileManager), FromFileManager(FromFileManager), - Minimal(MinimalImport) + Minimal(MinimalImport), LastDiagFromFrom(false) { ImportedDecls[FromContext.getTranslationUnitDecl()] = ToContext.getTranslationUnitDecl(); @@ -4798,10 +4827,18 @@ DeclarationName ASTImporter::HandleNameConflict(DeclarationName Name, } DiagnosticBuilder ASTImporter::ToDiag(SourceLocation Loc, unsigned DiagID) { + if (LastDiagFromFrom) + ToContext.getDiagnostics().notePriorDiagnosticFrom( + FromContext.getDiagnostics()); + LastDiagFromFrom = false; return ToContext.getDiagnostics().Report(Loc, DiagID); } DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) { + if (!LastDiagFromFrom) + FromContext.getDiagnostics().notePriorDiagnosticFrom( + ToContext.getDiagnostics()); + LastDiagFromFrom = true; return FromContext.getDiagnostics().Report(Loc, DiagID); } diff --git a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp index cffcc65..daf65e5 100644 --- a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp @@ -13,8 +13,8 @@ #include "clang/AST/Attr.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/Type.h" #include "clang/AST/Expr.h" +#include "clang/AST/Type.h" using namespace clang; Attr::~Attr() { } @@ -23,4 +23,6 @@ void InheritableAttr::anchor() { } void InheritableParamAttr::anchor() { } +void MSInheritanceAttr::anchor() { } + #include "clang/AST/AttrImpl.inc" diff --git a/contrib/llvm/tools/clang/lib/AST/CXXABI.h b/contrib/llvm/tools/clang/lib/AST/CXXABI.h index 0d9c869..6d67d9a 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXABI.h +++ b/contrib/llvm/tools/clang/lib/AST/CXXABI.h @@ -27,9 +27,9 @@ class CXXABI { public: virtual ~CXXABI(); - /// Returns the size of a member pointer in multiples of the target - /// pointer size. - virtual unsigned getMemberPointerSize(const MemberPointerType *MPT) const = 0; + /// Returns the width and alignment of a member pointer in bits. + virtual std::pair<uint64_t, unsigned> + getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const = 0; /// Returns the default calling convention for C++ methods. virtual CallingConv getDefaultMethodCallConv(bool isVariadic) const = 0; diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp index 213b214..0e0b35d 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "clang/AST/CXXInheritance.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/RecordLayout.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/RecordLayout.h" #include "llvm/ADT/SetVector.h" #include <algorithm> #include <set> @@ -28,7 +28,7 @@ void CXXBasePaths::ComputeDeclsFound() { llvm::SetVector<NamedDecl *, SmallVector<NamedDecl *, 8> > Decls; for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path) - Decls.insert(*Path->Decls.first); + Decls.insert(Path->Decls.front()); NumDeclsFound = Decls.size(); DeclsFound = new NamedDecl * [NumDeclsFound]; @@ -118,7 +118,19 @@ static bool BaseIsNot(const CXXRecordDecl *Base, void *OpaqueTarget) { } bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const { - return forallBases(BaseIsNot, (void*) Base->getCanonicalDecl()); + return forallBases(BaseIsNot, + const_cast<CXXRecordDecl *>(Base->getCanonicalDecl())); +} + +bool +CXXRecordDecl::isCurrentInstantiation(const DeclContext *CurContext) const { + assert(isDependentContext()); + + for (; !CurContext->isFileContext(); CurContext = CurContext->getParent()) + if (CurContext->Equals(this)) + return true; + + return false; } bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches, @@ -140,7 +152,9 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches, CXXRecordDecl *Base = cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition()); - if (!Base) { + if (!Base || + (Base->isDependentContext() && + !Base->isCurrentInstantiation(Record))) { if (AllowShortCircuit) return false; AllMatches = false; continue; @@ -384,9 +398,9 @@ bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier, DeclarationName N = DeclarationName::getFromOpaquePtr(Name); for (Path.Decls = BaseRecord->lookup(N); - Path.Decls.first != Path.Decls.second; - ++Path.Decls.first) { - if ((*Path.Decls.first)->isInIdentifierNamespace(IDNS_Tag)) + !Path.Decls.empty(); + Path.Decls = Path.Decls.slice(1)) { + if (Path.Decls.front()->isInIdentifierNamespace(IDNS_Tag)) return true; } @@ -402,9 +416,9 @@ bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier, const unsigned IDNS = IDNS_Ordinary | IDNS_Tag | IDNS_Member; DeclarationName N = DeclarationName::getFromOpaquePtr(Name); for (Path.Decls = BaseRecord->lookup(N); - Path.Decls.first != Path.Decls.second; - ++Path.Decls.first) { - if ((*Path.Decls.first)->isInIdentifierNamespace(IDNS)) + !Path.Decls.empty(); + Path.Decls = Path.Decls.slice(1)) { + if (Path.Decls.front()->isInIdentifierNamespace(IDNS)) return true; } @@ -420,11 +434,11 @@ FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, DeclarationName N = DeclarationName::getFromOpaquePtr(Name); for (Path.Decls = BaseRecord->lookup(N); - Path.Decls.first != Path.Decls.second; - ++Path.Decls.first) { + !Path.Decls.empty(); + Path.Decls = Path.Decls.slice(1)) { // FIXME: Refactor the "is it a nested-name-specifier?" check - if (isa<TypedefNameDecl>(*Path.Decls.first) || - (*Path.Decls.first)->isInIdentifierNamespace(IDNS_Tag)) + if (isa<TypedefNameDecl>(Path.Decls.front()) || + Path.Decls.front()->isInIdentifierNamespace(IDNS_Tag)) return true; } @@ -725,4 +739,3 @@ CXXRecordDecl::getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const { AddIndirectPrimaryBases(BaseDecl, Context, Bases); } } - diff --git a/contrib/llvm/tools/clang/lib/AST/Comment.cpp b/contrib/llvm/tools/clang/lib/AST/Comment.cpp index 361f8ac..db55c04 100644 --- a/contrib/llvm/tools/clang/lib/AST/Comment.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Comment.cpp @@ -32,20 +32,6 @@ const char *Comment::getCommentKindName() const { llvm_unreachable("Unknown comment kind!"); } -void Comment::dump() const { - // It is important that Comment::dump() is defined in a different TU than - // Comment::dump(raw_ostream, SourceManager). If both functions were defined - // in CommentDumper.cpp, that object file would be removed by linker because - // none of its functions are referenced by other object files, despite the - // LLVM_ATTRIBUTE_USED. - dump(llvm::errs(), NULL, NULL); -} - -void Comment::dump(const ASTContext &Context) const { - dump(llvm::errs(), &Context.getCommentCommandTraits(), - &Context.getSourceManager()); -} - namespace { struct good {}; struct bad {}; @@ -255,32 +241,32 @@ void DeclInfo::fill() { while (true) { TL = TL.IgnoreParens(); // Look through qualified types. - if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) { - TL = QualifiedTL->getUnqualifiedLoc(); + if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) { + TL = QualifiedTL.getUnqualifiedLoc(); continue; } // Look through pointer types. - if (PointerTypeLoc *PointerTL = dyn_cast<PointerTypeLoc>(&TL)) { - TL = PointerTL->getPointeeLoc().getUnqualifiedLoc(); + if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) { + TL = PointerTL.getPointeeLoc().getUnqualifiedLoc(); continue; } - if (BlockPointerTypeLoc *BlockPointerTL = - dyn_cast<BlockPointerTypeLoc>(&TL)) { - TL = BlockPointerTL->getPointeeLoc().getUnqualifiedLoc(); + if (BlockPointerTypeLoc BlockPointerTL = + TL.getAs<BlockPointerTypeLoc>()) { + TL = BlockPointerTL.getPointeeLoc().getUnqualifiedLoc(); continue; } - if (MemberPointerTypeLoc *MemberPointerTL = - dyn_cast<MemberPointerTypeLoc>(&TL)) { - TL = MemberPointerTL->getPointeeLoc().getUnqualifiedLoc(); + if (MemberPointerTypeLoc MemberPointerTL = + TL.getAs<MemberPointerTypeLoc>()) { + TL = MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); continue; } // Is this a typedef for a function type? - if (FunctionTypeLoc *FTL = dyn_cast<FunctionTypeLoc>(&TL)) { + if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { Kind = FunctionKind; - ArrayRef<ParmVarDecl *> Params = FTL->getParams(); + ArrayRef<ParmVarDecl *> Params = FTL.getParams(); ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(), Params.size()); - ResultType = FTL->getResultLoc().getType(); + ResultType = FTL.getResultLoc().getType(); break; } break; diff --git a/contrib/llvm/tools/clang/lib/AST/CommentBriefParser.cpp b/contrib/llvm/tools/clang/lib/AST/CommentBriefParser.cpp index 95daa7e..090b921 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentBriefParser.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentBriefParser.cpp @@ -78,7 +78,7 @@ std::string BriefParser::Parse() { continue; } - if (Tok.is(tok::command)) { + if (Tok.is(tok::backslash_command) || Tok.is(tok::at_command)) { const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID()); if (Info->IsBriefCommand) { FirstParagraphOrBrief.clear(); diff --git a/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp b/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp index e7e40fd..e24d542 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp @@ -15,9 +15,21 @@ namespace comments { #include "clang/AST/CommentCommandInfo.inc" -CommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator) : - NextID(llvm::array_lengthof(Commands)), Allocator(Allocator) -{ } +CommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator, + const CommentOptions &CommentOptions) : + NextID(llvm::array_lengthof(Commands)), Allocator(Allocator) { + registerCommentOptions(CommentOptions); +} + +void CommandTraits::registerCommentOptions( + const CommentOptions &CommentOptions) { + for (CommentOptions::BlockCommandNamesTy::const_iterator + I = CommentOptions.BlockCommandNames.begin(), + E = CommentOptions.BlockCommandNames.end(); + I != E; I++) { + registerBlockCommand(*I); + } +} const CommandInfo *CommandTraits::getCommandInfoOrNULL(StringRef Name) const { if (const CommandInfo *Info = getBuiltinCommandInfo(Name)) @@ -31,7 +43,7 @@ const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const { return getRegisteredCommandInfo(CommandID); } -const CommandInfo *CommandTraits::registerUnknownCommand(StringRef CommandName) { +CommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) { char *Name = Allocator.Allocate<char>(CommandName.size() + 1); memcpy(Name, CommandName.data(), CommandName.size()); Name[CommandName.size()] = '\0'; @@ -40,13 +52,25 @@ const CommandInfo *CommandTraits::registerUnknownCommand(StringRef CommandName) CommandInfo *Info = new (Allocator) CommandInfo(); Info->Name = Name; Info->ID = NextID++; - Info->IsUnknownCommand = true; RegisteredCommands.push_back(Info); return Info; } +const CommandInfo *CommandTraits::registerUnknownCommand( + StringRef CommandName) { + CommandInfo *Info = createCommandInfoWithName(CommandName); + Info->IsUnknownCommand = true; + return Info; +} + +const CommandInfo *CommandTraits::registerBlockCommand(StringRef CommandName) { + CommandInfo *Info = createCommandInfoWithName(CommandName); + Info->IsBlockCommand = true; + return Info; +} + const CommandInfo *CommandTraits::getBuiltinCommandInfo( unsigned CommandID) { if (CommandID < llvm::array_lengthof(Commands)) diff --git a/contrib/llvm/tools/clang/lib/AST/CommentDumper.cpp b/contrib/llvm/tools/clang/lib/AST/CommentDumper.cpp deleted file mode 100644 index 19d24b2..0000000 --- a/contrib/llvm/tools/clang/lib/AST/CommentDumper.cpp +++ /dev/null @@ -1,257 +0,0 @@ -//===--- CommentDumper.cpp - Dumping implementation for Comment ASTs ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "clang/AST/CommentVisitor.h" -#include "llvm/Support/raw_ostream.h" - -namespace clang { -namespace comments { - -namespace { -class CommentDumper: public comments::ConstCommentVisitor<CommentDumper> { - raw_ostream &OS; - const CommandTraits *Traits; - const SourceManager *SM; - - /// The \c FullComment parent of the comment being dumped. - const FullComment *FC; - - unsigned IndentLevel; - -public: - CommentDumper(raw_ostream &OS, - const CommandTraits *Traits, - const SourceManager *SM, - const FullComment *FC) : - OS(OS), Traits(Traits), SM(SM), FC(FC), IndentLevel(0) - { } - - void dumpIndent() const { - for (unsigned i = 1, e = IndentLevel; i < e; ++i) - OS << " "; - } - - void dumpLocation(SourceLocation Loc) { - if (SM) - Loc.print(OS, *SM); - } - - void dumpSourceRange(const Comment *C); - - void dumpComment(const Comment *C); - - void dumpSubtree(const Comment *C); - - // Inline content. - void visitTextComment(const TextComment *C); - void visitInlineCommandComment(const InlineCommandComment *C); - void visitHTMLStartTagComment(const HTMLStartTagComment *C); - void visitHTMLEndTagComment(const HTMLEndTagComment *C); - - // Block content. - void visitParagraphComment(const ParagraphComment *C); - void visitBlockCommandComment(const BlockCommandComment *C); - void visitParamCommandComment(const ParamCommandComment *C); - void visitTParamCommandComment(const TParamCommandComment *C); - void visitVerbatimBlockComment(const VerbatimBlockComment *C); - void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C); - void visitVerbatimLineComment(const VerbatimLineComment *C); - - void visitFullComment(const FullComment *C); - - const char *getCommandName(unsigned CommandID) { - if (Traits) - return Traits->getCommandInfo(CommandID)->Name; - const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID); - if (Info) - return Info->Name; - return "<not a builtin command>"; - } -}; - -void CommentDumper::dumpSourceRange(const Comment *C) { - if (!SM) - return; - - SourceRange SR = C->getSourceRange(); - - OS << " <"; - dumpLocation(SR.getBegin()); - if (SR.getBegin() != SR.getEnd()) { - OS << ", "; - dumpLocation(SR.getEnd()); - } - OS << ">"; -} - -void CommentDumper::dumpComment(const Comment *C) { - dumpIndent(); - OS << "(" << C->getCommentKindName() - << " " << (const void *) C; - dumpSourceRange(C); -} - -void CommentDumper::dumpSubtree(const Comment *C) { - ++IndentLevel; - if (C) { - visit(C); - for (Comment::child_iterator I = C->child_begin(), - E = C->child_end(); - I != E; ++I) { - OS << '\n'; - dumpSubtree(*I); - } - OS << ')'; - } else { - dumpIndent(); - OS << "<<<NULL>>>"; - } - --IndentLevel; -} - -void CommentDumper::visitTextComment(const TextComment *C) { - dumpComment(C); - - OS << " Text=\"" << C->getText() << "\""; -} - -void CommentDumper::visitInlineCommandComment(const InlineCommandComment *C) { - dumpComment(C); - - OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; - switch (C->getRenderKind()) { - case InlineCommandComment::RenderNormal: - OS << " RenderNormal"; - break; - case InlineCommandComment::RenderBold: - OS << " RenderBold"; - break; - case InlineCommandComment::RenderMonospaced: - OS << " RenderMonospaced"; - break; - case InlineCommandComment::RenderEmphasized: - OS << " RenderEmphasized"; - break; - } - - for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) - OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\""; -} - -void CommentDumper::visitHTMLStartTagComment(const HTMLStartTagComment *C) { - dumpComment(C); - - OS << " Name=\"" << C->getTagName() << "\""; - if (C->getNumAttrs() != 0) { - OS << " Attrs: "; - for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) { - const HTMLStartTagComment::Attribute &Attr = C->getAttr(i); - OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\""; - } - } - if (C->isSelfClosing()) - OS << " SelfClosing"; -} - -void CommentDumper::visitHTMLEndTagComment(const HTMLEndTagComment *C) { - dumpComment(C); - - OS << " Name=\"" << C->getTagName() << "\""; -} - -void CommentDumper::visitParagraphComment(const ParagraphComment *C) { - dumpComment(C); -} - -void CommentDumper::visitBlockCommandComment(const BlockCommandComment *C) { - dumpComment(C); - - OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; - for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) - OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\""; -} - -void CommentDumper::visitParamCommandComment(const ParamCommandComment *C) { - dumpComment(C); - - OS << " " << ParamCommandComment::getDirectionAsString(C->getDirection()); - - if (C->isDirectionExplicit()) - OS << " explicitly"; - else - OS << " implicitly"; - - if (C->hasParamName()) { - if (C->isParamIndexValid()) - OS << " Param=\"" << C->getParamName(FC) << "\""; - else - OS << " Param=\"" << C->getParamNameAsWritten() << "\""; - } - - if (C->isParamIndexValid()) - OS << " ParamIndex=" << C->getParamIndex(); -} - -void CommentDumper::visitTParamCommandComment(const TParamCommandComment *C) { - dumpComment(C); - - if (C->hasParamName()) { - if (C->isPositionValid()) - OS << " Param=\"" << C->getParamName(FC) << "\""; - else - OS << " Param=\"" << C->getParamNameAsWritten() << "\""; - } - - if (C->isPositionValid()) { - OS << " Position=<"; - for (unsigned i = 0, e = C->getDepth(); i != e; ++i) { - OS << C->getIndex(i); - if (i != e - 1) - OS << ", "; - } - OS << ">"; - } -} - -void CommentDumper::visitVerbatimBlockComment(const VerbatimBlockComment *C) { - dumpComment(C); - - OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"" - " CloseName=\"" << C->getCloseName() << "\""; -} - -void CommentDumper::visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C) { - dumpComment(C); - - OS << " Text=\"" << C->getText() << "\""; -} - -void CommentDumper::visitVerbatimLineComment(const VerbatimLineComment *C) { - dumpComment(C); - - OS << " Text=\"" << C->getText() << "\""; -} - -void CommentDumper::visitFullComment(const FullComment *C) { - dumpComment(C); -} - -} // unnamed namespace - -void Comment::dump(llvm::raw_ostream &OS, const CommandTraits *Traits, - const SourceManager *SM) const { - const FullComment *FC = dyn_cast<FullComment>(this); - CommentDumper D(llvm::errs(), Traits, SM, FC); - D.dumpSubtree(this); - llvm::errs() << '\n'; -} - -} // end namespace comments -} // end namespace clang - diff --git a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp index 31a09f7..1194520 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp @@ -1,7 +1,9 @@ #include "clang/AST/CommentLexer.h" #include "clang/AST/CommentCommandTraits.h" -#include "clang/Basic/ConvertUTF.h" +#include "clang/Basic/CharInfo.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/ConvertUTF.h" #include "llvm/Support/ErrorHandling.h" namespace clang { @@ -13,34 +15,46 @@ void Token::dump(const Lexer &L, const SourceManager &SM) const { llvm::errs() << " " << Length << " \"" << L.getSpelling(*this, SM) << "\"\n"; } -namespace { -bool isHTMLNamedCharacterReferenceCharacter(char C) { - return (C >= 'a' && C <= 'z') || - (C >= 'A' && C <= 'Z'); +static inline bool isHTMLNamedCharacterReferenceCharacter(char C) { + return isLetter(C); } -bool isHTMLDecimalCharacterReferenceCharacter(char C) { - return C >= '0' && C <= '9'; +static inline bool isHTMLDecimalCharacterReferenceCharacter(char C) { + return isDigit(C); } -bool isHTMLHexCharacterReferenceCharacter(char C) { - return (C >= '0' && C <= '9') || - (C >= 'a' && C <= 'f') || - (C >= 'A' && C <= 'F'); +static inline bool isHTMLHexCharacterReferenceCharacter(char C) { + return isHexDigit(C); } +static inline StringRef convertCodePointToUTF8( + llvm::BumpPtrAllocator &Allocator, + unsigned CodePoint) { + char *Resolved = Allocator.Allocate<char>(UNI_MAX_UTF8_BYTES_PER_CODE_POINT); + char *ResolvedPtr = Resolved; + if (llvm::ConvertCodePointToUTF8(CodePoint, ResolvedPtr)) + return StringRef(Resolved, ResolvedPtr - Resolved); + else + return StringRef(); +} + +namespace { + #include "clang/AST/CommentHTMLTags.inc" +#include "clang/AST/CommentHTMLNamedCharacterReferences.inc" } // unnamed namespace StringRef Lexer::resolveHTMLNamedCharacterReference(StringRef Name) const { + // Fast path, first check a few most widely used named character references. return llvm::StringSwitch<StringRef>(Name) .Case("amp", "&") .Case("lt", "<") .Case("gt", ">") .Case("quot", "\"") .Case("apos", "\'") - .Default(""); + // Slow path. + .Default(translateHTMLNamedCharacterReferenceToUTF8(Name)); } StringRef Lexer::resolveHTMLDecimalCharacterReference(StringRef Name) const { @@ -50,13 +64,7 @@ StringRef Lexer::resolveHTMLDecimalCharacterReference(StringRef Name) const { CodePoint *= 10; CodePoint += Name[i] - '0'; } - - char *Resolved = Allocator.Allocate<char>(UNI_MAX_UTF8_BYTES_PER_CODE_POINT); - char *ResolvedPtr = Resolved; - if (ConvertCodePointToUTF8(CodePoint, ResolvedPtr)) - return StringRef(Resolved, ResolvedPtr - Resolved); - else - return StringRef(); + return convertCodePointToUTF8(Allocator, CodePoint); } StringRef Lexer::resolveHTMLHexCharacterReference(StringRef Name) const { @@ -65,20 +73,9 @@ StringRef Lexer::resolveHTMLHexCharacterReference(StringRef Name) const { CodePoint *= 16; const char C = Name[i]; assert(isHTMLHexCharacterReferenceCharacter(C)); - if (C >= '0' && C <= '9') - CodePoint += Name[i] - '0'; - else if (C >= 'a' && C <= 'f') - CodePoint += Name[i] - 'a' + 10; - else - CodePoint += Name[i] - 'A' + 10; + CodePoint += llvm::hexDigitValue(C); } - - char *Resolved = Allocator.Allocate<char>(UNI_MAX_UTF8_BYTES_PER_CODE_POINT); - char *ResolvedPtr = Resolved; - if (ConvertCodePointToUTF8(CodePoint, ResolvedPtr)) - return StringRef(Resolved, ResolvedPtr - Resolved); - else - return StringRef(); + return convertCodePointToUTF8(Allocator, CodePoint); } void Lexer::skipLineStartingDecorations() { @@ -99,7 +96,7 @@ void Lexer::skipLineStartingDecorations() { return; char C = *NewBufferPtr; - while (C == ' ' || C == '\t' || C == '\f' || C == '\v') { + while (isHorizontalWhitespace(C)) { NewBufferPtr++; if (NewBufferPtr == CommentEnd) return; @@ -119,8 +116,7 @@ namespace { /// Returns pointer to the first newline character in the string. const char *findNewline(const char *BufferPtr, const char *BufferEnd) { for ( ; BufferPtr != BufferEnd; ++BufferPtr) { - const char C = *BufferPtr; - if (C == '\n' || C == '\r') + if (isVerticalWhitespace(*BufferPtr)) return BufferPtr; } return BufferEnd; @@ -169,14 +165,11 @@ const char *skipHexCharacterReference(const char *BufferPtr, } bool isHTMLIdentifierStartingCharacter(char C) { - return (C >= 'a' && C <= 'z') || - (C >= 'A' && C <= 'Z'); + return isLetter(C); } bool isHTMLIdentifierCharacter(char C) { - return (C >= 'a' && C <= 'z') || - (C >= 'A' && C <= 'Z') || - (C >= '0' && C <= '9'); + return isAlphanumeric(C); } const char *skipHTMLIdentifier(const char *BufferPtr, const char *BufferEnd) { @@ -205,15 +198,6 @@ const char *skipHTMLQuotedString(const char *BufferPtr, const char *BufferEnd) return BufferEnd; } -bool isHorizontalWhitespace(char C) { - return C == ' ' || C == '\t' || C == '\f' || C == '\v'; -} - -bool isWhitespace(char C) { - return C == ' ' || C == '\n' || C == '\r' || - C == '\t' || C == '\f' || C == '\v'; -} - const char *skipWhitespace(const char *BufferPtr, const char *BufferEnd) { for ( ; BufferPtr != BufferEnd; ++BufferPtr) { if (!isWhitespace(*BufferPtr)) @@ -227,14 +211,11 @@ bool isWhitespace(const char *BufferPtr, const char *BufferEnd) { } bool isCommandNameStartCharacter(char C) { - return (C >= 'a' && C <= 'z') || - (C >= 'A' && C <= 'Z'); + return isLetter(C); } bool isCommandNameCharacter(char C) { - return (C >= 'a' && C <= 'z') || - (C >= 'A' && C <= 'Z') || - (C >= '0' && C <= '9'); + return isAlphanumeric(C); } const char *skipCommandName(const char *BufferPtr, const char *BufferEnd) { @@ -250,12 +231,10 @@ const char *skipCommandName(const char *BufferPtr, const char *BufferEnd) { const char *findBCPLCommentEnd(const char *BufferPtr, const char *BufferEnd) { const char *CurPtr = BufferPtr; while (CurPtr != BufferEnd) { - char C = *CurPtr; - while (C != '\n' && C != '\r') { + while (!isVerticalWhitespace(*CurPtr)) { CurPtr++; if (CurPtr == BufferEnd) return BufferEnd; - C = *CurPtr; } // We found a newline, check if it is escaped. const char *EscapePtr = CurPtr - 1; @@ -319,6 +298,11 @@ void Lexer::lexCommentText(Token &T) { switch(*TokenPtr) { case '\\': case '@': { + // Commands that start with a backslash and commands that start with + // 'at' have equivalent semantics. But we keep information about the + // exact syntax in AST for comments. + tok::TokenKind CommandKind = + (*TokenPtr == '@') ? tok::at_command : tok::backslash_command; TokenPtr++; if (TokenPtr == CommentEnd) { formTextToken(T, TokenPtr); @@ -379,7 +363,7 @@ void Lexer::lexCommentText(Token &T) { setupAndLexVerbatimLine(T, TokenPtr, Info); return; } - formTokenWithChars(T, TokenPtr, tok::command); + formTokenWithChars(T, TokenPtr, CommandKind); T.setCommandID(Info->getID()); return; } @@ -415,15 +399,12 @@ void Lexer::lexCommentText(Token &T) { return; default: { - while (true) { - TokenPtr++; - if (TokenPtr == CommentEnd) - break; - const char C = *TokenPtr; - if(C == '\n' || C == '\r' || - C == '\\' || C == '@' || C == '&' || C == '<') - break; - } + size_t End = StringRef(TokenPtr, CommentEnd - TokenPtr). + find_first_of("\n\r\\@&<"); + if (End != StringRef::npos) + TokenPtr += End; + else + TokenPtr = CommentEnd; formTextToken(T, TokenPtr); return; } @@ -446,13 +427,11 @@ void Lexer::setupAndLexVerbatimBlock(Token &T, // If there is a newline following the verbatim opening command, skip the // newline so that we don't create an tok::verbatim_block_line with empty // text content. - if (BufferPtr != CommentEnd) { - const char C = *BufferPtr; - if (C == '\n' || C == '\r') { - BufferPtr = skipNewline(BufferPtr, CommentEnd); - State = LS_VerbatimBlockBody; - return; - } + if (BufferPtr != CommentEnd && + isVerticalWhitespace(*BufferPtr)) { + BufferPtr = skipNewline(BufferPtr, CommentEnd); + State = LS_VerbatimBlockBody; + return; } State = LS_VerbatimBlockFirstLine; diff --git a/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp b/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp index d0a8474..09912c6 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp @@ -8,9 +8,10 @@ //===----------------------------------------------------------------------===// #include "clang/AST/CommentParser.h" -#include "clang/AST/CommentSema.h" -#include "clang/AST/CommentDiagnostic.h" #include "clang/AST/CommentCommandTraits.h" +#include "clang/AST/CommentDiagnostic.h" +#include "clang/AST/CommentSema.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" #include "llvm/Support/ErrorHandling.h" @@ -109,11 +110,6 @@ class TextTokenRetokenizer { return true; } - static bool isWhitespace(char C) { - return C == ' ' || C == '\n' || C == '\r' || - C == '\t' || C == '\f' || C == '\v'; - } - void consumeWhitespace() { while (!isEnd()) { if (isWhitespace(peek())) @@ -175,8 +171,7 @@ public: memcpy(TextPtr, WordText.c_str(), Length + 1); StringRef Text = StringRef(TextPtr, Length); - formTokenWithChars(Tok, Loc, WordBegin, - Pos.BufferPtr - WordBegin, Text); + formTokenWithChars(Tok, Loc, WordBegin, Length, Text); return true; } @@ -305,7 +300,7 @@ void Parser::parseBlockCommandArgs(BlockCommandComment *BC, } BlockCommandComment *Parser::parseBlockCommand() { - assert(Tok.is(tok::command)); + assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command)); ParamCommandComment *PC; TParamCommandComment *TPC; @@ -313,25 +308,29 @@ BlockCommandComment *Parser::parseBlockCommand() { bool IsParam = false; bool IsTParam = false; const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID()); + CommandMarkerKind CommandMarker = + Tok.is(tok::backslash_command) ? CMK_Backslash : CMK_At; if (Info->IsParamCommand) { IsParam = true; PC = S.actOnParamCommandStart(Tok.getLocation(), Tok.getEndLocation(), - Tok.getCommandID()); - } if (Info->IsTParamCommand) { + Tok.getCommandID(), + CommandMarker); + } else if (Info->IsTParamCommand) { IsTParam = true; TPC = S.actOnTParamCommandStart(Tok.getLocation(), Tok.getEndLocation(), - Tok.getCommandID()); + Tok.getCommandID(), + CommandMarker); } else { BC = S.actOnBlockCommandStart(Tok.getLocation(), Tok.getEndLocation(), - Tok.getCommandID()); + Tok.getCommandID(), + CommandMarker); } consumeToken(); - if (Tok.is(tok::command) && - Traits.getCommandInfo(Tok.getCommandID())->IsBlockCommand) { + if (isTokBlockCommand()) { // Block command ahead. We can't nest block commands, so pretend that this // command has an empty argument. ParagraphComment *Paragraph = S.actOnParagraphComment( @@ -363,10 +362,28 @@ BlockCommandComment *Parser::parseBlockCommand() { Retokenizer.putBackLeftoverTokens(); } - BlockContentComment *Block = parseParagraphOrBlockCommand(); - // Since we have checked for a block command, we should have parsed a - // paragraph. - ParagraphComment *Paragraph = cast<ParagraphComment>(Block); + // If there's a block command ahead, we will attach an empty paragraph to + // this command. + bool EmptyParagraph = false; + if (isTokBlockCommand()) + EmptyParagraph = true; + else if (Tok.is(tok::newline)) { + Token PrevTok = Tok; + consumeToken(); + EmptyParagraph = isTokBlockCommand(); + putBack(PrevTok); + } + + ParagraphComment *Paragraph; + if (EmptyParagraph) + Paragraph = S.actOnParagraphComment(ArrayRef<InlineContentComment *>()); + else { + BlockContentComment *Block = parseParagraphOrBlockCommand(); + // Since we have checked for a block command, we should have parsed a + // paragraph. + Paragraph = cast<ParagraphComment>(Block); + } + if (IsParam) { S.actOnParamCommandFinish(PC, Paragraph); return PC; @@ -380,7 +397,7 @@ BlockCommandComment *Parser::parseBlockCommand() { } InlineCommandComment *Parser::parseInlineCommand() { - assert(Tok.is(tok::command)); + assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command)); const Token CommandTok = Tok; consumeToken(); @@ -547,7 +564,8 @@ BlockContentComment *Parser::parseParagraphOrBlockCommand() { consumeToken(); continue; - case tok::command: { + case tok::backslash_command: + case tok::at_command: { const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID()); if (Info->IsBlockCommand) { if (Content.size() == 0) @@ -557,6 +575,7 @@ BlockContentComment *Parser::parseParagraphOrBlockCommand() { if (Info->IsVerbatimBlockEndCommand) { Diag(Tok.getLocation(), diag::warn_verbatim_block_end_without_start) + << Tok.is(tok::at_command) << Info->Name << SourceRange(Tok.getLocation(), Tok.getEndLocation()); consumeToken(); @@ -694,7 +713,8 @@ BlockContentComment *Parser::parseBlockContent() { switch (Tok.getKind()) { case tok::text: case tok::unknown_command: - case tok::command: + case tok::backslash_command: + case tok::at_command: case tok::html_start_tag: case tok::html_end_tag: return parseParagraphOrBlockCommand(); diff --git a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp index 08ecb3a..e0138d5 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp @@ -8,14 +8,15 @@ //===----------------------------------------------------------------------===// #include "clang/AST/CommentSema.h" -#include "clang/AST/CommentDiagnostic.h" +#include "clang/AST/Attr.h" #include "clang/AST/CommentCommandTraits.h" +#include "clang/AST/CommentDiagnostic.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSwitch.h" namespace clang { namespace comments { @@ -28,7 +29,8 @@ Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, DiagnosticsEngine &Diags, CommandTraits &Traits, const Preprocessor *PP) : Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits), - PP(PP), ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL) { + PP(PP), ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL), + HeaderfileCommand(NULL) { } void Sema::setDecl(const Decl *D) { @@ -45,10 +47,16 @@ ParagraphComment *Sema::actOnParagraphComment( return new (Allocator) ParagraphComment(Content); } -BlockCommandComment *Sema::actOnBlockCommandStart(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID) { - return new (Allocator) BlockCommandComment(LocBegin, LocEnd, CommandID); +BlockCommandComment *Sema::actOnBlockCommandStart( + SourceLocation LocBegin, + SourceLocation LocEnd, + unsigned CommandID, + CommandMarkerKind CommandMarker) { + BlockCommandComment *BC = new (Allocator) BlockCommandComment(LocBegin, LocEnd, + CommandID, + CommandMarker); + checkContainerDecl(BC); + return BC; } void Sema::actOnBlockCommandArgs(BlockCommandComment *Command, @@ -65,20 +73,139 @@ void Sema::actOnBlockCommandFinish(BlockCommandComment *Command, checkDeprecatedCommand(Command); } -ParamCommandComment *Sema::actOnParamCommandStart(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID) { +ParamCommandComment *Sema::actOnParamCommandStart( + SourceLocation LocBegin, + SourceLocation LocEnd, + unsigned CommandID, + CommandMarkerKind CommandMarker) { ParamCommandComment *Command = - new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID); + new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID, + CommandMarker); if (!isFunctionDecl()) Diag(Command->getLocation(), diag::warn_doc_param_not_attached_to_a_function_decl) + << CommandMarker << Command->getCommandNameRange(Traits); return Command; } +void Sema::checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment) { + const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID()); + if (!Info->IsFunctionDeclarationCommand) + return; + + unsigned DiagSelect; + switch (Comment->getCommandID()) { + case CommandTraits::KCI_function: + DiagSelect = !isAnyFunctionDecl() ? 1 : 0; + break; + case CommandTraits::KCI_functiongroup: + DiagSelect = !isAnyFunctionDecl() ? 2 : 0; + break; + case CommandTraits::KCI_method: + DiagSelect = !isObjCMethodDecl() ? 3 : 0; + break; + case CommandTraits::KCI_methodgroup: + DiagSelect = !isObjCMethodDecl() ? 4 : 0; + break; + case CommandTraits::KCI_callback: + DiagSelect = !isFunctionPointerVarDecl() ? 5 : 0; + break; + default: + DiagSelect = 0; + break; + } + if (DiagSelect) + Diag(Comment->getLocation(), diag::warn_doc_function_method_decl_mismatch) + << Comment->getCommandMarker() + << (DiagSelect-1) << (DiagSelect-1) + << Comment->getSourceRange(); +} + +void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) { + const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID()); + if (!Info->IsRecordLikeDeclarationCommand) + return; + unsigned DiagSelect; + switch (Comment->getCommandID()) { + case CommandTraits::KCI_class: + DiagSelect = !isClassOrStructDecl() ? 1 : 0; + break; + case CommandTraits::KCI_interface: + DiagSelect = !isObjCInterfaceDecl() ? 2 : 0; + break; + case CommandTraits::KCI_protocol: + DiagSelect = !isObjCProtocolDecl() ? 3 : 0; + break; + case CommandTraits::KCI_struct: + DiagSelect = !isClassOrStructDecl() ? 4 : 0; + break; + case CommandTraits::KCI_union: + DiagSelect = !isUnionDecl() ? 5 : 0; + break; + default: + DiagSelect = 0; + break; + } + if (DiagSelect) + Diag(Comment->getLocation(), diag::warn_doc_api_container_decl_mismatch) + << Comment->getCommandMarker() + << (DiagSelect-1) << (DiagSelect-1) + << Comment->getSourceRange(); +} + +void Sema::checkContainerDecl(const BlockCommandComment *Comment) { + const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID()); + if (!Info->IsRecordLikeDetailCommand || isRecordLikeDecl()) + return; + unsigned DiagSelect; + switch (Comment->getCommandID()) { + case CommandTraits::KCI_classdesign: + DiagSelect = 1; + break; + case CommandTraits::KCI_coclass: + DiagSelect = 2; + break; + case CommandTraits::KCI_dependency: + DiagSelect = 3; + break; + case CommandTraits::KCI_helper: + DiagSelect = 4; + break; + case CommandTraits::KCI_helperclass: + DiagSelect = 5; + break; + case CommandTraits::KCI_helps: + DiagSelect = 6; + break; + case CommandTraits::KCI_instancesize: + DiagSelect = 7; + break; + case CommandTraits::KCI_ownership: + DiagSelect = 8; + break; + case CommandTraits::KCI_performance: + DiagSelect = 9; + break; + case CommandTraits::KCI_security: + DiagSelect = 10; + break; + case CommandTraits::KCI_superclass: + DiagSelect = 11; + break; + default: + DiagSelect = 0; + break; + } + if (DiagSelect) + Diag(Comment->getLocation(), diag::warn_doc_container_decl_mismatch) + << Comment->getCommandMarker() + << (DiagSelect-1) + << Comment->getSourceRange(); +} + void Sema::actOnParamCommandDirectionArg(ParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, @@ -158,15 +285,19 @@ void Sema::actOnParamCommandFinish(ParamCommandComment *Command, checkBlockCommandEmptyParagraph(Command); } -TParamCommandComment *Sema::actOnTParamCommandStart(SourceLocation LocBegin, - SourceLocation LocEnd, - unsigned CommandID) { +TParamCommandComment *Sema::actOnTParamCommandStart( + SourceLocation LocBegin, + SourceLocation LocEnd, + unsigned CommandID, + CommandMarkerKind CommandMarker) { TParamCommandComment *Command = - new (Allocator) TParamCommandComment(LocBegin, LocEnd, CommandID); + new (Allocator) TParamCommandComment(LocBegin, LocEnd, CommandID, + CommandMarker); if (!isTemplateOrSpecialization()) Diag(Command->getLocation(), diag::warn_doc_tparam_not_attached_to_a_template_decl) + << CommandMarker << Command->getCommandNameRange(Traits); return Command; @@ -324,12 +455,15 @@ VerbatimLineComment *Sema::actOnVerbatimLine(SourceLocation LocBegin, unsigned CommandID, SourceLocation TextBegin, StringRef Text) { - return new (Allocator) VerbatimLineComment( + VerbatimLineComment *VL = new (Allocator) VerbatimLineComment( LocBegin, TextBegin.getLocWithOffset(Text.size()), CommandID, TextBegin, Text); + checkFunctionDeclVerbatimLine(VL); + checkContainerDeclVerbatimLine(VL); + return VL; } HTMLStartTagComment *Sema::actOnHTMLStartTagStart(SourceLocation LocBegin, @@ -430,6 +564,7 @@ void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) { if (!DiagLoc.isValid()) DiagLoc = Command->getCommandNameRange(Traits).getEnd(); Diag(DiagLoc, diag::warn_doc_block_command_empty_paragraph) + << Command->getCommandMarker() << Command->getCommandName(Traits) << Command->getSourceRange(); } @@ -457,14 +592,19 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { } Diag(Command->getLocation(), diag::warn_doc_returns_attached_to_a_void_function) + << Command->getCommandMarker() << Command->getCommandName(Traits) << DiagKind << Command->getSourceRange(); } return; } + else if (isObjCPropertyDecl()) + return; + Diag(Command->getLocation(), diag::warn_doc_returns_not_attached_to_a_function_decl) + << Command->getCommandMarker() << Command->getCommandName(Traits) << Command->getSourceRange(); } @@ -484,6 +624,12 @@ void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) { return; } PrevCommand = ReturnsCommand; + } else if (Info->IsHeaderfileCommand) { + if (!HeaderfileCommand) { + HeaderfileCommand = Command; + return; + } + PrevCommand = HeaderfileCommand; } else { // We don't want to check this command for duplicates. return; @@ -491,15 +637,18 @@ void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) { StringRef CommandName = Command->getCommandName(Traits); StringRef PrevCommandName = PrevCommand->getCommandName(Traits); Diag(Command->getLocation(), diag::warn_doc_block_command_duplicate) + << Command->getCommandMarker() << CommandName << Command->getSourceRange(); if (CommandName == PrevCommandName) Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous) + << PrevCommand->getCommandMarker() << PrevCommandName << PrevCommand->getSourceRange(); else Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous_alias) + << PrevCommand->getCommandMarker() << PrevCommandName << CommandName; } @@ -559,11 +708,11 @@ void Sema::resolveParamCommandIndexes(const FullComment *FC) { return; } - llvm::SmallVector<ParamCommandComment *, 8> UnresolvedParamCommands; + SmallVector<ParamCommandComment *, 8> UnresolvedParamCommands; // Comment AST nodes that correspond to \c ParamVars for which we have // found a \\param command or NULL if no documentation was found so far. - llvm::SmallVector<ParamCommandComment *, 8> ParamVarDocs; + SmallVector<ParamCommandComment *, 8> ParamVarDocs; ArrayRef<const ParmVarDecl *> ParamVars = getParamVars(); ParamVarDocs.resize(ParamVars.size(), NULL); @@ -596,7 +745,7 @@ void Sema::resolveParamCommandIndexes(const FullComment *FC) { } // Find parameter declarations that have no corresponding \\param. - llvm::SmallVector<const ParmVarDecl *, 8> OrphanedParamDecls; + SmallVector<const ParmVarDecl *, 8> OrphanedParamDecls; for (unsigned i = 0, e = ParamVarDocs.size(); i != e; ++i) { if (!ParamVarDocs[i]) OrphanedParamDecls.push_back(ParamVars[i]); @@ -645,6 +794,40 @@ bool Sema::isFunctionDecl() { return ThisDeclInfo->getKind() == DeclInfo::FunctionKind; } +bool Sema::isAnyFunctionDecl() { + return isFunctionDecl() && ThisDeclInfo->CurrentDecl && + isa<FunctionDecl>(ThisDeclInfo->CurrentDecl); +} + +bool Sema::isObjCMethodDecl() { + return isFunctionDecl() && ThisDeclInfo->CurrentDecl && + isa<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl); +} + +/// isFunctionPointerVarDecl - returns 'true' if declaration is a pointer to +/// function decl. +bool Sema::isFunctionPointerVarDecl() { + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + if (ThisDeclInfo->getKind() == DeclInfo::VariableKind) { + if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(ThisDeclInfo->CurrentDecl)) { + QualType QT = VD->getType(); + return QT->isFunctionPointerType(); + } + } + return false; +} + +bool Sema::isObjCPropertyDecl() { + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + return ThisDeclInfo->CurrentDecl->getKind() == Decl::ObjCProperty; +} + bool Sema::isTemplateOrSpecialization() { if (!ThisDeclInfo) return false; @@ -653,6 +836,54 @@ bool Sema::isTemplateOrSpecialization() { return ThisDeclInfo->getTemplateKind() != DeclInfo::NotTemplate; } +bool Sema::isRecordLikeDecl() { + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + return isUnionDecl() || isClassOrStructDecl() + || isObjCInterfaceDecl() || isObjCProtocolDecl(); +} + +bool Sema::isUnionDecl() { + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + if (const RecordDecl *RD = + dyn_cast_or_null<RecordDecl>(ThisDeclInfo->CurrentDecl)) + return RD->isUnion(); + return false; +} + +bool Sema::isClassOrStructDecl() { + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + return ThisDeclInfo->CurrentDecl && + isa<RecordDecl>(ThisDeclInfo->CurrentDecl) && + !isUnionDecl(); +} + +bool Sema::isObjCInterfaceDecl() { + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + return ThisDeclInfo->CurrentDecl && + isa<ObjCInterfaceDecl>(ThisDeclInfo->CurrentDecl); +} + +bool Sema::isObjCProtocolDecl() { + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + return ThisDeclInfo->CurrentDecl && + isa<ObjCProtocolDecl>(ThisDeclInfo->CurrentDecl); +} + ArrayRef<const ParmVarDecl *> Sema::getParamVars() { if (!ThisDeclInfo->IsFilled) inspectThisDecl(); diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index 7b13755..bf807ae 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -12,23 +12,24 @@ //===----------------------------------------------------------------------===// #include "clang/AST/Decl.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/TypeLoc.h" -#include "clang/AST/Stmt.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/PrettyPrinter.h" -#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Module.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Support/ErrorHandling.h" - +#include "llvm/Support/type_traits.h" #include <algorithm> using namespace clang; @@ -37,17 +38,163 @@ using namespace clang; // NamedDecl Implementation //===----------------------------------------------------------------------===// -static llvm::Optional<Visibility> getVisibilityOf(const Decl *D) { +// Visibility rules aren't rigorously externally specified, but here +// are the basic principles behind what we implement: +// +// 1. An explicit visibility attribute is generally a direct expression +// of the user's intent and should be honored. Only the innermost +// visibility attribute applies. If no visibility attribute applies, +// global visibility settings are considered. +// +// 2. There is one caveat to the above: on or in a template pattern, +// an explicit visibility attribute is just a default rule, and +// visibility can be decreased by the visibility of template +// arguments. But this, too, has an exception: an attribute on an +// explicit specialization or instantiation causes all the visibility +// restrictions of the template arguments to be ignored. +// +// 3. A variable that does not otherwise have explicit visibility can +// be restricted by the visibility of its type. +// +// 4. A visibility restriction is explicit if it comes from an +// attribute (or something like it), not a global visibility setting. +// When emitting a reference to an external symbol, visibility +// restrictions are ignored unless they are explicit. +// +// 5. When computing the visibility of a non-type, including a +// non-type member of a class, only non-type visibility restrictions +// are considered: the 'visibility' attribute, global value-visibility +// settings, and a few special cases like __private_extern. +// +// 6. When computing the visibility of a type, including a type member +// of a class, only type visibility restrictions are considered: +// the 'type_visibility' attribute and global type-visibility settings. +// However, a 'visibility' attribute counts as a 'type_visibility' +// attribute on any declaration that only has the former. +// +// The visibility of a "secondary" entity, like a template argument, +// is computed using the kind of that entity, not the kind of the +// primary entity for which we are computing visibility. For example, +// the visibility of a specialization of either of these templates: +// template <class T, bool (&compare)(T, X)> bool has_match(list<T>, X); +// template <class T, bool (&compare)(T, X)> class matcher; +// is restricted according to the type visibility of the argument 'T', +// the type visibility of 'bool(&)(T,X)', and the value visibility of +// the argument function 'compare'. That 'has_match' is a value +// and 'matcher' is a type only matters when looking for attributes +// and settings from the immediate context. + +const unsigned IgnoreExplicitVisibilityBit = 2; + +/// Kinds of LV computation. The linkage side of the computation is +/// always the same, but different things can change how visibility is +/// computed. +enum LVComputationKind { + /// Do an LV computation for, ultimately, a type. + /// Visibility may be restricted by type visibility settings and + /// the visibility of template arguments. + LVForType = NamedDecl::VisibilityForType, + + /// Do an LV computation for, ultimately, a non-type declaration. + /// Visibility may be restricted by value visibility settings and + /// the visibility of template arguments. + LVForValue = NamedDecl::VisibilityForValue, + + /// Do an LV computation for, ultimately, a type that already has + /// some sort of explicit visibility. Visibility may only be + /// restricted by the visibility of template arguments. + LVForExplicitType = (LVForType | IgnoreExplicitVisibilityBit), + + /// Do an LV computation for, ultimately, a non-type declaration + /// that already has some sort of explicit visibility. Visibility + /// may only be restricted by the visibility of template arguments. + LVForExplicitValue = (LVForValue | IgnoreExplicitVisibilityBit) +}; + +/// Does this computation kind permit us to consider additional +/// visibility settings from attributes and the like? +static bool hasExplicitVisibilityAlready(LVComputationKind computation) { + return ((unsigned(computation) & IgnoreExplicitVisibilityBit) != 0); +} + +/// Given an LVComputationKind, return one of the same type/value sort +/// that records that it already has explicit visibility. +static LVComputationKind +withExplicitVisibilityAlready(LVComputationKind oldKind) { + LVComputationKind newKind = + static_cast<LVComputationKind>(unsigned(oldKind) | + IgnoreExplicitVisibilityBit); + assert(oldKind != LVForType || newKind == LVForExplicitType); + assert(oldKind != LVForValue || newKind == LVForExplicitValue); + assert(oldKind != LVForExplicitType || newKind == LVForExplicitType); + assert(oldKind != LVForExplicitValue || newKind == LVForExplicitValue); + return newKind; +} + +static Optional<Visibility> getExplicitVisibility(const NamedDecl *D, + LVComputationKind kind) { + assert(!hasExplicitVisibilityAlready(kind) && + "asking for explicit visibility when we shouldn't be"); + return D->getExplicitVisibility((NamedDecl::ExplicitVisibilityKind) kind); +} + +/// Is the given declaration a "type" or a "value" for the purposes of +/// visibility computation? +static bool usesTypeVisibility(const NamedDecl *D) { + return isa<TypeDecl>(D) || + isa<ClassTemplateDecl>(D) || + isa<ObjCInterfaceDecl>(D); +} + +/// Does the given declaration have member specialization information, +/// and if so, is it an explicit specialization? +template <class T> static typename +llvm::enable_if_c<!llvm::is_base_of<RedeclarableTemplateDecl, T>::value, + bool>::type +isExplicitMemberSpecialization(const T *D) { + if (const MemberSpecializationInfo *member = + D->getMemberSpecializationInfo()) { + return member->isExplicitSpecialization(); + } + return false; +} + +/// For templates, this question is easier: a member template can't be +/// explicitly instantiated, so there's a single bit indicating whether +/// or not this is an explicit member specialization. +static bool isExplicitMemberSpecialization(const RedeclarableTemplateDecl *D) { + return D->isMemberSpecialization(); +} + +/// Given a visibility attribute, return the explicit visibility +/// associated with it. +template <class T> +static Visibility getVisibilityFromAttr(const T *attr) { + switch (attr->getVisibility()) { + case T::Default: + return DefaultVisibility; + case T::Hidden: + return HiddenVisibility; + case T::Protected: + return ProtectedVisibility; + } + llvm_unreachable("bad visibility kind"); +} + +/// Return the explicit visibility of the given declaration. +static Optional<Visibility> getVisibilityOf(const NamedDecl *D, + NamedDecl::ExplicitVisibilityKind kind) { + // If we're ultimately computing the visibility of a type, look for + // a 'type_visibility' attribute before looking for 'visibility'. + if (kind == NamedDecl::VisibilityForType) { + if (const TypeVisibilityAttr *A = D->getAttr<TypeVisibilityAttr>()) { + return getVisibilityFromAttr(A); + } + } + // If this declaration has an explicit visibility attribute, use it. if (const VisibilityAttr *A = D->getAttr<VisibilityAttr>()) { - switch (A->getVisibility()) { - case VisibilityAttr::Default: - return DefaultVisibility; - case VisibilityAttr::Hidden: - return HiddenVisibility; - case VisibilityAttr::Protected: - return ProtectedVisibility; - } + return getVisibilityFromAttr(A); } // If we're on Mac OS X, an 'availability' for Mac OS X attribute @@ -61,43 +208,61 @@ static llvm::Optional<Visibility> getVisibilityOf(const Decl *D) { return DefaultVisibility; } - return llvm::Optional<Visibility>(); -} - -typedef NamedDecl::LinkageInfo LinkageInfo; - -static LinkageInfo getLVForType(QualType T) { - std::pair<Linkage,Visibility> P = T->getLinkageAndVisibility(); - return LinkageInfo(P.first, P.second, T->isVisibilityExplicit()); + return None; } /// \brief Get the most restrictive linkage for the types in the given -/// template parameter list. +/// template parameter list. For visibility purposes, template +/// parameters are part of the signature of a template. static LinkageInfo -getLVForTemplateParameterList(const TemplateParameterList *Params) { - LinkageInfo LV(ExternalLinkage, DefaultVisibility, false); - for (TemplateParameterList::const_iterator P = Params->begin(), - PEnd = Params->end(); +getLVForTemplateParameterList(const TemplateParameterList *params) { + LinkageInfo LV; + for (TemplateParameterList::const_iterator P = params->begin(), + PEnd = params->end(); P != PEnd; ++P) { + + // Template type parameters are the most common and never + // contribute to visibility, pack or not. + if (isa<TemplateTypeParmDecl>(*P)) + continue; + + // Non-type template parameters can be restricted by the value type, e.g. + // template <enum X> class A { ... }; + // We have to be careful here, though, because we can be dealing with + // dependent types. if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { - if (NTTP->isExpandedParameterPack()) { - for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) { - QualType T = NTTP->getExpansionType(I); - if (!T->isDependentType()) - LV.merge(getLVForType(T)); + // Handle the non-pack case first. + if (!NTTP->isExpandedParameterPack()) { + if (!NTTP->getType()->isDependentType()) { + LV.merge(NTTP->getType()->getLinkageAndVisibility()); } continue; } - if (!NTTP->getType()->isDependentType()) { - LV.merge(getLVForType(NTTP->getType())); - continue; + // Look at all the types in an expanded pack. + for (unsigned i = 0, n = NTTP->getNumExpansionTypes(); i != n; ++i) { + QualType type = NTTP->getExpansionType(i); + if (!type->isDependentType()) + LV.merge(type->getLinkageAndVisibility()); } + continue; } - if (TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(*P)) { + // Template template parameters can be restricted by their + // template parameters, recursively. + TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); + + // Handle the non-pack case first. + if (!TTP->isExpandedParameterPack()) { LV.merge(getLVForTemplateParameterList(TTP->getTemplateParameters())); + continue; + } + + // Look at all expansions in an expanded pack. + for (unsigned i = 0, n = TTP->getNumExpansionTemplateParameters(); + i != n; ++i) { + LV.merge(getLVForTemplateParameterList( + TTP->getExpansionTemplateParameters(i))); } } @@ -105,67 +270,177 @@ getLVForTemplateParameterList(const TemplateParameterList *Params) { } /// getLVForDecl - Get the linkage and visibility for the given declaration. -static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate); +static LinkageInfo getLVForDecl(const NamedDecl *D, + LVComputationKind computation); /// \brief Get the most restrictive linkage for the types and /// declarations in the given template argument list. -static LinkageInfo getLVForTemplateArgumentList(const TemplateArgument *Args, - unsigned NumArgs, - bool OnlyTemplate) { - LinkageInfo LV(ExternalLinkage, DefaultVisibility, false); +/// +/// Note that we don't take an LVComputationKind because we always +/// want to honor the visibility of template arguments in the same way. +static LinkageInfo +getLVForTemplateArgumentList(ArrayRef<TemplateArgument> args) { + LinkageInfo LV; - for (unsigned I = 0; I != NumArgs; ++I) { - switch (Args[I].getKind()) { + for (unsigned i = 0, e = args.size(); i != e; ++i) { + const TemplateArgument &arg = args[i]; + switch (arg.getKind()) { case TemplateArgument::Null: case TemplateArgument::Integral: case TemplateArgument::Expression: - break; + continue; case TemplateArgument::Type: - LV.mergeWithMin(getLVForType(Args[I].getAsType())); - break; + LV.merge(arg.getAsType()->getLinkageAndVisibility()); + continue; case TemplateArgument::Declaration: - if (NamedDecl *ND = dyn_cast<NamedDecl>(Args[I].getAsDecl())) - LV.mergeWithMin(getLVForDecl(ND, OnlyTemplate)); - break; + if (NamedDecl *ND = dyn_cast<NamedDecl>(arg.getAsDecl())) { + assert(!usesTypeVisibility(ND)); + LV.merge(getLVForDecl(ND, LVForValue)); + } + continue; case TemplateArgument::NullPtr: - LV.mergeWithMin(getLVForType(Args[I].getNullPtrType())); - break; + LV.merge(arg.getNullPtrType()->getLinkageAndVisibility()); + continue; case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: if (TemplateDecl *Template - = Args[I].getAsTemplateOrTemplatePattern().getAsTemplateDecl()) - LV.mergeWithMin(getLVForDecl(Template, OnlyTemplate)); - break; + = arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) + LV.merge(getLVForDecl(Template, LVForValue)); + continue; case TemplateArgument::Pack: - LV.mergeWithMin(getLVForTemplateArgumentList(Args[I].pack_begin(), - Args[I].pack_size(), - OnlyTemplate)); - break; + LV.merge(getLVForTemplateArgumentList(arg.getPackAsArray())); + continue; } + llvm_unreachable("bad template argument kind"); } return LV; } static LinkageInfo -getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, - bool OnlyTemplate) { - return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), OnlyTemplate); +getLVForTemplateArgumentList(const TemplateArgumentList &TArgs) { + return getLVForTemplateArgumentList(TArgs.asArray()); } -static bool shouldConsiderTemplateVis(const FunctionDecl *fn, - const FunctionTemplateSpecializationInfo *spec) { - return !fn->hasAttr<VisibilityAttr>() || spec->isExplicitSpecialization(); +static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn, + const FunctionTemplateSpecializationInfo *specInfo) { + // Include visibility from the template parameters and arguments + // only if this is not an explicit instantiation or specialization + // with direct explicit visibility. (Implicit instantiations won't + // have a direct attribute.) + if (!specInfo->isExplicitInstantiationOrSpecialization()) + return true; + + return !fn->hasAttr<VisibilityAttr>(); +} + +/// Merge in template-related linkage and visibility for the given +/// function template specialization. +/// +/// We don't need a computation kind here because we can assume +/// LVForValue. +/// +/// \param[out] LV the computation to use for the parent +static void +mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn, + const FunctionTemplateSpecializationInfo *specInfo) { + bool considerVisibility = + shouldConsiderTemplateVisibility(fn, specInfo); + + // Merge information from the template parameters. + FunctionTemplateDecl *temp = specInfo->getTemplate(); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters()); + LV.mergeMaybeWithVisibility(tempLV, considerVisibility); + + // Merge information from the template arguments. + const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments; + LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs); + LV.mergeMaybeWithVisibility(argsLV, considerVisibility); +} + +/// Does the given declaration have a direct visibility attribute +/// that would match the given rules? +static bool hasDirectVisibilityAttribute(const NamedDecl *D, + LVComputationKind computation) { + switch (computation) { + case LVForType: + case LVForExplicitType: + if (D->hasAttr<TypeVisibilityAttr>()) + return true; + // fallthrough + case LVForValue: + case LVForExplicitValue: + if (D->hasAttr<VisibilityAttr>()) + return true; + return false; + } + llvm_unreachable("bad visibility computation kind"); +} + +/// Should we consider visibility associated with the template +/// arguments and parameters of the given class template specialization? +static bool shouldConsiderTemplateVisibility( + const ClassTemplateSpecializationDecl *spec, + LVComputationKind computation) { + // Include visibility from the template parameters and arguments + // only if this is not an explicit instantiation or specialization + // with direct explicit visibility (and note that implicit + // instantiations won't have a direct attribute). + // + // Furthermore, we want to ignore template parameters and arguments + // for an explicit specialization when computing the visibility of a + // member thereof with explicit visibility. + // + // This is a bit complex; let's unpack it. + // + // An explicit class specialization is an independent, top-level + // declaration. As such, if it or any of its members has an + // explicit visibility attribute, that must directly express the + // user's intent, and we should honor it. The same logic applies to + // an explicit instantiation of a member of such a thing. + + // Fast path: if this is not an explicit instantiation or + // specialization, we always want to consider template-related + // visibility restrictions. + if (!spec->isExplicitInstantiationOrSpecialization()) + return true; + + // This is the 'member thereof' check. + if (spec->isExplicitSpecialization() && + hasExplicitVisibilityAlready(computation)) + return false; + + return !hasDirectVisibilityAttribute(spec, computation); } -static bool -shouldConsiderTemplateVis(const ClassTemplateSpecializationDecl *d) { - return !d->hasAttr<VisibilityAttr>() || d->isExplicitSpecialization(); +/// Merge in template-related linkage and visibility for the given +/// class template specialization. +static void mergeTemplateLV(LinkageInfo &LV, + const ClassTemplateSpecializationDecl *spec, + LVComputationKind computation) { + bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation); + + // Merge information from the template parameters, but ignore + // visibility if we're only considering template arguments. + + ClassTemplateDecl *temp = spec->getSpecializedTemplate(); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters()); + LV.mergeMaybeWithVisibility(tempLV, + considerVisibility && !hasExplicitVisibilityAlready(computation)); + + // Merge information from the template arguments. We ignore + // template-argument visibility if we've got an explicit + // instantiation with a visibility attribute. + const TemplateArgumentList &templateArgs = spec->getTemplateArgs(); + LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs); + LV.mergeMaybeWithVisibility(argsLV, considerVisibility); } static bool useInlineVisibilityHidden(const NamedDecl *D) { @@ -196,8 +471,13 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) { FD->hasBody(Def) && Def->isInlined() && !Def->hasAttr<GNUInlineAttr>(); } +template <typename T> static bool isInExternCContext(T *D) { + const T *First = D->getFirstDeclaration(); + return First->getDeclContext()->isExternCContext(); +} + static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, - bool OnlyTemplate) { + LVComputationKind computation) { assert(D->getDeclContext()->getRedeclContext()->isFileContext() && "Not a name having namespace scope"); ASTContext &Context = D->getASTContext(); @@ -218,26 +498,24 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // declared to have external linkage; or (there is no equivalent in C99) if (Context.getLangOpts().CPlusPlus && Var->getType().isConstQualified() && - !Var->getType().isVolatileQualified() && - Var->getStorageClass() != SC_Extern && - Var->getStorageClass() != SC_PrivateExtern) { - bool FoundExtern = false; - for (const VarDecl *PrevVar = Var->getPreviousDecl(); - PrevVar && !FoundExtern; - PrevVar = PrevVar->getPreviousDecl()) - if (isExternalLinkage(PrevVar->getLinkage())) - FoundExtern = true; - - if (!FoundExtern) - return LinkageInfo::internal(); - } - if (Var->getStorageClass() == SC_None) { + !Var->getType().isVolatileQualified()) { const VarDecl *PrevVar = Var->getPreviousDecl(); - for (; PrevVar; PrevVar = PrevVar->getPreviousDecl()) - if (PrevVar->getStorageClass() == SC_PrivateExtern) - break; if (PrevVar) return PrevVar->getLinkageAndVisibility(); + + if (Var->getStorageClass() != SC_Extern && + Var->getStorageClass() != SC_PrivateExtern) + return LinkageInfo::internal(); + } + + for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar; + PrevVar = PrevVar->getPreviousDecl()) { + if (PrevVar->getStorageClass() == SC_PrivateExtern && + Var->getStorageClass() == SC_None) + return PrevVar->getLinkageAndVisibility(); + // Explicitly declared static. + if (PrevVar->getStorageClass() == SC_Static) + return LinkageInfo::internal(); } } else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) { // C++ [temp]p4: @@ -251,7 +529,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, Function = cast<FunctionDecl>(D); // Explicitly declared static. - if (Function->getStorageClass() == SC_Static) + if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) return LinkageInfo(InternalLinkage, DefaultVisibility, false); } else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) { // - a data member of an anonymous union. @@ -262,8 +540,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (D->isInAnonymousNamespace()) { const VarDecl *Var = dyn_cast<VarDecl>(D); const FunctionDecl *Func = dyn_cast<FunctionDecl>(D); - if ((!Var || !Var->getDeclContext()->isExternCContext()) && - (!Func || !Func->getDeclContext()->isExternCContext())) + if ((!Var || !isInExternCContext(Var)) && + (!Func || !isInExternCContext(Func))) return LinkageInfo::uniqueExternal(); } @@ -275,31 +553,41 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // external. LinkageInfo LV; - if (!OnlyTemplate) { - if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility()) { + if (!hasExplicitVisibilityAlready(computation)) { + if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) { LV.mergeVisibility(*Vis, true); } else { // If we're declared in a namespace with a visibility attribute, - // use that namespace's visibility, but don't call it explicit. + // use that namespace's visibility, and it still counts as explicit. for (const DeclContext *DC = D->getDeclContext(); !isa<TranslationUnitDecl>(DC); DC = DC->getParent()) { const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC); if (!ND) continue; - if (llvm::Optional<Visibility> Vis = ND->getExplicitVisibility()) { + if (Optional<Visibility> Vis = getExplicitVisibility(ND, computation)) { LV.mergeVisibility(*Vis, true); break; } } } - } - if (!OnlyTemplate) { - LV.mergeVisibility(Context.getLangOpts().getVisibilityMode()); - // If we're paying attention to global visibility, apply - // -finline-visibility-hidden if this is an inline method. - if (!LV.visibilityExplicit() && useInlineVisibilityHidden(D)) - LV.mergeVisibility(HiddenVisibility, true); + // Add in global settings if the above didn't give us direct visibility. + if (!LV.isVisibilityExplicit()) { + // Use global type/value visibility as appropriate. + Visibility globalVisibility; + if (computation == LVForValue) { + globalVisibility = Context.getLangOpts().getValueVisibilityMode(); + } else { + assert(computation == LVForType); + globalVisibility = Context.getLangOpts().getTypeVisibilityMode(); + } + LV.mergeVisibility(globalVisibility, /*explicit*/ false); + + // If we're paying attention to global visibility, apply + // -finline-visibility-hidden if this is an inline method. + if (useInlineVisibilityHidden(D)) + LV.mergeVisibility(HiddenVisibility, true); + } } // C++ [basic.link]p4: @@ -330,12 +618,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // // Note that we don't want to make the variable non-external // because of this, but unique-external linkage suits us. - if (Context.getLangOpts().CPlusPlus && - !Var->getDeclContext()->isExternCContext()) { - LinkageInfo TypeLV = getLVForType(Var->getType()); - if (TypeLV.linkage() != ExternalLinkage) + if (Context.getLangOpts().CPlusPlus && !isInExternCContext(Var)) { + LinkageInfo TypeLV = Var->getType()->getLinkageAndVisibility(); + if (TypeLV.getLinkage() != ExternalLinkage) return LinkageInfo::uniqueExternal(); - LV.mergeVisibility(TypeLV); + if (!LV.isVisibilityExplicit()) + LV.mergeVisibility(TypeLV); } if (Var->getStorageClass() == SC_PrivateExtern) @@ -355,30 +643,9 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (Function->getStorageClass() == SC_PrivateExtern) LV.mergeVisibility(HiddenVisibility, true); - // C99 6.2.2p5: - // If the declaration of an identifier for a function has no - // storage-class specifier, its linkage is determined exactly - // as if it were declared with the storage-class specifier - // extern. - if (!Context.getLangOpts().CPlusPlus && - (Function->getStorageClass() == SC_Extern || - Function->getStorageClass() == SC_PrivateExtern || - Function->getStorageClass() == SC_None)) { - // C99 6.2.2p4: - // For an identifier declared with the storage-class specifier - // extern in a scope in which a prior declaration of that - // identifier is visible, if the prior declaration specifies - // internal or external linkage, the linkage of the identifier - // at the later declaration is the same as the linkage - // specified at the prior declaration. If no prior declaration - // is visible, or if the prior declaration specifies no - // linkage, then the identifier has external linkage. - if (const FunctionDecl *PrevFunc = Function->getPreviousDecl()) { - LinkageInfo PrevLV = getLVForDecl(PrevFunc, OnlyTemplate); - if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage()); - LV.mergeVisibility(PrevLV); - } - } + // Note that Sema::MergeCompatibleFunctionDecls already takes care of + // merging storage classes and visibility attributes, so we don't have to + // look at previous decls in here. // In C++, then if the type of the function uses a type with // unique-external linkage, it's not legally usable from outside @@ -389,21 +656,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, Function->getType()->getLinkage() == UniqueExternalLinkage) return LinkageInfo::uniqueExternal(); - // Consider LV from the template and the template arguments unless - // this is an explicit specialization with a visibility attribute. + // Consider LV from the template and the template arguments. + // We're at file scope, so we do not need to worry about nested + // specializations. if (FunctionTemplateSpecializationInfo *specInfo = Function->getTemplateSpecializationInfo()) { - LinkageInfo TempLV = getLVForDecl(specInfo->getTemplate(), true); - const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments; - LinkageInfo ArgsLV = getLVForTemplateArgumentList(templateArgs, - OnlyTemplate); - if (shouldConsiderTemplateVis(Function, specInfo)) { - LV.mergeWithMin(TempLV); - LV.mergeWithMin(ArgsLV); - } else { - LV.mergeLinkage(TempLV); - LV.mergeLinkage(ArgsLV); - } + mergeTemplateLV(LV, Function, specInfo); } // - a named class (Clause 9), or an unnamed class defined in a @@ -414,41 +672,33 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // has the typedef name for linkage purposes (7.1.3); or } else if (const TagDecl *Tag = dyn_cast<TagDecl>(D)) { // Unnamed tags have no linkage. - if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) + if (!Tag->hasNameForLinkage()) return LinkageInfo::none(); // If this is a class template specialization, consider the - // linkage of the template and template arguments. + // linkage of the template and template arguments. We're at file + // scope, so we do not need to worry about nested specializations. if (const ClassTemplateSpecializationDecl *spec = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) { - // From the template. - LinkageInfo TempLV = getLVForDecl(spec->getSpecializedTemplate(), true); - - // The arguments at which the template was instantiated. - const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs(); - LinkageInfo ArgsLV = getLVForTemplateArgumentList(TemplateArgs, - OnlyTemplate); - if (shouldConsiderTemplateVis(spec)) { - LV.mergeWithMin(TempLV); - LV.mergeWithMin(ArgsLV); - } else { - LV.mergeLinkage(TempLV); - LV.mergeLinkage(ArgsLV); - } + mergeTemplateLV(LV, spec, computation); } // - an enumerator belonging to an enumeration with external linkage; } else if (isa<EnumConstantDecl>(D)) { LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()), - OnlyTemplate); - if (!isExternalLinkage(EnumLV.linkage())) + computation); + if (!isExternalLinkage(EnumLV.getLinkage())) return LinkageInfo::none(); LV.merge(EnumLV); // - a template, unless it is a function template that has // internal linkage (Clause 14); } else if (const TemplateDecl *temp = dyn_cast<TemplateDecl>(D)) { - LV.merge(getLVForTemplateParameterList(temp->getTemplateParameters())); + bool considerVisibility = !hasExplicitVisibilityAlready(computation); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters()); + LV.mergeMaybeWithVisibility(tempLV, considerVisibility); + // - a namespace (7.3), unless it is declared within an unnamed // namespace. } else if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace()) { @@ -466,13 +716,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // If we ended up with non-external linkage, visibility should // always be default. - if (LV.linkage() != ExternalLinkage) - return LinkageInfo(LV.linkage(), DefaultVisibility, false); + if (LV.getLinkage() != ExternalLinkage) + return LinkageInfo(LV.getLinkage(), DefaultVisibility, false); return LV; } -static LinkageInfo getLVForClassMember(const NamedDecl *D, bool OnlyTemplate) { +static LinkageInfo getLVForClassMember(const NamedDecl *D, + LVComputationKind computation) { // Only certain class members have linkage. Note that fields don't // really have linkage, but it's convenient to say they do for the // purposes of calculating linkage of pointer-to-data-member @@ -480,46 +731,45 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, bool OnlyTemplate) { if (!(isa<CXXMethodDecl>(D) || isa<VarDecl>(D) || isa<FieldDecl>(D) || - (isa<TagDecl>(D) && - (D->getDeclName() || cast<TagDecl>(D)->getTypedefNameForAnonDecl())))) + isa<TagDecl>(D))) return LinkageInfo::none(); LinkageInfo LV; // If we have an explicit visibility attribute, merge that in. - if (!OnlyTemplate) { - if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility()) + if (!hasExplicitVisibilityAlready(computation)) { + if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) LV.mergeVisibility(*Vis, true); // If we're paying attention to global visibility, apply // -finline-visibility-hidden if this is an inline method. // // Note that we do this before merging information about // the class visibility. - if (!LV.visibilityExplicit() && useInlineVisibilityHidden(D)) + if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D)) LV.mergeVisibility(HiddenVisibility, true); } // If this class member has an explicit visibility attribute, the only // thing that can change its visibility is the template arguments, so // only look for them when processing the class. - bool ClassOnlyTemplate = LV.visibilityExplicit() ? true : OnlyTemplate; - - // If this member has an visibility attribute, ClassF will exclude - // attributes on the class or command line options, keeping only information - // about the template instantiation. If the member has no visibility - // attributes, mergeWithMin behaves like merge, so in both cases mergeWithMin - // produces the desired result. - LV.mergeWithMin(getLVForDecl(cast<RecordDecl>(D->getDeclContext()), - ClassOnlyTemplate)); - if (!isExternalLinkage(LV.linkage())) + LVComputationKind classComputation = computation; + if (LV.isVisibilityExplicit()) + classComputation = withExplicitVisibilityAlready(computation); + + LinkageInfo classLV = + getLVForDecl(cast<RecordDecl>(D->getDeclContext()), classComputation); + if (!isExternalLinkage(classLV.getLinkage())) return LinkageInfo::none(); // If the class already has unique-external linkage, we can't improve. - if (LV.linkage() == UniqueExternalLinkage) + if (classLV.getLinkage() == UniqueExternalLinkage) return LinkageInfo::uniqueExternal(); - if (!OnlyTemplate) - LV.mergeVisibility(D->getASTContext().getLangOpts().getVisibilityMode()); + // Otherwise, don't merge in classLV yet, because in certain cases + // we need to completely ignore the visibility from it. + + // Specifically, if this decl exists and has an explicit attribute. + const NamedDecl *explicitSpecSuppressor = 0; if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { // If the type of the function uses a type with unique-external @@ -531,192 +781,269 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, bool OnlyTemplate) { // the template parameters and arguments. if (FunctionTemplateSpecializationInfo *spec = MD->getTemplateSpecializationInfo()) { - const TemplateArgumentList &TemplateArgs = *spec->TemplateArguments; - LinkageInfo ArgsLV = getLVForTemplateArgumentList(TemplateArgs, - OnlyTemplate); - TemplateParameterList *TemplateParams = - spec->getTemplate()->getTemplateParameters(); - LinkageInfo ParamsLV = getLVForTemplateParameterList(TemplateParams); - if (shouldConsiderTemplateVis(MD, spec)) { - LV.mergeWithMin(ArgsLV); - if (!OnlyTemplate) - LV.mergeWithMin(ParamsLV); - } else { - LV.mergeLinkage(ArgsLV); - if (!OnlyTemplate) - LV.mergeLinkage(ParamsLV); + mergeTemplateLV(LV, MD, spec); + if (spec->isExplicitSpecialization()) { + explicitSpecSuppressor = MD; + } else if (isExplicitMemberSpecialization(spec->getTemplate())) { + explicitSpecSuppressor = spec->getTemplate()->getTemplatedDecl(); } + } else if (isExplicitMemberSpecialization(MD)) { + explicitSpecSuppressor = MD; } - // Note that in contrast to basically every other situation, we - // *do* apply -fvisibility to method declarations. - } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { if (const ClassTemplateSpecializationDecl *spec = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { - // Merge template argument/parameter information for member - // class template specializations. - const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs(); - LinkageInfo ArgsLV = getLVForTemplateArgumentList(TemplateArgs, - OnlyTemplate); - TemplateParameterList *TemplateParams = - spec->getSpecializedTemplate()->getTemplateParameters(); - LinkageInfo ParamsLV = getLVForTemplateParameterList(TemplateParams); - if (shouldConsiderTemplateVis(spec)) { - LV.mergeWithMin(ArgsLV); - if (!OnlyTemplate) - LV.mergeWithMin(ParamsLV); + mergeTemplateLV(LV, spec, computation); + if (spec->isExplicitSpecialization()) { + explicitSpecSuppressor = spec; } else { - LV.mergeLinkage(ArgsLV); - if (!OnlyTemplate) - LV.mergeLinkage(ParamsLV); + const ClassTemplateDecl *temp = spec->getSpecializedTemplate(); + if (isExplicitMemberSpecialization(temp)) { + explicitSpecSuppressor = temp->getTemplatedDecl(); + } } + } else if (isExplicitMemberSpecialization(RD)) { + explicitSpecSuppressor = RD; } // Static data members. } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { // Modify the variable's linkage by its type, but ignore the // type's visibility unless it's a definition. - LinkageInfo TypeLV = getLVForType(VD->getType()); - if (TypeLV.linkage() != ExternalLinkage) - LV.mergeLinkage(UniqueExternalLinkage); - LV.mergeVisibility(TypeLV); - } + LinkageInfo typeLV = VD->getType()->getLinkageAndVisibility(); + LV.mergeMaybeWithVisibility(typeLV, + !LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit()); - return LV; -} + if (isExplicitMemberSpecialization(VD)) { + explicitSpecSuppressor = VD; + } -static void clearLinkageForClass(const CXXRecordDecl *record) { - for (CXXRecordDecl::decl_iterator - i = record->decls_begin(), e = record->decls_end(); i != e; ++i) { - Decl *child = *i; - if (isa<NamedDecl>(child)) - cast<NamedDecl>(child)->ClearLinkageCache(); + // Template members. + } else if (const TemplateDecl *temp = dyn_cast<TemplateDecl>(D)) { + bool considerVisibility = + (!LV.isVisibilityExplicit() && + !classLV.isVisibilityExplicit() && + !hasExplicitVisibilityAlready(computation)); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters()); + LV.mergeMaybeWithVisibility(tempLV, considerVisibility); + + if (const RedeclarableTemplateDecl *redeclTemp = + dyn_cast<RedeclarableTemplateDecl>(temp)) { + if (isExplicitMemberSpecialization(redeclTemp)) { + explicitSpecSuppressor = temp->getTemplatedDecl(); + } + } } -} -void NamedDecl::anchor() { } + // We should never be looking for an attribute directly on a template. + assert(!explicitSpecSuppressor || !isa<TemplateDecl>(explicitSpecSuppressor)); -void NamedDecl::ClearLinkageCache() { - // Note that we can't skip clearing the linkage of children just - // because the parent doesn't have cached linkage: we don't cache - // when computing linkage for parent contexts. + // If this member is an explicit member specialization, and it has + // an explicit attribute, ignore visibility from the parent. + bool considerClassVisibility = true; + if (explicitSpecSuppressor && + // optimization: hasDVA() is true only with explicit visibility. + LV.isVisibilityExplicit() && + classLV.getVisibility() != DefaultVisibility && + hasDirectVisibilityAttribute(explicitSpecSuppressor, computation)) { + considerClassVisibility = false; + } - HasCachedLinkage = 0; + // Finally, merge in information from the class. + LV.mergeMaybeWithVisibility(classLV, considerClassVisibility); + return LV; +} - // If we're changing the linkage of a class, we need to reset the - // linkage of child declarations, too. - if (const CXXRecordDecl *record = dyn_cast<CXXRecordDecl>(this)) - clearLinkageForClass(record); +void NamedDecl::anchor() { } - if (ClassTemplateDecl *temp = - dyn_cast<ClassTemplateDecl>(const_cast<NamedDecl*>(this))) { - // Clear linkage for the template pattern. - CXXRecordDecl *record = temp->getTemplatedDecl(); - record->HasCachedLinkage = 0; - clearLinkageForClass(record); +bool NamedDecl::isLinkageValid() const { + if (!HasCachedLinkage) + return true; - // We need to clear linkage for specializations, too. - for (ClassTemplateDecl::spec_iterator - i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i) - i->ClearLinkageCache(); - } + return getLVForDecl(this, LVForExplicitValue).getLinkage() == + Linkage(CachedLinkage); +} - // Clear cached linkage for function template decls, too. - if (FunctionTemplateDecl *temp = - dyn_cast<FunctionTemplateDecl>(const_cast<NamedDecl*>(this))) { - temp->getTemplatedDecl()->ClearLinkageCache(); - for (FunctionTemplateDecl::spec_iterator - i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i) - i->ClearLinkageCache(); - } - +bool NamedDecl::hasExternalLinkageUncached() const { + return getLVForDecl(this, LVForExplicitValue).getLinkage() == ExternalLinkage; } Linkage NamedDecl::getLinkage() const { - if (HasCachedLinkage) { - assert(Linkage(CachedLinkage) == - getLVForDecl(this, true).linkage()); + if (HasCachedLinkage) return Linkage(CachedLinkage); - } - CachedLinkage = getLVForDecl(this, true).linkage(); + // We don't care about visibility here, so ask for the cheapest + // possible visibility analysis. + CachedLinkage = getLVForDecl(this, LVForExplicitValue).getLinkage(); HasCachedLinkage = 1; + +#ifndef NDEBUG + verifyLinkage(); +#endif + return Linkage(CachedLinkage); } LinkageInfo NamedDecl::getLinkageAndVisibility() const { - LinkageInfo LI = getLVForDecl(this, false); - assert(!HasCachedLinkage || Linkage(CachedLinkage) == LI.linkage()); + LVComputationKind computation = + (usesTypeVisibility(this) ? LVForType : LVForValue); + LinkageInfo LI = getLVForDecl(this, computation); + if (HasCachedLinkage) { + assert(Linkage(CachedLinkage) == LI.getLinkage()); + return LI; + } HasCachedLinkage = 1; - CachedLinkage = LI.linkage(); + CachedLinkage = LI.getLinkage(); + +#ifndef NDEBUG + verifyLinkage(); +#endif + return LI; } -llvm::Optional<Visibility> NamedDecl::getExplicitVisibility() const { - // Use the most recent declaration of a variable. - if (const VarDecl *Var = dyn_cast<VarDecl>(this)) { - if (llvm::Optional<Visibility> V = - getVisibilityOf(Var->getMostRecentDecl())) - return V; +void NamedDecl::verifyLinkage() const { + // In C (because of gnu inline) and in c++ with microsoft extensions an + // static can follow an extern, so we can have two decls with different + // linkages. + const LangOptions &Opts = getASTContext().getLangOpts(); + if (!Opts.CPlusPlus || Opts.MicrosoftExt) + return; + + // We have just computed the linkage for this decl. By induction we know + // that all other computed linkages match, check that the one we just computed + // also does. + NamedDecl *D = NULL; + for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { + NamedDecl *T = cast<NamedDecl>(*I); + if (T == this) + continue; + if (T->HasCachedLinkage != 0) { + D = T; + break; + } + } + assert(!D || D->CachedLinkage == CachedLinkage); +} + +Optional<Visibility> +NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const { + // Check the declaration itself first. + if (Optional<Visibility> V = getVisibilityOf(this, kind)) + return V; + + // If this is a member class of a specialization of a class template + // and the corresponding decl has explicit visibility, use that. + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) { + CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass(); + if (InstantiatedFrom) + return getVisibilityOf(InstantiatedFrom, kind); + } + + // If there wasn't explicit visibility there, and this is a + // specialization of a class template, check for visibility + // on the pattern. + if (const ClassTemplateSpecializationDecl *spec + = dyn_cast<ClassTemplateSpecializationDecl>(this)) + return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(), + kind); + // Use the most recent declaration. + const NamedDecl *MostRecent = cast<NamedDecl>(this->getMostRecentDecl()); + if (MostRecent != this) + return MostRecent->getExplicitVisibility(kind); + + if (const VarDecl *Var = dyn_cast<VarDecl>(this)) { if (Var->isStaticDataMember()) { VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember(); if (InstantiatedFrom) - return getVisibilityOf(InstantiatedFrom); + return getVisibilityOf(InstantiatedFrom, kind); } - return llvm::Optional<Visibility>(); + return None; } - // Use the most recent declaration of a function, and also handle - // function template specializations. + // Also handle function template specializations. if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(this)) { - if (llvm::Optional<Visibility> V - = getVisibilityOf(fn->getMostRecentDecl())) - return V; - // If the function is a specialization of a template with an // explicit visibility attribute, use that. if (FunctionTemplateSpecializationInfo *templateInfo = fn->getTemplateSpecializationInfo()) - return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl()); + return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(), + kind); // If the function is a member of a specialization of a class template // and the corresponding decl has explicit visibility, use that. FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction(); if (InstantiatedFrom) - return getVisibilityOf(InstantiatedFrom); + return getVisibilityOf(InstantiatedFrom, kind); - return llvm::Optional<Visibility>(); + return None; } - // Otherwise, just check the declaration itself first. - if (llvm::Optional<Visibility> V = getVisibilityOf(this)) - return V; - // The visibility of a template is stored in the templated decl. if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(this)) - return getVisibilityOf(TD->getTemplatedDecl()); + return getVisibilityOf(TD->getTemplatedDecl(), kind); - // If there wasn't explicit visibility there, and this is a - // specialization of a class template, check for visibility - // on the pattern. - if (const ClassTemplateSpecializationDecl *spec - = dyn_cast<ClassTemplateSpecializationDecl>(this)) - return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl()); + return None; +} - // If this is a member class of a specialization of a class template - // and the corresponding decl has explicit visibility, use that. - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) { - CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass(); - if (InstantiatedFrom) - return getVisibilityOf(InstantiatedFrom); +static LinkageInfo getLVForLocalDecl(const NamedDecl *D, + LVComputationKind computation) { + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { + if (Function->isInAnonymousNamespace() && + !Function->getDeclContext()->isExternCContext()) + return LinkageInfo::uniqueExternal(); + + // This is a "void f();" which got merged with a file static. + if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) + return LinkageInfo::internal(); + + LinkageInfo LV; + if (!hasExplicitVisibilityAlready(computation)) { + if (Optional<Visibility> Vis = + getExplicitVisibility(Function, computation)) + LV.mergeVisibility(*Vis, true); + } + + // Note that Sema::MergeCompatibleFunctionDecls already takes care of + // merging storage classes and visibility attributes, so we don't have to + // look at previous decls in here. + + return LV; } - return llvm::Optional<Visibility>(); + if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { + if (Var->hasExternalStorage()) { + if (Var->isInAnonymousNamespace() && + !Var->getDeclContext()->isExternCContext()) + return LinkageInfo::uniqueExternal(); + + LinkageInfo LV; + if (Var->getStorageClass() == SC_PrivateExtern) + LV.mergeVisibility(HiddenVisibility, true); + else if (!hasExplicitVisibilityAlready(computation)) { + if (Optional<Visibility> Vis = getExplicitVisibility(Var, computation)) + LV.mergeVisibility(*Vis, true); + } + + if (const VarDecl *Prev = Var->getPreviousDecl()) { + LinkageInfo PrevLV = getLVForDecl(Prev, computation); + if (PrevLV.getLinkage()) + LV.setLinkage(PrevLV.getLinkage()); + LV.mergeVisibility(PrevLV); + } + + return LV; + } + } + + return LinkageInfo::none(); } -static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) { +static LinkageInfo getLVForDecl(const NamedDecl *D, + LVComputationKind computation) { // Objective-C: treat all Objective-C declarations as having external // linkage. switch (D->getKind()) { @@ -751,12 +1078,11 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) { if (isa<ParmVarDecl>(ContextDecl)) DC = ContextDecl->getDeclContext()->getRedeclContext(); else - return getLVForDecl(cast<NamedDecl>(ContextDecl), - OnlyTemplate); + return getLVForDecl(cast<NamedDecl>(ContextDecl), computation); } if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) - return getLVForDecl(ND, OnlyTemplate); + return getLVForDecl(ND, computation); return LinkageInfo::external(); } @@ -767,7 +1093,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) { // Handle linkage for namespace-scope names. if (D->getDeclContext()->getRedeclContext()->isFileContext()) - return getLVForNamespaceScopeDecl(D, OnlyTemplate); + return getLVForNamespaceScopeDecl(D, computation); // C++ [basic.link]p5: // In addition, a member function, static data member, a named @@ -777,7 +1103,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) { // purposes (7.1.3), has external linkage if the name of the class // has external linkage. if (D->getDeclContext()->isRecord()) - return getLVForClassMember(D, OnlyTemplate); + return getLVForClassMember(D, computation); // C++ [basic.link]p6: // The name of a function declared in block scope and the name of @@ -790,48 +1116,8 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) { // one such matching entity, the program is ill-formed. Otherwise, // if no matching entity is found, the block scope entity receives // external linkage. - if (D->getLexicalDeclContext()->isFunctionOrMethod()) { - if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { - if (Function->isInAnonymousNamespace() && - !Function->getDeclContext()->isExternCContext()) - return LinkageInfo::uniqueExternal(); - - LinkageInfo LV; - if (!OnlyTemplate) { - if (llvm::Optional<Visibility> Vis = Function->getExplicitVisibility()) - LV.mergeVisibility(*Vis, true); - } - - if (const FunctionDecl *Prev = Function->getPreviousDecl()) { - LinkageInfo PrevLV = getLVForDecl(Prev, OnlyTemplate); - if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage()); - LV.mergeVisibility(PrevLV); - } - - return LV; - } - - if (const VarDecl *Var = dyn_cast<VarDecl>(D)) - if (Var->getStorageClass() == SC_Extern || - Var->getStorageClass() == SC_PrivateExtern) { - if (Var->isInAnonymousNamespace() && - !Var->getDeclContext()->isExternCContext()) - return LinkageInfo::uniqueExternal(); - - LinkageInfo LV; - if (Var->getStorageClass() == SC_PrivateExtern) - LV.mergeVisibility(HiddenVisibility, true); - else if (!OnlyTemplate) { - if (llvm::Optional<Visibility> Vis = Var->getExplicitVisibility()) - LV.mergeVisibility(*Vis, true); - } - - // Note that Sema::MergeVarDecl already takes care of implementing - // C99 6.2.2p4 and propagating the visibility attribute, so we don't - // have to do it here. - return LV; - } - } + if (D->getDeclContext()->isFunctionOrMethod()) + return getLVForLocalDecl(D, computation); // C++ [basic.link]p6: // Names not covered by these rules have no linkage. @@ -843,10 +1129,24 @@ std::string NamedDecl::getQualifiedNameAsString() const { } std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { + std::string QualName; + llvm::raw_string_ostream OS(QualName); + printQualifiedName(OS, P); + return OS.str(); +} + +void NamedDecl::printQualifiedName(raw_ostream &OS) const { + printQualifiedName(OS, getASTContext().getPrintingPolicy()); +} + +void NamedDecl::printQualifiedName(raw_ostream &OS, + const PrintingPolicy &P) const { const DeclContext *Ctx = getDeclContext(); - if (Ctx->isFunctionOrMethod()) - return getNameAsString(); + if (Ctx->isFunctionOrMethod()) { + printName(OS); + return; + } typedef SmallVector<const DeclContext *, 8> ContextsTy; ContextsTy Contexts; @@ -855,22 +1155,18 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { while (Ctx && isa<NamedDecl>(Ctx)) { Contexts.push_back(Ctx); Ctx = Ctx->getParent(); - }; - - std::string QualName; - llvm::raw_string_ostream OS(QualName); + } for (ContextsTy::reverse_iterator I = Contexts.rbegin(), E = Contexts.rend(); I != E; ++I) { if (const ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(*I)) { + OS << Spec->getName(); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - std::string TemplateArgsStr - = TemplateSpecializationType::PrintTemplateArgumentList( - TemplateArgs.data(), - TemplateArgs.size(), - P); - OS << Spec->getName() << TemplateArgsStr; + TemplateSpecializationType::PrintTemplateArgumentList(OS, + TemplateArgs.data(), + TemplateArgs.size(), + P); } else if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(*I)) { if (ND->isAnonymousNamespace()) OS << "<anonymous namespace>"; @@ -912,8 +1208,15 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { OS << *this; else OS << "<anonymous>"; +} - return OS.str(); +void NamedDecl::getNameForDiagnostic(raw_ostream &OS, + const PrintingPolicy &Policy, + bool Qualified) const { + if (Qualified) + printQualifiedName(OS, Policy); + else + printName(OS); } bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { @@ -1166,45 +1469,80 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartL, SourceLocation IdL, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten) { - return new (C) VarDecl(Var, DC, StartL, IdL, Id, T, TInfo, S, SCAsWritten); + StorageClass S) { + return new (C) VarDecl(Var, DC, StartL, IdL, Id, T, TInfo, S); } VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(VarDecl)); return new (Mem) VarDecl(Var, 0, SourceLocation(), SourceLocation(), 0, - QualType(), 0, SC_None, SC_None); + QualType(), 0, SC_None); } void VarDecl::setStorageClass(StorageClass SC) { assert(isLegalForVariable(SC)); - if (getStorageClass() != SC) - ClearLinkageCache(); - VarDeclBits.SClass = SC; } SourceRange VarDecl::getSourceRange() const { if (const Expr *Init = getInit()) { SourceLocation InitEnd = Init->getLocEnd(); - if (InitEnd.isValid()) + // If Init is implicit, ignore its source range and fallback on + // DeclaratorDecl::getSourceRange() to handle postfix elements. + if (InitEnd.isValid() && InitEnd != getLocation()) return SourceRange(getOuterLocStart(), InitEnd); } return DeclaratorDecl::getSourceRange(); } -bool VarDecl::isExternC() const { - if (getLinkage() != ExternalLinkage) - return false; +template<typename T> +static LanguageLinkage getLanguageLinkageTemplate(const T &D) { + // C++ [dcl.link]p1: All function types, function names with external linkage, + // and variable names with external linkage have a language linkage. + if (!isExternalLinkage(D.getLinkage())) + return NoLanguageLinkage; + + // Language linkage is a C++ concept, but saying that everything else in C has + // C language linkage fits the implementation nicely. + ASTContext &Context = D.getASTContext(); + if (!Context.getLangOpts().CPlusPlus) + return CLanguageLinkage; - const DeclContext *DC = getDeclContext(); + // C++ [dcl.link]p4: A C language linkage is ignored in determining the + // language linkage of the names of class members and the function type of + // class member functions. + const DeclContext *DC = D.getDeclContext(); if (DC->isRecord()) + return CXXLanguageLinkage; + + // If the first decl is in an extern "C" context, any other redeclaration + // will have C language linkage. If the first one is not in an extern "C" + // context, we would have reported an error for any other decl being in one. + const T *First = D.getFirstDeclaration(); + if (First->getDeclContext()->isExternCContext()) + return CLanguageLinkage; + return CXXLanguageLinkage; +} + +template<typename T> +static bool isExternCTemplate(const T &D) { + // Since the context is ignored for class members, they can only have C++ + // language linkage or no language linkage. + const DeclContext *DC = D.getDeclContext(); + if (DC->isRecord()) { + assert(D.getASTContext().getLangOpts().CPlusPlus); return false; + } - ASTContext &Context = getASTContext(); - if (!Context.getLangOpts().CPlusPlus) - return true; - return DC->isExternCContext(); + return D.getLanguageLinkage() == CLanguageLinkage; +} + +LanguageLinkage VarDecl::getLanguageLinkage() const { + return getLanguageLinkageTemplate(*this); +} + +bool VarDecl::isExternC() const { + return isExternCTemplate(*this); } VarDecl *VarDecl::getCanonicalDecl() { @@ -1241,12 +1579,11 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( // AST for 'extern "C" int foo;' is annotated with 'extern'. if (hasExternalStorage()) return DeclarationOnly; - - if (getStorageClassAsWritten() == SC_Extern || - getStorageClassAsWritten() == SC_PrivateExtern) { + + if (hasExternalStorage()) { for (const VarDecl *PrevVar = getPreviousDecl(); PrevVar; PrevVar = PrevVar->getPreviousDecl()) { - if (PrevVar->getLinkage() == InternalLinkage && PrevVar->hasInit()) + if (PrevVar->getLinkage() == InternalLinkage) return DeclarationOnly; } } @@ -1375,7 +1712,7 @@ bool VarDecl::isUsableInConstantExpressions(ASTContext &C) const { // In C++11, any variable of reference type can be used in a constant // expression if it is initialized by a constant expression. - if (Lang.CPlusPlus0x && getType()->isReferenceType()) + if (Lang.CPlusPlus11 && getType()->isReferenceType()) return true; // Only const objects can be used in constant expressions in C++. C++98 does @@ -1391,7 +1728,7 @@ bool VarDecl::isUsableInConstantExpressions(ASTContext &C) const { // Additionally, in C++11, non-volatile constexpr variables can be used in // constant expressions. - return Lang.CPlusPlus0x && isConstexpr(); + return Lang.CPlusPlus11 && isConstexpr(); } /// Convert the initializer for this declaration to the elaborated EvaluatedStmt @@ -1409,12 +1746,12 @@ EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const { } APValue *VarDecl::evaluateValue() const { - llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + SmallVector<PartialDiagnosticAt, 8> Notes; return evaluateValue(Notes); } APValue *VarDecl::evaluateValue( - llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const { + SmallVectorImpl<PartialDiagnosticAt> &Notes) const { EvaluatedStmt *Eval = ensureEvaluatedStmt(); // We only produce notes indicating why an initializer is non-constant the @@ -1447,7 +1784,7 @@ APValue *VarDecl::evaluateValue( // In C++11, we have determined whether the initializer was a constant // expression as a side-effect. - if (getASTContext().getLangOpts().CPlusPlus0x && !Eval->CheckedICE) { + if (getASTContext().getLangOpts().CPlusPlus11 && !Eval->CheckedICE) { Eval->CheckedICE = true; Eval->IsICE = Result && Notes.empty(); } @@ -1471,8 +1808,8 @@ bool VarDecl::checkInitIsICE() const { // In C++11, evaluate the initializer to check whether it's a constant // expression. - if (getASTContext().getLangOpts().CPlusPlus0x) { - llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + if (getASTContext().getLangOpts().CPlusPlus11) { + SmallVector<PartialDiagnosticAt, 8> Notes; evaluateValue(Notes); return Eval->IsICE; } @@ -1541,16 +1878,15 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten, - Expr *DefArg) { + StorageClass S, Expr *DefArg) { return new (C) ParmVarDecl(ParmVar, DC, StartLoc, IdLoc, Id, T, TInfo, - S, SCAsWritten, DefArg); + S, DefArg); } ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ParmVarDecl)); return new (Mem) ParmVarDecl(ParmVar, 0, SourceLocation(), SourceLocation(), - 0, QualType(), 0, SC_None, SC_None, 0); + 0, QualType(), 0, SC_None, 0); } SourceRange ParmVarDecl::getSourceRange() const { @@ -1602,17 +1938,13 @@ unsigned ParmVarDecl::getParameterIndexLarge() const { // FunctionDecl Implementation //===----------------------------------------------------------------------===// -void FunctionDecl::getNameForDiagnostic(std::string &S, - const PrintingPolicy &Policy, - bool Qualified) const { - NamedDecl::getNameForDiagnostic(S, Policy, Qualified); +void FunctionDecl::getNameForDiagnostic( + raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const { + NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs(); if (TemplateArgs) - S += TemplateSpecializationType::PrintTemplateArgumentList( - TemplateArgs->data(), - TemplateArgs->size(), - Policy); - + TemplateSpecializationType::PrintTemplateArgumentList( + OS, TemplateArgs->data(), TemplateArgs->size(), Policy); } bool FunctionDecl::isVariadic() const { @@ -1684,13 +2016,6 @@ void FunctionDecl::setPure(bool P) { Parent->markedVirtualFunctionPure(); } -void FunctionDecl::setConstexpr(bool IC) { - IsConstexpr = IC; - CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(this); - if (IC && CD) - CD->getParent()->markedConstructorConstexpr(CD); -} - bool FunctionDecl::isMain() const { const TranslationUnitDecl *tunit = dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()); @@ -1722,29 +2047,25 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { return (proto->getArgType(1).getCanonicalType() == Context.VoidPtrTy); } -bool FunctionDecl::isExternC() const { - if (getLinkage() != ExternalLinkage) - return false; - - if (getAttr<OverloadableAttr>()) - return false; - - const DeclContext *DC = getDeclContext(); - if (DC->isRecord()) - return false; +LanguageLinkage FunctionDecl::getLanguageLinkage() const { + // Users expect to be able to write + // extern "C" void *__builtin_alloca (size_t); + // so consider builtins as having C language linkage. + if (getBuiltinID()) + return CLanguageLinkage; - ASTContext &Context = getASTContext(); - if (!Context.getLangOpts().CPlusPlus) - return true; + return getLanguageLinkageTemplate(*this); +} - return isMain() || DC->isExternCContext(); +bool FunctionDecl::isExternC() const { + return isExternCTemplate(*this); } bool FunctionDecl::isGlobal() const { if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this)) return Method->isStatic(); - if (getStorageClass() == SC_Static) + if (getCanonicalDecl()->getStorageClass() == SC_Static) return false; for (const DeclContext *DC = getDeclContext(); @@ -1760,6 +2081,12 @@ bool FunctionDecl::isGlobal() const { return true; } +bool FunctionDecl::isNoReturn() const { + return hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() || + hasAttr<C11NoReturnAttr>() || + getType()->getAs<FunctionType>()->getNoReturnAttr(); +} + void FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { redeclarable_base::setPreviousDeclaration(PrevDecl); @@ -1783,14 +2110,6 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDeclaration(); } -void FunctionDecl::setStorageClass(StorageClass SC) { - assert(isLegalForFunction(SC)); - if (getStorageClass() != SC) - ClearLinkageCache(); - - SClass = SC; -} - /// \brief Returns a value indicating whether this function /// corresponds to a builtin function. /// @@ -1851,7 +2170,7 @@ unsigned FunctionDecl::getNumParams() const { } void FunctionDecl::setParams(ASTContext &C, - llvm::ArrayRef<ParmVarDecl *> NewParamInfo) { + ArrayRef<ParmVarDecl *> NewParamInfo) { assert(ParamInfo == 0 && "Already has param info!"); assert(NewParamInfo.size() == getNumParams() && "Parameter count mismatch!"); @@ -1862,13 +2181,13 @@ void FunctionDecl::setParams(ASTContext &C, } } -void FunctionDecl::setDeclsInPrototypeScope(llvm::ArrayRef<NamedDecl *> NewDecls) { +void FunctionDecl::setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls) { assert(DeclsInPrototypeScope.empty() && "Already has prototype decls!"); if (!NewDecls.empty()) { NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()]; std::copy(NewDecls.begin(), NewDecls.end(), A); - DeclsInPrototypeScope = llvm::ArrayRef<NamedDecl*>(A, NewDecls.size()); + DeclsInPrototypeScope = ArrayRef<NamedDecl *>(A, NewDecls.size()); } } @@ -1907,38 +2226,6 @@ unsigned FunctionDecl::getMinRequiredArguments() const { return NumRequiredArgs; } -bool FunctionDecl::isInlined() const { - if (IsInline) - return true; - - if (isa<CXXMethodDecl>(this)) { - if (!isOutOfLine() || getCanonicalDecl()->isInlineSpecified()) - return true; - } - - switch (getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - return false; - - case TSK_ImplicitInstantiation: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - // Handle below. - break; - } - - const FunctionDecl *PatternDecl = getTemplateInstantiationPattern(); - bool HasPattern = false; - if (PatternDecl) - HasPattern = PatternDecl->hasBody(PatternDecl); - - if (HasPattern && PatternDecl) - return PatternDecl->isInlined(); - - return false; -} - static bool RedeclForcesDefC99(const FunctionDecl *Redecl) { // Only consider file-scope declarations in this test. if (!Redecl->getLexicalDeclContext()->isTranslationUnit()) @@ -1973,7 +2260,7 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { // // FIXME: What happens if gnu_inline gets added on after the first // declaration? - if (!isInlineSpecified() || getStorageClassAsWritten() == SC_Extern) + if (!isInlineSpecified() || getStorageClass() == SC_Extern) return false; const FunctionDecl *Prev = this; @@ -1985,10 +2272,10 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { // If it's not the case that both 'inline' and 'extern' are // specified on the definition, then it is always externally visible. if (!Prev->isInlineSpecified() || - Prev->getStorageClassAsWritten() != SC_Extern) + Prev->getStorageClass() != SC_Extern) return false; } else if (Prev->isInlineSpecified() && - Prev->getStorageClassAsWritten() != SC_Extern) { + Prev->getStorageClass() != SC_Extern) { return false; } } @@ -2014,8 +2301,8 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { return FoundBody; } -/// \brief For an inline function definition in C or C++, determine whether the -/// definition will be externally visible. +/// \brief For an inline function definition in C, or for a gnu_inline function +/// in C++, determine whether the definition will be externally visible. /// /// Inline function definitions are always available for inlining optimizations. /// However, depending on the language dialect, declaration specifiers, and @@ -2043,7 +2330,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { // If it's not the case that both 'inline' and 'extern' are // specified on the definition, then this inline definition is // externally visible. - if (!(isInlineSpecified() && getStorageClassAsWritten() == SC_Extern)) + if (!(isInlineSpecified() && getStorageClass() == SC_Extern)) return true; // If any declaration is 'inline' but not 'extern', then this definition @@ -2052,13 +2339,17 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { Redecl != RedeclEnd; ++Redecl) { if (Redecl->isInlineSpecified() && - Redecl->getStorageClassAsWritten() != SC_Extern) + Redecl->getStorageClass() != SC_Extern) return true; } return false; } + // The rest of this function is C-only. + assert(!Context.getLangOpts().CPlusPlus && + "should not use C inline rules in C++"); + // C99 6.7.4p6: // [...] If all of the file scope declarations for a function in a // translation unit include the inline function specifier without extern, @@ -2118,10 +2409,6 @@ FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const { return 0; } -MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const { - return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>(); -} - void FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD, @@ -2553,18 +2840,17 @@ TagDecl* TagDecl::getCanonicalDecl() { return getFirstDeclaration(); } -void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { - TypedefNameDeclOrQualifier = TDD; +void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { + TypedefNameDeclOrQualifier = TDD; if (TypeForDecl) - const_cast<Type*>(TypeForDecl)->ClearLinkageCache(); - ClearLinkageCache(); + assert(TypeForDecl->isLinkageValid()); + assert(isLinkageValid()); } void TagDecl::startDefinition() { IsBeingDefined = true; - if (isa<CXXRecordDecl>(this)) { - CXXRecordDecl *D = cast<CXXRecordDecl>(this); + if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(this)) { struct CXXRecordDecl::DefinitionData *Data = new (getASTContext()) struct CXXRecordDecl::DefinitionData(D); for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) @@ -2587,6 +2873,16 @@ void TagDecl::completeDefinition() { TagDecl *TagDecl::getDefinition() const { if (isCompleteDefinition()) return const_cast<TagDecl *>(this); + + // If it's possible for us to have an out-of-date definition, check now. + if (MayHaveOutOfDateDef) { + if (IdentifierInfo *II = getIdentifier()) { + if (II->isOutOfDate()) { + updateOutOfDate(*II); + } + } + } + if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this)) return CXXRD->getDefinition(); @@ -2643,14 +2939,17 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, bool IsScopedUsingClassTag, bool IsFixed) { EnumDecl *Enum = new (C) EnumDecl(DC, StartLoc, IdLoc, Id, PrevDecl, IsScoped, IsScopedUsingClassTag, IsFixed); + Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules; C.getTypeDeclType(Enum, PrevDecl); return Enum; } EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EnumDecl)); - return new (Mem) EnumDecl(0, SourceLocation(), SourceLocation(), 0, 0, - false, false, false); + EnumDecl *Enum = new (Mem) EnumDecl(0, SourceLocation(), SourceLocation(), + 0, 0, false, false, false); + Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules; + return Enum; } void EnumDecl::completeDefinition(QualType NewType, @@ -2708,6 +3007,7 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, HasFlexibleArrayMember = false; AnonymousStructOrUnion = false; HasObjectMember = false; + HasVolatileMember = false; LoadedFieldsFromExternalStorage = false; assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); } @@ -2717,14 +3017,18 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, IdentifierInfo *Id, RecordDecl* PrevDecl) { RecordDecl* R = new (C) RecordDecl(Record, TK, DC, StartLoc, IdLoc, Id, PrevDecl); + R->MayHaveOutOfDateDef = C.getLangOpts().Modules; + C.getTypeDeclType(R, PrevDecl); return R; } RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(RecordDecl)); - return new (Mem) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), - SourceLocation(), 0, 0); + RecordDecl *R = new (Mem) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), + SourceLocation(), 0, 0); + R->MayHaveOutOfDateDef = C.getLangOpts().Modules; + return R; } bool RecordDecl::isInjectedClassName() const { @@ -2793,7 +3097,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { // BlockDecl Implementation //===----------------------------------------------------------------------===// -void BlockDecl::setParams(llvm::ArrayRef<ParmVarDecl *> NewParamInfo) { +void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) { assert(ParamInfo == 0 && "Already has param info!"); // Zero params -> null pointer. @@ -2871,6 +3175,14 @@ LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void ValueDecl::anchor() { } +bool ValueDecl::isWeak() const { + for (attr_iterator I = attr_begin(), E = attr_end(); I != E; ++I) + if (isa<WeakAttr>(*I) || isa<WeakRefAttr>(*I)) + return true; + + return isWeakImported(); +} + void ImplicitParamDecl::anchor() { } ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, @@ -2890,12 +3202,12 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass SC, StorageClass SCAsWritten, + StorageClass SC, bool isInlineSpecified, bool hasWrittenPrototype, bool isConstexprSpecified) { FunctionDecl *New = new (C) FunctionDecl(Function, DC, StartLoc, NameInfo, - T, TInfo, SC, SCAsWritten, + T, TInfo, SC, isInlineSpecified, isConstexprSpecified); New->HasWrittenPrototype = hasWrittenPrototype; @@ -2906,7 +3218,7 @@ FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FunctionDecl)); return new (Mem) FunctionDecl(Function, 0, SourceLocation(), DeclarationNameInfo(), QualType(), 0, - SC_None, SC_None, false, false); + SC_None, false, false); } BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { @@ -3013,6 +3325,17 @@ FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, return new (Mem) FileScopeAsmDecl(0, 0, SourceLocation(), SourceLocation()); } +void EmptyDecl::anchor() {} + +EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { + return new (C) EmptyDecl(DC, L); +} + +EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EmptyDecl)); + return new (Mem) EmptyDecl(0, SourceLocation()); +} + //===----------------------------------------------------------------------===// // ImportDecl Implementation //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index 4400d50..bd6d99c 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -12,19 +12,21 @@ //===----------------------------------------------------------------------===// #include "clang/AST/DeclBase.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclContextInternals.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclContextInternals.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DependentDiagnostic.h" #include "clang/AST/ExternalASTSource.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Type.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" -#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/Type.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/raw_ostream.h" @@ -39,6 +41,10 @@ using namespace clang; #define ABSTRACT_DECL(DECL) #include "clang/AST/DeclNodes.inc" +void Decl::updateOutOfDate(IdentifierInfo &II) const { + getASTContext().getExternalSource()->updateOutOfDateIdentifier(II); +} + void *Decl::AllocateDeserializedDecl(const ASTContext &Context, unsigned ID, unsigned Size) { @@ -58,6 +64,11 @@ void *Decl::AllocateDeserializedDecl(const ASTContext &Context, return Result; } +Module *Decl::getOwningModuleSlow() const { + assert(isFromASTFile() && "Not from AST file?"); + return getASTContext().getExternalSource()->getModule(getOwningModuleID()); +} + const char *Decl::getDeclKindName() const { switch (DeclKind) { default: llvm_unreachable("Declaration not in DeclNodes.inc!"); @@ -180,8 +191,11 @@ void PrettyStackTraceDecl::print(raw_ostream &OS) const { OS << Message; - if (const NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl)) - OS << " '" << DN->getQualifiedNameAsString() << '\''; + if (const NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl)) { + OS << " '"; + DN->printQualifiedName(OS); + OS << '\''; + } OS << '\n'; } @@ -253,6 +267,19 @@ ASTMutationListener *Decl::getASTMutationListener() const { return getASTContext().getASTMutationListener(); } +unsigned Decl::getMaxAlignment() const { + if (!hasAttrs()) + return 0; + + unsigned Align = 0; + const AttrVec &V = getAttrs(); + ASTContext &Ctx = getASTContext(); + specific_attr_iterator<AlignedAttr> I(V.begin()), E(V.end()); + for (; I != E; ++I) + Align = std::max(Align, I->getAlignment(Ctx)); + return Align; +} + bool Decl::isUsed(bool CheckUsedAttr) const { if (Used) return true; @@ -260,13 +287,7 @@ bool Decl::isUsed(bool CheckUsedAttr) const { // Check for used attribute. if (CheckUsedAttr && hasAttr<UsedAttr>()) return true; - - // Check redeclarations for used attribute. - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { - if ((CheckUsedAttr && I->hasAttr<UsedAttr>()) || I->Used) - return true; - } - + return false; } @@ -414,7 +435,7 @@ bool Decl::canBeWeakImported(bool &IsDefinition) const { // Variables, if they aren't definitions. if (const VarDecl *Var = dyn_cast<VarDecl>(this)) { - if (!Var->hasExternalStorage() || Var->getInit()) { + if (Var->isThisDeclarationADefinition()) { IsDefinition = true; return false; } @@ -541,6 +562,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ObjCCategory: case ObjCCategoryImpl: case Import: + case OMPThreadPrivate: + case Empty: // Never looked up by name. return 0; } @@ -789,6 +812,17 @@ bool DeclContext::isExternCContext() const { return false; } +bool DeclContext::isExternCXXContext() const { + const DeclContext *DC = this; + while (DC->DeclKind != Decl::TranslationUnit) { + if (DC->DeclKind == Decl::LinkageSpec) + return cast<LinkageSpecDecl>(DC)->getLanguage() + == LinkageSpecDecl::lang_cxx; + DC = DC->getParent(); + } + return false; +} + bool DeclContext::Encloses(const DeclContext *DC) const { if (getPrimaryContext() != this) return getPrimaryContext()->Encloses(DC); @@ -862,7 +896,7 @@ DeclContext *DeclContext::getPrimaryContext() { } void -DeclContext::collectAllContexts(llvm::SmallVectorImpl<DeclContext *> &Contexts){ +DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts){ Contexts.clear(); if (DeclKind != Decl::Namespace) { @@ -900,6 +934,21 @@ DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls, return std::make_pair(FirstNewDecl, PrevDecl); } +/// \brief We have just acquired external visible storage, and we already have +/// built a lookup map. For every name in the map, pull in the new names from +/// the external storage. +void DeclContext::reconcileExternalVisibleStorage() { + assert(NeedToReconcileExternalVisibleStorage && LookupPtr.getPointer()); + NeedToReconcileExternalVisibleStorage = false; + + StoredDeclsMap &Map = *LookupPtr.getPointer(); + ExternalASTSource *Source = getParentASTContext().getExternalSource(); + for (StoredDeclsMap::iterator I = Map.begin(); I != Map.end(); ++I) { + I->second.removeExternalDecls(); + Source->FindExternalVisibleDeclsByName(this, I->first); + } +} + /// \brief Load the declarations within this lexical storage from an /// external source. void @@ -950,9 +999,8 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC, if (!(Map = DC->LookupPtr.getPointer())) Map = DC->CreateStoredDeclsMap(Context); - StoredDeclsList &List = (*Map)[Name]; - assert(List.isNull()); - (void) List; + // Add an entry to the map for this name, if it's not already present. + (*Map)[Name]; return DeclContext::lookup_result(); } @@ -962,7 +1010,6 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name, ArrayRef<NamedDecl*> Decls) { ASTContext &Context = DC->getParentASTContext(); - StoredDeclsMap *Map; if (!(Map = DC->LookupPtr.getPointer())) Map = DC->CreateStoredDeclsMap(Context); @@ -973,6 +1020,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, if (List.isNull()) List.setOnlyValue(*I); else + // FIXME: Need declarationReplaces handling for redeclarations in modules. List.AddSubsequentDecl(*I); } @@ -1114,16 +1162,18 @@ static bool shouldBeHidden(NamedDecl *D) { StoredDeclsMap *DeclContext::buildLookup() { assert(this == getPrimaryContext() && "buildLookup called on non-primary DC"); + // FIXME: Should we keep going if hasExternalVisibleStorage? if (!LookupPtr.getInt()) return LookupPtr.getPointer(); - llvm::SmallVector<DeclContext *, 2> Contexts; + SmallVector<DeclContext *, 2> Contexts; collectAllContexts(Contexts); for (unsigned I = 0, N = Contexts.size(); I != N; ++I) buildLookupImpl(Contexts[I]); // We no longer have any lazy decls. LookupPtr.setInt(false); + NeedToReconcileExternalVisibleStorage = false; return LookupPtr.getPointer(); } @@ -1162,18 +1212,33 @@ DeclContext::lookup(DeclarationName Name) { return PrimaryContext->lookup(Name); if (hasExternalVisibleStorage()) { - // If a PCH has a result for this name, and we have a local declaration, we - // will have imported the PCH result when adding the local declaration. - // FIXME: For modules, we could have had more declarations added by module - // imoprts since we saw the declaration of the local name. - if (StoredDeclsMap *Map = LookupPtr.getPointer()) { - StoredDeclsMap::iterator I = Map->find(Name); - if (I != Map->end()) - return I->second.getLookupResult(); - } + StoredDeclsMap *Map = LookupPtr.getPointer(); + if (LookupPtr.getInt()) + Map = buildLookup(); + else if (NeedToReconcileExternalVisibleStorage) + reconcileExternalVisibleStorage(); + + if (!Map) + Map = CreateStoredDeclsMap(getParentASTContext()); + + // If a PCH/module has a result for this name, and we have a local + // declaration, we will have imported the PCH/module result when adding the + // local declaration or when reconciling the module. + std::pair<StoredDeclsMap::iterator, bool> R = + Map->insert(std::make_pair(Name, StoredDeclsList())); + if (!R.second) + return R.first->second.getLookupResult(); ExternalASTSource *Source = getParentASTContext().getExternalSource(); - return Source->FindExternalVisibleDeclsByName(this, Name); + if (Source->FindExternalVisibleDeclsByName(this, Name)) { + if (StoredDeclsMap *Map = LookupPtr.getPointer()) { + StoredDeclsMap::iterator I = Map->find(Name); + if (I != Map->end()) + return I->second.getLookupResult(); + } + } + + return lookup_result(lookup_iterator(0), lookup_iterator(0)); } StoredDeclsMap *Map = LookupPtr.getPointer(); @@ -1190,26 +1255,26 @@ DeclContext::lookup(DeclarationName Name) { return I->second.getLookupResult(); } -void DeclContext::localUncachedLookup(DeclarationName Name, - llvm::SmallVectorImpl<NamedDecl *> &Results) { +void DeclContext::localUncachedLookup(DeclarationName Name, + SmallVectorImpl<NamedDecl *> &Results) { Results.clear(); // If there's no external storage, just perform a normal lookup and copy // the results. if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage() && Name) { lookup_result LookupResults = lookup(Name); - Results.insert(Results.end(), LookupResults.first, LookupResults.second); + Results.insert(Results.end(), LookupResults.begin(), LookupResults.end()); return; } // If we have a lookup table, check there first. Maybe we'll get lucky. - if (Name) { + if (Name && !LookupPtr.getInt()) { if (StoredDeclsMap *Map = LookupPtr.getPointer()) { StoredDeclsMap::iterator Pos = Map->find(Name); if (Pos != Map->end()) { Results.insert(Results.end(), - Pos->second.getLookupResult().first, - Pos->second.getLookupResult().second); + Pos->second.getLookupResult().begin(), + Pos->second.getLookupResult().end()); return; } } @@ -1361,8 +1426,8 @@ DeclContext::getUsingDirectives() const { // FIXME: Use something more efficient than normal lookup for using // directives. In C++, using directives are looked up more than anything else. lookup_const_result Result = lookup(UsingDirectiveDecl::getName()); - return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first), - reinterpret_cast<udir_iterator>(Result.second)); + return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.begin()), + reinterpret_cast<udir_iterator>(Result.end())); } //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index 82e630a..ffad9ae 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclTemplate.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/TypeLoc.h" @@ -36,28 +36,33 @@ AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { } CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) - : UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false), - UserDeclaredMoveConstructor(false), UserDeclaredCopyAssignment(false), - UserDeclaredMoveAssignment(false), UserDeclaredDestructor(false), + : UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0), Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true), HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false), HasMutableFields(false), HasOnlyCMembers(true), - HasInClassInitializer(false), - HasTrivialDefaultConstructor(true), + HasInClassInitializer(false), HasUninitializedReferenceMember(false), + NeedOverloadResolutionForMoveConstructor(false), + NeedOverloadResolutionForMoveAssignment(false), + NeedOverloadResolutionForDestructor(false), + DefaultedMoveConstructorIsDeleted(false), + DefaultedMoveAssignmentIsDeleted(false), + DefaultedDestructorIsDeleted(false), + HasTrivialSpecialMembers(SMF_All), + DeclaredNonTrivialSpecialMembers(0), + HasIrrelevantDestructor(true), HasConstexprNonCopyMoveConstructor(false), DefaultedDefaultConstructorIsConstexpr(true), - HasConstexprDefaultConstructor(false), HasTrivialCopyConstructor(true), - HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true), - HasTrivialMoveAssignment(true), HasTrivialDestructor(true), - HasIrrelevantDestructor(true), + HasConstexprDefaultConstructor(false), HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false), - UserProvidedDefaultConstructor(false), DeclaredDefaultConstructor(false), - DeclaredCopyConstructor(false), DeclaredMoveConstructor(false), - DeclaredCopyAssignment(false), DeclaredMoveAssignment(false), - DeclaredDestructor(false), FailedImplicitMoveConstructor(false), - FailedImplicitMoveAssignment(false), IsLambda(false), NumBases(0), - NumVBases(0), Bases(), VBases(), Definition(D), FirstFriend(0) { + UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0), + ImplicitCopyConstructorHasConstParam(true), + ImplicitCopyAssignmentHasConstParam(true), + HasDeclaredCopyConstructorWithConstParam(false), + HasDeclaredCopyAssignmentWithConstParam(false), + FailedImplicitMoveConstructor(false), FailedImplicitMoveAssignment(false), + IsLambda(false), NumBases(0), NumVBases(0), Bases(), VBases(), + Definition(D), FirstFriend(0) { } CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const { @@ -82,6 +87,7 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, bool DelayTypeCreation) { CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, StartLoc, IdLoc, Id, PrevDecl); + R->MayHaveOutOfDateDef = C.getLangOpts().Modules; // FIXME: DelayTypeCreation seems like such a hack if (!DelayTypeCreation) @@ -96,6 +102,7 @@ CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, 0, 0); R->IsBeingDefined = true; R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, Dependent); + R->MayHaveOutOfDateDef = false; C.getTypeDeclType(R, /*PrevDecl=*/0); return R; } @@ -103,8 +110,11 @@ CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, CXXRecordDecl * CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXRecordDecl)); - return new (Mem) CXXRecordDecl(CXXRecord, TTK_Struct, 0, SourceLocation(), - SourceLocation(), 0, 0); + CXXRecordDecl *R = new (Mem) CXXRecordDecl(CXXRecord, TTK_Struct, 0, + SourceLocation(), SourceLocation(), + 0, 0); + R->MayHaveOutOfDateDef = false; + return R; } void @@ -184,38 +194,35 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, BaseClassDecl->vbases_begin(), E = BaseClassDecl->vbases_end(); VBase != E; ++VBase) { // Add this base if it's not already in the list. - if (SeenVBaseTypes.insert(C.getCanonicalType(VBase->getType()))) + if (SeenVBaseTypes.insert(C.getCanonicalType(VBase->getType()))) { VBases.push_back(VBase); + + // C++11 [class.copy]p8: + // The implicitly-declared copy constructor for a class X will have + // the form 'X::X(const X&)' if each [...] virtual base class B of X + // has a copy constructor whose first parameter is of type + // 'const B&' or 'const volatile B&' [...] + if (CXXRecordDecl *VBaseDecl = VBase->getType()->getAsCXXRecordDecl()) + if (!VBaseDecl->hasCopyConstructorWithConstParam()) + data().ImplicitCopyConstructorHasConstParam = false; + } } if (Base->isVirtual()) { // Add this base if it's not already in the list. if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType))) - VBases.push_back(Base); - + VBases.push_back(Base); + // C++0x [meta.unary.prop] is_empty: // T is a class type, but not a union type, with ... no virtual base // classes data().Empty = false; - - // C++ [class.ctor]p5: - // A default constructor is trivial [...] if: - // -- its class has [...] no virtual bases - data().HasTrivialDefaultConstructor = false; - - // C++0x [class.copy]p13: - // A copy/move constructor for class X is trivial if it is neither - // user-provided nor deleted and if - // -- class X has no virtual functions and no virtual base classes, and - data().HasTrivialCopyConstructor = false; - data().HasTrivialMoveConstructor = false; - // C++0x [class.copy]p27: - // A copy/move assignment operator for class X is trivial if it is - // neither user-provided nor deleted and if - // -- class X has no virtual functions and no virtual base classes, and - data().HasTrivialCopyAssignment = false; - data().HasTrivialMoveAssignment = false; + // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25: + // A [default constructor, copy/move constructor, or copy/move assignment + // operator for a class X] is trivial [...] if: + // -- class X has [...] no virtual base classes + data().HasTrivialSpecialMembers &= SMF_Destructor; // C++0x [class]p7: // A standard-layout class is a class that: [...] @@ -232,36 +239,35 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // -- all the direct base classes of its class have trivial default // constructors. if (!BaseClassDecl->hasTrivialDefaultConstructor()) - data().HasTrivialDefaultConstructor = false; - + data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor; + // C++0x [class.copy]p13: // A copy/move constructor for class X is trivial if [...] // [...] // -- the constructor selected to copy/move each direct base class // subobject is trivial, and - // FIXME: C++0x: We need to only consider the selected constructor - // instead of all of them. For now, we treat a move constructor as being - // non-trivial if it calls anything other than a trivial move constructor. if (!BaseClassDecl->hasTrivialCopyConstructor()) - data().HasTrivialCopyConstructor = false; - if (!BaseClassDecl->hasTrivialMoveConstructor() || - !(BaseClassDecl->hasDeclaredMoveConstructor() || - BaseClassDecl->needsImplicitMoveConstructor())) - data().HasTrivialMoveConstructor = false; + data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor; + // If the base class doesn't have a simple move constructor, we'll eagerly + // declare it and perform overload resolution to determine which function + // it actually calls. If it does have a simple move constructor, this + // check is correct. + if (!BaseClassDecl->hasTrivialMoveConstructor()) + data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor; // C++0x [class.copy]p27: // A copy/move assignment operator for class X is trivial if [...] // [...] // -- the assignment operator selected to copy/move each direct base // class subobject is trivial, and - // FIXME: C++0x: We need to only consider the selected operator instead - // of all of them. if (!BaseClassDecl->hasTrivialCopyAssignment()) - data().HasTrivialCopyAssignment = false; - if (!BaseClassDecl->hasTrivialMoveAssignment() || - !(BaseClassDecl->hasDeclaredMoveAssignment() || - BaseClassDecl->needsImplicitMoveAssignment())) - data().HasTrivialMoveAssignment = false; + data().HasTrivialSpecialMembers &= ~SMF_CopyAssignment; + // If the base class doesn't have a simple move assignment, we'll eagerly + // declare it and perform overload resolution to determine which function + // it actually calls. If it does have a simple move assignment, this + // check is correct. + if (!BaseClassDecl->hasTrivialMoveAssignment()) + data().HasTrivialSpecialMembers &= ~SMF_MoveAssignment; // C++11 [class.ctor]p6: // If that user-written default constructor would satisfy the @@ -270,24 +276,48 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, if (!BaseClassDecl->hasConstexprDefaultConstructor()) data().DefaultedDefaultConstructorIsConstexpr = false; } - + // C++ [class.ctor]p3: // A destructor is trivial if all the direct base classes of its class // have trivial destructors. if (!BaseClassDecl->hasTrivialDestructor()) - data().HasTrivialDestructor = false; + data().HasTrivialSpecialMembers &= ~SMF_Destructor; if (!BaseClassDecl->hasIrrelevantDestructor()) data().HasIrrelevantDestructor = false; + // C++11 [class.copy]p18: + // The implicitly-declared copy assignment oeprator for a class X will + // have the form 'X& X::operator=(const X&)' if each direct base class B + // of X has a copy assignment operator whose parameter is of type 'const + // B&', 'const volatile B&', or 'B' [...] + if (!BaseClassDecl->hasCopyAssignmentWithConstParam()) + data().ImplicitCopyAssignmentHasConstParam = false; + + // C++11 [class.copy]p8: + // The implicitly-declared copy constructor for a class X will have + // the form 'X::X(const X&)' if each direct [...] base class B of X + // has a copy constructor whose first parameter is of type + // 'const B&' or 'const volatile B&' [...] + if (!BaseClassDecl->hasCopyConstructorWithConstParam()) + data().ImplicitCopyConstructorHasConstParam = false; + // A class has an Objective-C object member if... or any of its bases // has an Objective-C object member. if (BaseClassDecl->hasObjectMember()) setHasObjectMember(true); + + if (BaseClassDecl->hasVolatileMember()) + setHasVolatileMember(true); // Keep track of the presence of mutable fields. if (BaseClassDecl->hasMutableFields()) data().HasMutableFields = true; + + if (BaseClassDecl->hasUninitializedReferenceMember()) + data().HasUninitializedReferenceMember = true; + + addedClassSubobject(BaseClassDecl); } if (VBases.empty()) @@ -296,8 +326,44 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // Create base specifier for any direct or indirect virtual bases. data().VBases = new (C) CXXBaseSpecifier[VBases.size()]; data().NumVBases = VBases.size(); - for (int I = 0, E = VBases.size(); I != E; ++I) + for (int I = 0, E = VBases.size(); I != E; ++I) { + QualType Type = VBases[I]->getType(); + if (!Type->isDependentType()) + addedClassSubobject(Type->getAsCXXRecordDecl()); data().getVBases()[I] = *VBases[I]; + } +} + +void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { + // C++11 [class.copy]p11: + // A defaulted copy/move constructor for a class X is defined as + // deleted if X has: + // -- a direct or virtual base class B that cannot be copied/moved [...] + // -- a non-static data member of class type M (or array thereof) + // that cannot be copied or moved [...] + if (!Subobj->hasSimpleMoveConstructor()) + data().NeedOverloadResolutionForMoveConstructor = true; + + // C++11 [class.copy]p23: + // A defaulted copy/move assignment operator for a class X is defined as + // deleted if X has: + // -- a direct or virtual base class B that cannot be copied/moved [...] + // -- a non-static data member of class type M (or array thereof) + // that cannot be copied or moved [...] + if (!Subobj->hasSimpleMoveAssignment()) + data().NeedOverloadResolutionForMoveAssignment = true; + + // C++11 [class.ctor]p5, C++11 [class.copy]p11, C++11 [class.dtor]p5: + // A defaulted [ctor or dtor] for a class X is defined as + // deleted if X has: + // -- any direct or virtual base class [...] has a type with a destructor + // that is deleted or inaccessible from the defaulted [ctor or dtor]. + // -- any non-static data member has a type with a destructor + // that is deleted or inaccessible from the defaulted [ctor or dtor]. + if (!Subobj->hasSimpleDestructor()) { + data().NeedOverloadResolutionForMoveConstructor = true; + data().NeedOverloadResolutionForDestructor = true; + } } /// Callback function for CXXRecordDecl::forallBases that acknowledges @@ -313,161 +379,29 @@ bool CXXRecordDecl::hasAnyDependentBases() const { return !forallBases(SawBase, 0); } -bool CXXRecordDecl::hasConstCopyConstructor() const { - return getCopyConstructor(Qualifiers::Const) != 0; -} - bool CXXRecordDecl::isTriviallyCopyable() const { // C++0x [class]p5: // A trivially copyable class is a class that: // -- has no non-trivial copy constructors, - if (!hasTrivialCopyConstructor()) return false; + if (hasNonTrivialCopyConstructor()) return false; // -- has no non-trivial move constructors, - if (!hasTrivialMoveConstructor()) return false; + if (hasNonTrivialMoveConstructor()) return false; // -- has no non-trivial copy assignment operators, - if (!hasTrivialCopyAssignment()) return false; + if (hasNonTrivialCopyAssignment()) return false; // -- has no non-trivial move assignment operators, and - if (!hasTrivialMoveAssignment()) return false; + if (hasNonTrivialMoveAssignment()) return false; // -- has a trivial destructor. if (!hasTrivialDestructor()) return false; return true; } -/// \brief Perform a simplistic form of overload resolution that only considers -/// cv-qualifiers on a single parameter, and return the best overload candidate -/// (if there is one). -static CXXMethodDecl * -GetBestOverloadCandidateSimple( - const SmallVectorImpl<std::pair<CXXMethodDecl *, Qualifiers> > &Cands) { - if (Cands.empty()) - return 0; - if (Cands.size() == 1) - return Cands[0].first; - - unsigned Best = 0, N = Cands.size(); - for (unsigned I = 1; I != N; ++I) - if (Cands[Best].second.compatiblyIncludes(Cands[I].second)) - Best = I; - - for (unsigned I = 0; I != N; ++I) - if (I != Best && Cands[Best].second.compatiblyIncludes(Cands[I].second)) - return 0; - - return Cands[Best].first; -} - -CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(unsigned TypeQuals) const{ - ASTContext &Context = getASTContext(); - QualType ClassType - = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this)); - DeclarationName ConstructorName - = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(ClassType)); - unsigned FoundTQs; - SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found; - DeclContext::lookup_const_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName); - Con != ConEnd; ++Con) { - // C++ [class.copy]p2: - // A non-template constructor for class X is a copy constructor if [...] - if (isa<FunctionTemplateDecl>(*Con)) - continue; - - CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); - if (Constructor->isCopyConstructor(FoundTQs)) { - if (((TypeQuals & Qualifiers::Const) == (FoundTQs & Qualifiers::Const)) || - (!(TypeQuals & Qualifiers::Const) && (FoundTQs & Qualifiers::Const))) - Found.push_back(std::make_pair( - const_cast<CXXConstructorDecl *>(Constructor), - Qualifiers::fromCVRMask(FoundTQs))); - } - } - - return cast_or_null<CXXConstructorDecl>( - GetBestOverloadCandidateSimple(Found)); -} - -CXXConstructorDecl *CXXRecordDecl::getMoveConstructor() const { - for (ctor_iterator I = ctor_begin(), E = ctor_end(); I != E; ++I) - if (I->isMoveConstructor()) - return *I; - - return 0; -} - -CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const { - ASTContext &Context = getASTContext(); - QualType Class = Context.getTypeDeclType(const_cast<CXXRecordDecl *>(this)); - DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); - - SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found; - DeclContext::lookup_const_iterator Op, OpEnd; - for (llvm::tie(Op, OpEnd) = this->lookup(Name); Op != OpEnd; ++Op) { - // C++ [class.copy]p9: - // A user-declared copy assignment operator is a non-static non-template - // member function of class X with exactly one parameter of type X, X&, - // const X&, volatile X& or const volatile X&. - const CXXMethodDecl* Method = dyn_cast<CXXMethodDecl>(*Op); - if (!Method || Method->isStatic() || Method->getPrimaryTemplate()) - continue; - - const FunctionProtoType *FnType - = Method->getType()->getAs<FunctionProtoType>(); - assert(FnType && "Overloaded operator has no prototype."); - // Don't assert on this; an invalid decl might have been left in the AST. - if (FnType->getNumArgs() != 1 || FnType->isVariadic()) - continue; - - QualType ArgType = FnType->getArgType(0); - Qualifiers Quals; - if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>()) { - ArgType = Ref->getPointeeType(); - // If we have a const argument and we have a reference to a non-const, - // this function does not match. - if (ArgIsConst && !ArgType.isConstQualified()) - continue; - - Quals = ArgType.getQualifiers(); - } else { - // By-value copy-assignment operators are treated like const X& - // copy-assignment operators. - Quals = Qualifiers::fromCVRMask(Qualifiers::Const); - } - - if (!Context.hasSameUnqualifiedType(ArgType, Class)) - continue; - - // Save this copy-assignment operator. It might be "the one". - Found.push_back(std::make_pair(const_cast<CXXMethodDecl *>(Method), Quals)); - } - - // Use a simplistic form of overload resolution to find the candidate. - return GetBestOverloadCandidateSimple(Found); -} - -CXXMethodDecl *CXXRecordDecl::getMoveAssignmentOperator() const { - for (method_iterator I = method_begin(), E = method_end(); I != E; ++I) - if (I->isMoveAssignmentOperator()) - return *I; - - return 0; -} - void CXXRecordDecl::markedVirtualFunctionPure() { // C++ [class.abstract]p2: // A class is abstract if it has at least one pure virtual function. data().Abstract = true; } -void CXXRecordDecl::markedConstructorConstexpr(CXXConstructorDecl *CD) { - if (!CD->isCopyOrMoveConstructor()) - data().HasConstexprNonCopyMoveConstructor = true; - - if (CD->isDefaultConstructor()) - data().HasConstexprDefaultConstructor = true; -} - void CXXRecordDecl::addedMember(Decl *D) { if (!D->isImplicit() && !isa<FieldDecl>(D) && @@ -502,75 +436,41 @@ void CXXRecordDecl::addedMember(Decl *D) { // A class that declares or inherits a virtual function is called a // polymorphic class. data().Polymorphic = true; - - // C++0x [class.ctor]p5 - // A default constructor is trivial [...] if: - // -- its class has no virtual functions [...] - data().HasTrivialDefaultConstructor = false; - // C++0x [class.copy]p13: - // A copy/move constructor for class X is trivial if [...] + // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25: + // A [default constructor, copy/move constructor, or copy/move + // assignment operator for a class X] is trivial [...] if: // -- class X has no virtual functions [...] - data().HasTrivialCopyConstructor = false; - data().HasTrivialMoveConstructor = false; + data().HasTrivialSpecialMembers &= SMF_Destructor; - // C++0x [class.copy]p27: - // A copy/move assignment operator for class X is trivial if [...] - // -- class X has no virtual functions [...] - data().HasTrivialCopyAssignment = false; - data().HasTrivialMoveAssignment = false; - // C++0x [class]p7: // A standard-layout class is a class that: [...] // -- has no virtual functions data().IsStandardLayout = false; } } - - if (D->isImplicit()) { - // Notify that an implicit member was added after the definition - // was completed. - if (!isBeingDefined()) - if (ASTMutationListener *L = getASTMutationListener()) - L->AddedCXXImplicitMember(data().Definition, D); - - // If this is a special member function, note that it was added and then - // return early. - if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { - if (Constructor->isDefaultConstructor()) { - data().DeclaredDefaultConstructor = true; - if (Constructor->isConstexpr()) { - data().HasConstexprDefaultConstructor = true; - data().HasConstexprNonCopyMoveConstructor = true; - } - } else if (Constructor->isCopyConstructor()) { - data().DeclaredCopyConstructor = true; - } else if (Constructor->isMoveConstructor()) { - data().DeclaredMoveConstructor = true; - } else - goto NotASpecialMember; - return; - } else if (isa<CXXDestructorDecl>(D)) { - data().DeclaredDestructor = true; - return; - } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { - if (Method->isCopyAssignmentOperator()) - data().DeclaredCopyAssignment = true; - else if (Method->isMoveAssignmentOperator()) - data().DeclaredMoveAssignment = true; - else - goto NotASpecialMember; - return; - } -NotASpecialMember:; - // Any other implicit declarations are handled like normal declarations. - } - - // Handle (user-declared) constructors. + // Notify the listener if an implicit member was added after the definition + // was completed. + if (!isBeingDefined() && D->isImplicit()) + if (ASTMutationListener *L = getASTMutationListener()) + L->AddedCXXImplicitMember(data().Definition, D); + + // The kind of special member this declaration is, if any. + unsigned SMKind = 0; + + // Handle constructors. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { - // Note that we have a user-declared constructor. - data().UserDeclaredConstructor = true; + if (!Constructor->isImplicit()) { + // Note that we have a user-declared constructor. + data().UserDeclaredConstructor = true; + + // C++ [class]p4: + // A POD-struct is an aggregate class [...] + // Since the POD bit is meant to be C++03 POD-ness, clear it even if the + // type is technically an aggregate in C++0x since it wouldn't be in 03. + data().PlainOldData = false; + } // Technically, "user-provided" is only defined for special member // functions, but the intent of the standard is clearly that it should apply @@ -578,47 +478,29 @@ NotASpecialMember:; bool UserProvided = Constructor->isUserProvided(); if (Constructor->isDefaultConstructor()) { - data().DeclaredDefaultConstructor = true; - if (UserProvided) { - // C++0x [class.ctor]p5: - // A default constructor is trivial if it is not user-provided [...] - data().HasTrivialDefaultConstructor = false; + SMKind |= SMF_DefaultConstructor; + + if (UserProvided) data().UserProvidedDefaultConstructor = true; - } - if (Constructor->isConstexpr()) { + if (Constructor->isConstexpr()) data().HasConstexprDefaultConstructor = true; - data().HasConstexprNonCopyMoveConstructor = true; - } } - // Note when we have a user-declared copy or move constructor, which will - // suppress the implicit declaration of those constructors. if (!FunTmpl) { - if (Constructor->isCopyConstructor()) { - data().UserDeclaredCopyConstructor = true; - data().DeclaredCopyConstructor = true; - - // C++0x [class.copy]p13: - // A copy/move constructor for class X is trivial if it is not - // user-provided [...] - if (UserProvided) - data().HasTrivialCopyConstructor = false; - } else if (Constructor->isMoveConstructor()) { - data().UserDeclaredMoveConstructor = true; - data().DeclaredMoveConstructor = true; - - // C++0x [class.copy]p13: - // A copy/move constructor for class X is trivial if it is not - // user-provided [...] - if (UserProvided) - data().HasTrivialMoveConstructor = false; - } + unsigned Quals; + if (Constructor->isCopyConstructor(Quals)) { + SMKind |= SMF_CopyConstructor; + + if (Quals & Qualifiers::Const) + data().HasDeclaredCopyConstructorWithConstParam = true; + } else if (Constructor->isMoveConstructor()) + SMKind |= SMF_MoveConstructor; } - if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) { - // Record if we see any constexpr constructors which are neither copy - // nor move constructors. + + // Record if we see any constexpr constructors which are neither copy + // nor move constructors. + if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) data().HasConstexprNonCopyMoveConstructor = true; - } // C++ [dcl.init.aggr]p1: // An aggregate is an array or a class with no user-declared @@ -626,106 +508,99 @@ NotASpecialMember:; // C++0x [dcl.init.aggr]p1: // An aggregate is an array or a class with no user-provided // constructors [...]. - if (!getASTContext().getLangOpts().CPlusPlus0x || UserProvided) + if (getASTContext().getLangOpts().CPlusPlus11 + ? UserProvided : !Constructor->isImplicit()) data().Aggregate = false; - - // C++ [class]p4: - // A POD-struct is an aggregate class [...] - // Since the POD bit is meant to be C++03 POD-ness, clear it even if the - // type is technically an aggregate in C++0x since it wouldn't be in 03. - data().PlainOldData = false; - - return; } - // Handle (user-declared) destructors. + // Handle destructors. if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) { - data().DeclaredDestructor = true; - data().UserDeclaredDestructor = true; - data().HasIrrelevantDestructor = false; - - // C++ [class]p4: - // A POD-struct is an aggregate class that has [...] no user-defined - // destructor. - // This bit is the C++03 POD bit, not the 0x one. - data().PlainOldData = false; - - // C++11 [class.dtor]p5: - // A destructor is trivial if it is not user-provided and if - // -- the destructor is not virtual. - if (DD->isUserProvided() || DD->isVirtual()) - data().HasTrivialDestructor = false; + SMKind |= SMF_Destructor; - return; + if (!DD->isImplicit()) + data().HasIrrelevantDestructor = false; + + // C++11 [class.dtor]p5: + // A destructor is trivial if [...] the destructor is not virtual. + if (DD->isVirtual()) + data().HasTrivialSpecialMembers &= ~SMF_Destructor; } - - // Handle (user-declared) member functions. + + // Handle member functions. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { if (Method->isCopyAssignmentOperator()) { - // C++ [class]p4: - // A POD-struct is an aggregate class that [...] has no user-defined - // copy assignment operator [...]. - // This is the C++03 bit only. - data().PlainOldData = false; + SMKind |= SMF_CopyAssignment; - // This is a copy assignment operator. - - // Suppress the implicit declaration of a copy constructor. - data().UserDeclaredCopyAssignment = true; - data().DeclaredCopyAssignment = true; - - // C++0x [class.copy]p27: - // A copy/move assignment operator for class X is trivial if it is - // neither user-provided nor deleted [...] - if (Method->isUserProvided()) - data().HasTrivialCopyAssignment = false; - - return; + const ReferenceType *ParamTy = + Method->getParamDecl(0)->getType()->getAs<ReferenceType>(); + if (!ParamTy || ParamTy->getPointeeType().isConstQualified()) + data().HasDeclaredCopyAssignmentWithConstParam = true; } - - if (Method->isMoveAssignmentOperator()) { - // This is an extension in C++03 mode, but we'll keep consistency by - // taking a move assignment operator to induce non-POD-ness - data().PlainOldData = false; - - // This is a move assignment operator. - data().UserDeclaredMoveAssignment = true; - data().DeclaredMoveAssignment = true; - // C++0x [class.copy]p27: - // A copy/move assignment operator for class X is trivial if it is - // neither user-provided nor deleted [...] - if (Method->isUserProvided()) - data().HasTrivialMoveAssignment = false; - } + if (Method->isMoveAssignmentOperator()) + SMKind |= SMF_MoveAssignment; // Keep the list of conversion functions up-to-date. if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { - // We don't record specializations. - if (Conversion->getPrimaryTemplate()) - return; - // FIXME: We intentionally don't use the decl's access here because it // hasn't been set yet. That's really just a misdesign in Sema. - - if (FunTmpl) { + if (Conversion->getPrimaryTemplate()) { + // We don't record specializations. + } else if (FunTmpl) { if (FunTmpl->getPreviousDecl()) data().Conversions.replace(FunTmpl->getPreviousDecl(), FunTmpl); else - data().Conversions.addDecl(FunTmpl); + data().Conversions.addDecl(getASTContext(), FunTmpl); } else { if (Conversion->getPreviousDecl()) data().Conversions.replace(Conversion->getPreviousDecl(), Conversion); else - data().Conversions.addDecl(Conversion); + data().Conversions.addDecl(getASTContext(), Conversion); } } - + + if (SMKind) { + // If this is the first declaration of a special member, we no longer have + // an implicit trivial special member. + data().HasTrivialSpecialMembers &= + data().DeclaredSpecialMembers | ~SMKind; + + if (!Method->isImplicit() && !Method->isUserProvided()) { + // This method is user-declared but not user-provided. We can't work out + // whether it's trivial yet (not until we get to the end of the class). + // We'll handle this method in finishedDefaultedOrDeletedMember. + } else if (Method->isTrivial()) + data().HasTrivialSpecialMembers |= SMKind; + else + data().DeclaredNonTrivialSpecialMembers |= SMKind; + + // Note when we have declared a declared special member, and suppress the + // implicit declaration of this special member. + data().DeclaredSpecialMembers |= SMKind; + + if (!Method->isImplicit()) { + data().UserDeclaredSpecialMembers |= SMKind; + + // C++03 [class]p4: + // A POD-struct is an aggregate class that has [...] no user-defined + // copy assignment operator and no user-defined destructor. + // + // Since the POD bit is meant to be C++03 POD-ness, and in C++03, + // aggregates could not have any constructors, clear it even for an + // explicitly defaulted or deleted constructor. + // type is technically an aggregate in C++0x since it wouldn't be in 03. + // + // Also, a user-declared move assignment operator makes a class non-POD. + // This is an extension in C++03. + data().PlainOldData = false; + } + } + return; } - + // Handle non-static data members. if (FieldDecl *Field = dyn_cast<FieldDecl>(D)) { // C++ [class.bit]p2: @@ -785,7 +660,8 @@ NotASpecialMember:; data().PlainOldData = false; if (T->isReferenceType()) { - data().HasTrivialDefaultConstructor = false; + if (!Field->hasInClassInitializer()) + data().HasUninitializedReferenceMember = true; // C++0x [class]p7: // A standard-layout class is a class that: @@ -803,7 +679,7 @@ NotASpecialMember:; // C++11 [class]p5: // A default constructor is trivial if [...] no non-static data member // of its class has a brace-or-equal-initializer. - data().HasTrivialDefaultConstructor = false; + data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor; // C++11 [dcl.init.aggr]p1: // An aggregate is a [...] class with [...] no @@ -815,16 +691,39 @@ NotASpecialMember:; data().PlainOldData = false; } + // C++11 [class.copy]p23: + // A defaulted copy/move assignment operator for a class X is defined + // as deleted if X has: + // -- a non-static data member of reference type + if (T->isReferenceType()) + data().DefaultedMoveAssignmentIsDeleted = true; + if (const RecordType *RecordTy = T->getAs<RecordType>()) { CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl()); if (FieldRec->getDefinition()) { + addedClassSubobject(FieldRec); + + // C++11 [class.ctor]p5, C++11 [class.copy]p11: + // A defaulted [special member] for a class X is defined as + // deleted if: + // -- X is a union-like class that has a variant member with a + // non-trivial [corresponding special member] + if (isUnion()) { + if (FieldRec->hasNonTrivialMoveConstructor()) + data().DefaultedMoveConstructorIsDeleted = true; + if (FieldRec->hasNonTrivialMoveAssignment()) + data().DefaultedMoveAssignmentIsDeleted = true; + if (FieldRec->hasNonTrivialDestructor()) + data().DefaultedDestructorIsDeleted = true; + } + // C++0x [class.ctor]p5: // A default constructor is trivial [...] if: // -- for all the non-static data members of its class that are of // class type (or array thereof), each such class has a trivial // default constructor. if (!FieldRec->hasTrivialDefaultConstructor()) - data().HasTrivialDefaultConstructor = false; + data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor; // C++0x [class.copy]p13: // A copy/move constructor for class X is trivial if [...] @@ -832,13 +731,13 @@ NotASpecialMember:; // -- for each non-static data member of X that is of class type (or // an array thereof), the constructor selected to copy/move that // member is trivial; - // FIXME: C++0x: We don't correctly model 'selected' constructors. if (!FieldRec->hasTrivialCopyConstructor()) - data().HasTrivialCopyConstructor = false; - if (!FieldRec->hasTrivialMoveConstructor() || - !(FieldRec->hasDeclaredMoveConstructor() || - FieldRec->needsImplicitMoveConstructor())) - data().HasTrivialMoveConstructor = false; + data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor; + // If the field doesn't have a simple move constructor, we'll eagerly + // declare the move constructor for this class and we'll decide whether + // it's trivial then. + if (!FieldRec->hasTrivialMoveConstructor()) + data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor; // C++0x [class.copy]p27: // A copy/move assignment operator for class X is trivial if [...] @@ -846,20 +745,22 @@ NotASpecialMember:; // -- for each non-static data member of X that is of class type (or // an array thereof), the assignment operator selected to // copy/move that member is trivial; - // FIXME: C++0x: We don't correctly model 'selected' operators. if (!FieldRec->hasTrivialCopyAssignment()) - data().HasTrivialCopyAssignment = false; - if (!FieldRec->hasTrivialMoveAssignment() || - !(FieldRec->hasDeclaredMoveAssignment() || - FieldRec->needsImplicitMoveAssignment())) - data().HasTrivialMoveAssignment = false; + data().HasTrivialSpecialMembers &= ~SMF_CopyAssignment; + // If the field doesn't have a simple move assignment, we'll eagerly + // declare the move assignment for this class and we'll decide whether + // it's trivial then. + if (!FieldRec->hasTrivialMoveAssignment()) + data().HasTrivialSpecialMembers &= ~SMF_MoveAssignment; if (!FieldRec->hasTrivialDestructor()) - data().HasTrivialDestructor = false; + data().HasTrivialSpecialMembers &= ~SMF_Destructor; if (!FieldRec->hasIrrelevantDestructor()) data().HasIrrelevantDestructor = false; if (FieldRec->hasObjectMember()) setHasObjectMember(true); + if (FieldRec->hasVolatileMember()) + setHasVolatileMember(true); // C++0x [class]p7: // A standard-layout class is a class that: @@ -910,12 +811,42 @@ NotASpecialMember:; // The standard requires any in-class initializer to be a constant // expression. We consider this to be a defect. data().DefaultedDefaultConstructorIsConstexpr = false; + + // C++11 [class.copy]p8: + // The implicitly-declared copy constructor for a class X will have + // the form 'X::X(const X&)' if [...] for all the non-static data + // members of X that are of a class type M (or array thereof), each + // such class type has a copy constructor whose first parameter is + // of type 'const M&' or 'const volatile M&'. + if (!FieldRec->hasCopyConstructorWithConstParam()) + data().ImplicitCopyConstructorHasConstParam = false; + + // C++11 [class.copy]p18: + // The implicitly-declared copy assignment oeprator for a class X will + // have the form 'X& X::operator=(const X&)' if [...] for all the + // non-static data members of X that are of a class type M (or array + // thereof), each such class type has a copy assignment operator whose + // parameter is of type 'const M&', 'const volatile M&' or 'M'. + if (!FieldRec->hasCopyAssignmentWithConstParam()) + data().ImplicitCopyAssignmentHasConstParam = false; + + if (FieldRec->hasUninitializedReferenceMember() && + !Field->hasInClassInitializer()) + data().HasUninitializedReferenceMember = true; } } else { // Base element type of field is a non-class type. if (!T->isLiteralType() || (!Field->hasInClassInitializer() && !isUnion())) data().DefaultedDefaultConstructorIsConstexpr = false; + + // C++11 [class.copy]p23: + // A defaulted copy/move assignment operator for a class X is defined + // as deleted if X has: + // -- a non-static data member of const non-class type (or array + // thereof) + if (T.isConstQualified()) + data().DefaultedMoveAssignmentIsDeleted = true; } // C++0x [class]p7: @@ -943,7 +874,41 @@ NotASpecialMember:; if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(D)) if (Shadow->getDeclName().getNameKind() == DeclarationName::CXXConversionFunctionName) - data().Conversions.addDecl(Shadow, Shadow->getAccess()); + data().Conversions.addDecl(getASTContext(), Shadow, Shadow->getAccess()); +} + +void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) { + assert(!D->isImplicit() && !D->isUserProvided()); + + // The kind of special member this declaration is, if any. + unsigned SMKind = 0; + + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { + if (Constructor->isDefaultConstructor()) { + SMKind |= SMF_DefaultConstructor; + if (Constructor->isConstexpr()) + data().HasConstexprDefaultConstructor = true; + } + if (Constructor->isCopyConstructor()) + SMKind |= SMF_CopyConstructor; + else if (Constructor->isMoveConstructor()) + SMKind |= SMF_MoveConstructor; + else if (Constructor->isConstexpr()) + // We may now know that the constructor is constexpr. + data().HasConstexprNonCopyMoveConstructor = true; + } else if (isa<CXXDestructorDecl>(D)) + SMKind |= SMF_Destructor; + else if (D->isCopyAssignmentOperator()) + SMKind |= SMF_CopyAssignment; + else if (D->isMoveAssignmentOperator()) + SMKind |= SMF_MoveAssignment; + + // Update which trivial / non-trivial special members we have. + // addedMember will have skipped this step for this member. + if (D->isTrivial()) + data().HasTrivialSpecialMembers |= SMKind; + else + data().DeclaredNonTrivialSpecialMembers |= SMKind; } bool CXXRecordDecl::isCLike() const { @@ -1004,7 +969,7 @@ static void CollectVisibleConversions(ASTContext &Context, bool InVirtual, AccessSpecifier Access, const llvm::SmallPtrSet<CanQualType, 8> &ParentHiddenTypes, - UnresolvedSetImpl &Output, + ASTUnresolvedSet &Output, UnresolvedSetImpl &VOutput, llvm::SmallPtrSet<NamedDecl*, 8> &HiddenVBaseCs) { // The set of types which have conversions in this class or its @@ -1015,12 +980,13 @@ static void CollectVisibleConversions(ASTContext &Context, // Collect the direct conversions and figure out which conversions // will be hidden in the subclasses. - UnresolvedSetImpl &Cs = *Record->getConversionFunctions(); - if (!Cs.empty()) { + CXXRecordDecl::conversion_iterator ConvI = Record->conversion_begin(); + CXXRecordDecl::conversion_iterator ConvE = Record->conversion_end(); + if (ConvI != ConvE) { HiddenTypesBuffer = ParentHiddenTypes; HiddenTypes = &HiddenTypesBuffer; - for (UnresolvedSetIterator I = Cs.begin(), E = Cs.end(); I != E; ++I) { + for (CXXRecordDecl::conversion_iterator I = ConvI; I != ConvE; ++I) { CanQualType ConvType(GetConversionType(Context, I.getDecl())); bool Hidden = ParentHiddenTypes.count(ConvType); if (!Hidden) @@ -1039,7 +1005,7 @@ static void CollectVisibleConversions(ASTContext &Context, if (InVirtual) VOutput.addDecl(I.getDecl(), IAccess); else - Output.addDecl(I.getDecl(), IAccess); + Output.addDecl(Context, I.getDecl(), IAccess); } } } @@ -1066,7 +1032,7 @@ static void CollectVisibleConversions(ASTContext &Context, /// bases. It might be worth special-casing that, really. static void CollectVisibleConversions(ASTContext &Context, CXXRecordDecl *Record, - UnresolvedSetImpl &Output) { + ASTUnresolvedSet &Output) { // The collection of all conversions in virtual bases that we've // found. These will be added to the output as long as they don't // appear in the hidden-conversions set. @@ -1081,10 +1047,11 @@ static void CollectVisibleConversions(ASTContext &Context, // Go ahead and collect the direct conversions and add them to the // hidden-types set. - UnresolvedSetImpl &Cs = *Record->getConversionFunctions(); - Output.append(Cs.begin(), Cs.end()); - for (UnresolvedSetIterator I = Cs.begin(), E = Cs.end(); I != E; ++I) - HiddenTypes.insert(GetConversionType(Context, I.getDecl())); + CXXRecordDecl::conversion_iterator ConvI = Record->conversion_begin(); + CXXRecordDecl::conversion_iterator ConvE = Record->conversion_end(); + Output.append(Context, ConvI, ConvE); + for (; ConvI != ConvE; ++ConvI) + HiddenTypes.insert(GetConversionType(Context, ConvI.getDecl())); // Recursively collect conversions from base classes. for (CXXRecordDecl::base_class_iterator @@ -1101,22 +1068,24 @@ static void CollectVisibleConversions(ASTContext &Context, for (UnresolvedSetIterator I = VBaseCs.begin(), E = VBaseCs.end(); I != E; ++I) { if (!HiddenVBaseCs.count(cast<NamedDecl>(I.getDecl()->getCanonicalDecl()))) - Output.addDecl(I.getDecl(), I.getAccess()); + Output.addDecl(Context, I.getDecl(), I.getAccess()); } } /// getVisibleConversionFunctions - get all conversion functions visible /// in current class; including conversion function templates. -const UnresolvedSetImpl *CXXRecordDecl::getVisibleConversionFunctions() { +std::pair<CXXRecordDecl::conversion_iterator,CXXRecordDecl::conversion_iterator> +CXXRecordDecl::getVisibleConversionFunctions() { // If root class, all conversions are visible. if (bases_begin() == bases_end()) - return &data().Conversions; + return std::make_pair(data().Conversions.begin(), data().Conversions.end()); // If visible conversion list is already evaluated, return it. - if (data().ComputedVisibleConversions) - return &data().VisibleConversions; - CollectVisibleConversions(getASTContext(), this, data().VisibleConversions); - data().ComputedVisibleConversions = true; - return &data().VisibleConversions; + if (!data().ComputedVisibleConversions) { + CollectVisibleConversions(getASTContext(), this, data().VisibleConversions); + data().ComputedVisibleConversions = true; + } + return std::make_pair(data().VisibleConversions.begin(), + data().VisibleConversions.end()); } void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { @@ -1131,7 +1100,7 @@ void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { // with sufficiently large numbers of directly-declared conversions // that asymptotic behavior matters. - UnresolvedSetImpl &Convs = *getConversionFunctions(); + ASTUnresolvedSet &Convs = data().Conversions; for (unsigned I = 0, E = Convs.size(); I != E; ++I) { if (Convs[I].getDecl() == ConvDecl) { Convs.erase(I); @@ -1151,10 +1120,6 @@ CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const { return 0; } -MemberSpecializationInfo *CXXRecordDecl::getMemberSpecializationInfo() const { - return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>(); -} - void CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD, TemplateSpecializationKind TSK) { @@ -1200,12 +1165,11 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const { = Context.DeclarationNames.getCXXDestructorName( Context.getCanonicalType(ClassType)); - DeclContext::lookup_const_iterator I, E; - llvm::tie(I, E) = lookup(Name); - if (I == E) + DeclContext::lookup_const_result R = lookup(Name); + if (R.empty()) return 0; - CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(*I); + CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(R.front()); return Dtor; } @@ -1225,12 +1189,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { // non-trivial. struct DefinitionData &Data = data(); Data.PlainOldData = false; - Data.HasTrivialDefaultConstructor = false; - Data.HasTrivialCopyConstructor = false; - Data.HasTrivialMoveConstructor = false; - Data.HasTrivialCopyAssignment = false; - Data.HasTrivialMoveAssignment = false; - Data.HasTrivialDestructor = false; + Data.HasTrivialSpecialMembers = 0; Data.HasIrrelevantDestructor = false; } @@ -1270,7 +1229,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { for (UnresolvedSetIterator I = data().Conversions.begin(), E = data().Conversions.end(); I != E; ++I) - data().Conversions.setAccess(I, (*I)->getAccess()); + I.setAccess((*I)->getAccess()); } bool CXXRecordDecl::mayBeAbstract() const { @@ -1292,6 +1251,42 @@ bool CXXRecordDecl::mayBeAbstract() const { void CXXMethodDecl::anchor() { } +bool CXXMethodDecl::isStatic() const { + const CXXMethodDecl *MD = this; + for (;;) { + const CXXMethodDecl *C = MD->getCanonicalDecl(); + if (C != MD) { + MD = C; + continue; + } + + FunctionTemplateSpecializationInfo *Info = + MD->getTemplateSpecializationInfo(); + if (!Info) + break; + MD = cast<CXXMethodDecl>(Info->getTemplate()->getTemplatedDecl()); + } + + if (MD->getStorageClass() == SC_Static) + return true; + + DeclarationName Name = getDeclName(); + // [class.free]p1: + // Any allocation function for a class T is a static member + // (even if not explicitly declared static). + if (Name.getCXXOverloadedOperator() == OO_New || + Name.getCXXOverloadedOperator() == OO_Array_New) + return true; + + // [class.free]p6 Any deallocation function for a class X is a static member + // (even if not explicitly declared static). + if (Name.getCXXOverloadedOperator() == OO_Delete || + Name.getCXXOverloadedOperator() == OO_Array_Delete) + return true; + + return false; +} + static bool recursivelyOverrides(const CXXMethodDecl *DerivedMD, const CXXMethodDecl *BaseMD) { for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(), @@ -1324,7 +1319,7 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD, } lookup_const_result Candidates = RD->lookup(getDeclName()); - for (NamedDecl * const * I = Candidates.first; I != Candidates.second; ++I) { + for (NamedDecl * const * I = Candidates.begin(); I != Candidates.end(); ++I) { CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*I); if (!MD) continue; @@ -1353,10 +1348,10 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isStatic, StorageClass SCAsWritten, bool isInline, + StorageClass SC, bool isInline, bool isConstexpr, SourceLocation EndLocation) { return new (C) CXXMethodDecl(CXXMethod, RD, StartLoc, NameInfo, T, TInfo, - isStatic, SCAsWritten, isInline, isConstexpr, + SC, isInline, isConstexpr, EndLocation); } @@ -1364,7 +1359,7 @@ CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXMethodDecl)); return new (Mem) CXXMethodDecl(CXXMethod, 0, SourceLocation(), DeclarationNameInfo(), QualType(), - 0, false, SC_None, false, false, + 0, SC_None, false, false, SourceLocation()); } @@ -1399,9 +1394,10 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const { // This function is a usual deallocation function if there are no // single-parameter deallocation functions of the same kind. - for (DeclContext::lookup_const_result R = getDeclContext()->lookup(getDeclName()); - R.first != R.second; ++R.first) { - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*R.first)) + DeclContext::lookup_const_result R = getDeclContext()->lookup(getDeclName()); + for (DeclContext::lookup_const_result::iterator I = R.begin(), E = R.end(); + I != E; ++I) { + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) if (FD->getNumParams() == 1) return false; } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp index 553d170..37a812e 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp @@ -27,7 +27,8 @@ FriendDecl *FriendDecl::getNextFriendSlowCase() { FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend, - SourceLocation FriendL) { + SourceLocation FriendL, + ArrayRef<TemplateParameterList*> FriendTypeTPLists) { #ifndef NDEBUG if (Friend.is<NamedDecl*>()) { NamedDecl *D = Friend.get<NamedDecl*>(); @@ -40,15 +41,25 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, // to the original declaration when instantiating members. assert(D->getFriendObjectKind() || (cast<CXXRecordDecl>(DC)->getTemplateSpecializationKind())); + // These template parameters are for friend types only. + assert(FriendTypeTPLists.size() == 0); } #endif - FriendDecl *FD = new (C) FriendDecl(DC, L, Friend, FriendL); + std::size_t Size = sizeof(FriendDecl) + + FriendTypeTPLists.size() * sizeof(TemplateParameterList*); + void *Mem = C.Allocate(Size); + FriendDecl *FD = new (Mem) FriendDecl(DC, L, Friend, FriendL, + FriendTypeTPLists); cast<CXXRecordDecl>(DC)->pushFriendDecl(FD); return FD; } -FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FriendDecl)); - return new (Mem) FriendDecl(EmptyShell()); +FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, unsigned ID, + unsigned FriendTypeNumTPLists) { + std::size_t Size = sizeof(FriendDecl) + + FriendTypeNumTPLists * sizeof(TemplateParameterList*); + void *Mem = AllocateDeserializedDecl(C, ID, Size); + return new (Mem) FriendDecl(EmptyShell(), FriendTypeNumTPLists); } + diff --git a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp index 036acc2..9861f22 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "clang/AST/DeclGroup.h" -#include "clang/AST/Decl.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" #include "llvm/Support/Allocator.h" using namespace clang; diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp index 65a9878..5f5ba52 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp @@ -13,8 +13,9 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/Stmt.h" #include "clang/AST/ASTMutationListener.h" +#include "clang/AST/Attr.h" +#include "clang/AST/Stmt.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" using namespace clang; @@ -53,8 +54,9 @@ void ObjCContainerDecl::anchor() { } /// ObjCIvarDecl * ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const { - lookup_const_iterator Ivar, IvarEnd; - for (llvm::tie(Ivar, IvarEnd) = lookup(Id); Ivar != IvarEnd; ++Ivar) { + lookup_const_result R = lookup(Id); + for (lookup_const_iterator Ivar = R.begin(), IvarEnd = R.end(); + Ivar != IvarEnd; ++Ivar) { if (ObjCIvarDecl *ivar = dyn_cast<ObjCIvarDecl>(*Ivar)) return ivar; } @@ -63,7 +65,16 @@ ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const { // Get the local instance/class method declared in this interface. ObjCMethodDecl * -ObjCContainerDecl::getMethod(Selector Sel, bool isInstance) const { +ObjCContainerDecl::getMethod(Selector Sel, bool isInstance, + bool AllowHidden) const { + // If this context is a hidden protocol definition, don't find any + // methods there. + if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) { + if (const ObjCProtocolDecl *Def = Proto->getDefinition()) + if (Def->isHidden() && !AllowHidden) + return 0; + } + // Since instance & class methods can have the same name, the loop below // ensures we get the correct method. // @@ -72,8 +83,9 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance) const { // + (float) class_method; // @end // - lookup_const_iterator Meth, MethEnd; - for (llvm::tie(Meth, MethEnd) = lookup(Sel); Meth != MethEnd; ++Meth) { + lookup_const_result R = lookup(Sel); + for (lookup_const_iterator Meth = R.begin(), MethEnd = R.end(); + Meth != MethEnd; ++Meth) { ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth); if (MD && MD->isInstanceMethod() == isInstance) return MD; @@ -81,13 +93,86 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance) const { return 0; } +/// HasUserDeclaredSetterMethod - This routine returns 'true' if a user declared setter +/// method was found in the class, its protocols, its super classes or categories. +/// It also returns 'true' if one of its categories has declared a 'readwrite' property. +/// This is because, user must provide a setter method for the category's 'readwrite' +/// property. +bool +ObjCContainerDecl::HasUserDeclaredSetterMethod(const ObjCPropertyDecl *Property) const { + Selector Sel = Property->getSetterName(); + lookup_const_result R = lookup(Sel); + for (lookup_const_iterator Meth = R.begin(), MethEnd = R.end(); + Meth != MethEnd; ++Meth) { + ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth); + if (MD && MD->isInstanceMethod() && !MD->isImplicit()) + return true; + } + + if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(this)) { + // Also look into categories, including class extensions, looking + // for a user declared instance method. + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = ID->visible_categories_begin(), + CatEnd = ID->visible_categories_end(); + Cat != CatEnd; + ++Cat) { + if (ObjCMethodDecl *MD = Cat->getInstanceMethod(Sel)) + if (!MD->isImplicit()) + return true; + if (Cat->IsClassExtension()) + continue; + // Also search through the categories looking for a 'readwrite' declaration + // of this property. If one found, presumably a setter will be provided + // (properties declared in categories will not get auto-synthesized). + for (ObjCContainerDecl::prop_iterator P = Cat->prop_begin(), + E = Cat->prop_end(); P != E; ++P) + if (P->getIdentifier() == Property->getIdentifier()) { + if (P->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite) + return true; + break; + } + } + + // Also look into protocols, for a user declared instance method. + for (ObjCInterfaceDecl::all_protocol_iterator P = + ID->all_referenced_protocol_begin(), + PE = ID->all_referenced_protocol_end(); P != PE; ++P) { + ObjCProtocolDecl *Proto = (*P); + if (Proto->HasUserDeclaredSetterMethod(Property)) + return true; + } + // And in its super class. + ObjCInterfaceDecl *OSC = ID->getSuperClass(); + while (OSC) { + if (OSC->HasUserDeclaredSetterMethod(Property)) + return true; + OSC = OSC->getSuperClass(); + } + } + if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(this)) + for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(), + E = PD->protocol_end(); PI != E; ++PI) { + if ((*PI)->HasUserDeclaredSetterMethod(Property)) + return true; + } + return false; +} + ObjCPropertyDecl * ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, IdentifierInfo *propertyID) { + // If this context is a hidden protocol definition, don't find any + // property. + if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(DC)) { + if (const ObjCProtocolDecl *Def = Proto->getDefinition()) + if (Def->isHidden()) + return 0; + } - DeclContext::lookup_const_iterator I, E; - llvm::tie(I, E) = DC->lookup(propertyID); - for ( ; I != E; ++I) + DeclContext::lookup_const_result R = DC->lookup(propertyID); + for (DeclContext::lookup_const_iterator I = R.begin(), E = R.end(); I != E; + ++I) if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I)) return PD; @@ -108,6 +193,12 @@ ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const { /// in 'PropertyId' and returns it. It returns 0, if not found. ObjCPropertyDecl * ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { + // Don't find properties within hidden protocol definitions. + if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) { + if (const ObjCProtocolDecl *Def = Proto->getDefinition()) + if (Def->isHidden()) + return 0; + } if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId)) @@ -126,12 +217,15 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { } case Decl::ObjCInterface: { const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(this); - // Look through categories. - for (ObjCCategoryDecl *Cat = OID->getCategoryList(); - Cat; Cat = Cat->getNextClassCategory()) + // Look through categories (but not extensions). + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = OID->visible_categories_begin(), + CatEnd = OID->visible_categories_end(); + Cat != CatEnd; ++Cat) { if (!Cat->IsClassExtension()) if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(PropertyId)) return P; + } // Look through protocols. for (ObjCInterfaceDecl::all_protocol_iterator @@ -190,21 +284,43 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( return 0; } -void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM) const { +void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM, + PropertyDeclOrder &PO) const { for (ObjCContainerDecl::prop_iterator P = prop_begin(), E = prop_end(); P != E; ++P) { ObjCPropertyDecl *Prop = *P; PM[Prop->getIdentifier()] = Prop; + PO.push_back(Prop); } for (ObjCInterfaceDecl::all_protocol_iterator PI = all_referenced_protocol_begin(), E = all_referenced_protocol_end(); PI != E; ++PI) - (*PI)->collectPropertiesToImplement(PM); + (*PI)->collectPropertiesToImplement(PM, PO); // Note, the properties declared only in class extensions are still copied // into the main @interface's property list, and therefore we don't // explicitly, have to search class extension properties. } +bool ObjCInterfaceDecl::isArcWeakrefUnavailable() const { + const ObjCInterfaceDecl *Class = this; + while (Class) { + if (Class->hasAttr<ArcWeakrefUnavailableAttr>()) + return true; + Class = Class->getSuperClass(); + } + return false; +} + +const ObjCInterfaceDecl *ObjCInterfaceDecl::isObjCRequiresPropertyDefs() const { + const ObjCInterfaceDecl *Class = this; + while (Class) { + if (Class->hasAttr<ObjCRequiresPropertyDefsAttr>()) + return Class; + Class = Class->getSuperClass(); + } + return 0; +} + void ObjCInterfaceDecl::mergeClassExtensionProtocolList( ObjCProtocolDecl *const* ExtList, unsigned ExtNum, ASTContext &C) @@ -254,8 +370,8 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList( void ObjCInterfaceDecl::allocateDefinitionData() { assert(!hasDefinition() && "ObjC class already has a definition"); - Data = new (getASTContext()) DefinitionData(); - Data->Definition = this; + Data.setPointer(new (getASTContext()) DefinitionData()); + Data.getPointer()->Definition = this; // Make the type point at the definition, now that we have one. if (TypeForDecl) @@ -273,24 +389,6 @@ void ObjCInterfaceDecl::startDefinition() { } } -/// getFirstClassExtension - Find first class extension of the given class. -ObjCCategoryDecl* ObjCInterfaceDecl::getFirstClassExtension() const { - for (ObjCCategoryDecl *CDecl = getCategoryList(); CDecl; - CDecl = CDecl->getNextClassCategory()) - if (CDecl->IsClassExtension()) - return CDecl; - return 0; -} - -/// getNextClassCategory - Find next class extension in list of categories. -const ObjCCategoryDecl* ObjCCategoryDecl::getNextClassExtension() const { - for (const ObjCCategoryDecl *CDecl = getNextClassCategory(); CDecl; - CDecl = CDecl->getNextClassCategory()) - if (CDecl->IsClassExtension()) - return CDecl; - return 0; -} - ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, ObjCInterfaceDecl *&clsDeclared) { // FIXME: Should make sure no callers ever do this. @@ -306,9 +404,12 @@ ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, clsDeclared = ClassDecl; return I; } - for (const ObjCCategoryDecl *CDecl = ClassDecl->getFirstClassExtension(); - CDecl; CDecl = CDecl->getNextClassExtension()) { - if (ObjCIvarDecl *I = CDecl->getIvarDecl(ID)) { + + for (ObjCInterfaceDecl::visible_extensions_iterator + Ext = ClassDecl->visible_extensions_begin(), + ExtEnd = ClassDecl->visible_extensions_end(); + Ext != ExtEnd; ++Ext) { + if (ObjCIvarDecl *I = Ext->getIvarDecl(ID)) { clsDeclared = ClassDecl; return I; } @@ -367,21 +468,22 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, return MethodDecl; // Didn't find one yet - now look through categories. - ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList(); - while (CatDecl) { - if ((MethodDecl = CatDecl->getMethod(Sel, isInstance))) + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = ClassDecl->visible_categories_begin(), + CatEnd = ClassDecl->visible_categories_end(); + Cat != CatEnd; ++Cat) { + if ((MethodDecl = Cat->getMethod(Sel, isInstance))) return MethodDecl; if (!shallowCategoryLookup) { // Didn't find one yet - look through protocols. const ObjCList<ObjCProtocolDecl> &Protocols = - CatDecl->getReferencedProtocols(); + Cat->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) return MethodDecl; } - CatDecl = CatDecl->getNextClassCategory(); } ClassDecl = ClassDecl->getSuperClass(); @@ -753,7 +855,8 @@ static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container, if (MovedToSuper) if (ObjCMethodDecl * Overridden = Container->getMethod(Method->getSelector(), - Method->isInstanceMethod())) + Method->isInstanceMethod(), + /*AllowHidden=*/true)) if (Method != Overridden) { // We found an override at this category; there is no need to look // into its protocols. @@ -771,7 +874,8 @@ static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container, // Check whether we have a matching method at this level. if (const ObjCMethodDecl * Overridden = Container->getMethod(Method->getSelector(), - Method->isInstanceMethod())) + Method->isInstanceMethod(), + /*AllowHidden=*/true)) if (Method != Overridden) { // We found an override at this level; there is no need to look // into other protocols or categories. @@ -793,10 +897,13 @@ static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container, P != PEnd; ++P) CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper); - for (const ObjCCategoryDecl *Category = Interface->getCategoryList(); - Category; Category = Category->getNextClassCategory()) - CollectOverriddenMethodsRecurse(Category, Method, Methods, + for (ObjCInterfaceDecl::known_categories_iterator + Cat = Interface->known_categories_begin(), + CatEnd = Interface->known_categories_end(); + Cat != CatEnd; ++Cat) { + CollectOverriddenMethodsRecurse(*Cat, Method, Methods, MovedToSuper); + } if (const ObjCInterfaceDecl *Super = Interface->getSuperClass()) return CollectOverriddenMethodsRecurse(Super, Method, Methods, @@ -827,7 +934,8 @@ static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method, // Start searching for overridden methods using the method from the // interface as starting point. if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), - Method->isInstanceMethod())) + Method->isInstanceMethod(), + /*AllowHidden=*/true)) Method = IFaceMeth; CollectOverriddenMethods(ID, Method, overridden); @@ -839,7 +947,8 @@ static void collectOverriddenMethodsSlow(const ObjCMethodDecl *Method, // Start searching for overridden methods using the method from the // interface as starting point. if (const ObjCMethodDecl *IFaceMeth = ID->getMethod(Method->getSelector(), - Method->isInstanceMethod())) + Method->isInstanceMethod(), + /*AllowHidden=*/true)) Method = IFaceMeth; CollectOverriddenMethods(ID, Method, overridden); @@ -858,11 +967,14 @@ static void collectOnCategoriesAfterLocation(SourceLocation Loc, if (!Class) return; - for (const ObjCCategoryDecl *Category = Class->getCategoryList(); - Category; Category = Category->getNextClassCategory()) - if (SM.isBeforeInTranslationUnit(Loc, Category->getLocation())) - CollectOverriddenMethodsRecurse(Category, Method, Methods, true); - + for (ObjCInterfaceDecl::known_categories_iterator + Cat = Class->known_categories_begin(), + CatEnd = Class->known_categories_end(); + Cat != CatEnd; ++Cat) { + if (SM.isBeforeInTranslationUnit(Loc, Cat->getLocation())) + CollectOverriddenMethodsRecurse(*Cat, Method, Methods, true); + } + collectOnCategoriesAfterLocation(Loc, Class->getSuperClass(), SM, Method, Methods); } @@ -924,6 +1036,11 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { if (isPropertyAccessor()) { const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent()); + // If container is class extension, find its primary class. + if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(Container)) + if (CatDecl->IsClassExtension()) + Container = CatDecl->getClassInterface(); + bool IsGetter = (NumArgs == 0); for (ObjCContainerDecl::prop_iterator I = Container->prop_begin(), @@ -967,6 +1084,7 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C, bool isInternal){ ObjCInterfaceDecl *Result = new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, PrevDecl, isInternal); + Result->Data.setInt(!C.getLangOpts().Modules); C.getObjCInterfaceType(Result, PrevDecl); return Result; } @@ -974,8 +1092,11 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C, ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCInterfaceDecl)); - return new (Mem) ObjCInterfaceDecl(0, SourceLocation(), 0, SourceLocation(), - 0, false); + ObjCInterfaceDecl *Result = new (Mem) ObjCInterfaceDecl(0, SourceLocation(), + 0, SourceLocation(), + 0, false); + Result->Data.setInt(!C.getLangOpts().Modules); + return Result; } ObjCInterfaceDecl:: @@ -1026,49 +1147,96 @@ void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) { getASTContext().setObjCImplementation(getDefinition(), ImplD); } +namespace { + struct SynthesizeIvarChunk { + uint64_t Size; + ObjCIvarDecl *Ivar; + SynthesizeIvarChunk(uint64_t size, ObjCIvarDecl *ivar) + : Size(size), Ivar(ivar) {} + }; + + bool operator<(const SynthesizeIvarChunk & LHS, + const SynthesizeIvarChunk &RHS) { + return LHS.Size < RHS.Size; + } +} + /// all_declared_ivar_begin - return first ivar declared in this class, /// its extensions and its implementation. Lazily build the list on first /// access. +/// +/// Caveat: The list returned by this method reflects the current +/// state of the parser. The cache will be updated for every ivar +/// added by an extension or the implementation when they are +/// encountered. +/// See also ObjCIvarDecl::Create(). ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) return 0; - if (data().IvarList) - return data().IvarList; - ObjCIvarDecl *curIvar = 0; - if (!ivar_empty()) { - ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end(); - data().IvarList = *I; ++I; - for (curIvar = data().IvarList; I != E; curIvar = *I, ++I) - curIvar->setNextIvar(*I); - } - - for (const ObjCCategoryDecl *CDecl = getFirstClassExtension(); CDecl; - CDecl = CDecl->getNextClassExtension()) { - if (!CDecl->ivar_empty()) { - ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(), - E = CDecl->ivar_end(); - if (!data().IvarList) { - data().IvarList = *I; ++I; - curIvar = data().IvarList; - } - for ( ;I != E; curIvar = *I, ++I) + if (!data().IvarList) { + if (!ivar_empty()) { + ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end(); + data().IvarList = *I; ++I; + for (curIvar = data().IvarList; I != E; curIvar = *I, ++I) curIvar->setNextIvar(*I); } + + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = known_extensions_begin(), + ExtEnd = known_extensions_end(); + Ext != ExtEnd; ++Ext) { + if (!Ext->ivar_empty()) { + ObjCCategoryDecl::ivar_iterator + I = Ext->ivar_begin(), + E = Ext->ivar_end(); + if (!data().IvarList) { + data().IvarList = *I; ++I; + curIvar = data().IvarList; + } + for ( ;I != E; curIvar = *I, ++I) + curIvar->setNextIvar(*I); + } + } + data().IvarListMissingImplementation = true; } + + // cached and complete! + if (!data().IvarListMissingImplementation) + return data().IvarList; if (ObjCImplementationDecl *ImplDecl = getImplementation()) { + data().IvarListMissingImplementation = false; if (!ImplDecl->ivar_empty()) { - ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(), - E = ImplDecl->ivar_end(); - if (!data().IvarList) { - data().IvarList = *I; ++I; - curIvar = data().IvarList; + SmallVector<SynthesizeIvarChunk, 16> layout; + for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(), + E = ImplDecl->ivar_end(); I != E; ++I) { + ObjCIvarDecl *IV = *I; + if (IV->getSynthesize() && !IV->isInvalidDecl()) { + layout.push_back(SynthesizeIvarChunk( + IV->getASTContext().getTypeSize(IV->getType()), IV)); + continue; + } + if (!data().IvarList) + data().IvarList = *I; + else + curIvar->setNextIvar(*I); + curIvar = *I; + } + + if (!layout.empty()) { + // Order synthesized ivars by their size. + std::stable_sort(layout.begin(), layout.end()); + unsigned Ix = 0, EIx = layout.size(); + if (!data().IvarList) { + data().IvarList = layout[0].Ivar; Ix++; + curIvar = data().IvarList; + } + for ( ; Ix != EIx; curIvar = layout[Ix].Ivar, Ix++) + curIvar->setNextIvar(layout[Ix].Ivar); } - for ( ;I != E; curIvar = *I, ++I) - curIvar->setNextIvar(*I); } } return data().IvarList; @@ -1087,29 +1255,41 @@ ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const { if (data().ExternallyCompleted) LoadExternalDefinition(); - for (ObjCCategoryDecl *Category = getCategoryList(); - Category; Category = Category->getNextClassCategory()) - if (Category->getIdentifier() == CategoryId) - return Category; + for (visible_categories_iterator Cat = visible_categories_begin(), + CatEnd = visible_categories_end(); + Cat != CatEnd; + ++Cat) { + if (Cat->getIdentifier() == CategoryId) + return *Cat; + } + return 0; } ObjCMethodDecl * ObjCInterfaceDecl::getCategoryInstanceMethod(Selector Sel) const { - for (ObjCCategoryDecl *Category = getCategoryList(); - Category; Category = Category->getNextClassCategory()) - if (ObjCCategoryImplDecl *Impl = Category->getImplementation()) + for (visible_categories_iterator Cat = visible_categories_begin(), + CatEnd = visible_categories_end(); + Cat != CatEnd; + ++Cat) { + if (ObjCCategoryImplDecl *Impl = Cat->getImplementation()) if (ObjCMethodDecl *MD = Impl->getInstanceMethod(Sel)) return MD; + } + return 0; } ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const { - for (ObjCCategoryDecl *Category = getCategoryList(); - Category; Category = Category->getNextClassCategory()) - if (ObjCCategoryImplDecl *Impl = Category->getImplementation()) + for (visible_categories_iterator Cat = visible_categories_begin(), + CatEnd = visible_categories_end(); + Cat != CatEnd; + ++Cat) { + if (ObjCCategoryImplDecl *Impl = Cat->getImplementation()) if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel)) return MD; + } + return 0; } @@ -1141,10 +1321,13 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, // 2nd, look up the category. if (lookupCategory) - for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; - CDecl = CDecl->getNextClassCategory()) { - for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(), - E = CDecl->protocol_end(); PI != E; ++PI) + for (visible_categories_iterator Cat = visible_categories_begin(), + CatEnd = visible_categories_end(); + Cat != CatEnd; + ++Cat) { + for (ObjCCategoryDecl::protocol_iterator PI = Cat->protocol_begin(), + E = Cat->protocol_end(); + PI != E; ++PI) if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI)) return true; } @@ -1274,15 +1457,17 @@ ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC, ObjCProtocolDecl *PrevDecl) { ObjCProtocolDecl *Result = new (C) ObjCProtocolDecl(DC, Id, nameLoc, atStartLoc, PrevDecl); - + Result->Data.setInt(!C.getLangOpts().Modules); return Result; } ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCProtocolDecl)); - return new (Mem) ObjCProtocolDecl(0, 0, SourceLocation(), SourceLocation(), - 0); + ObjCProtocolDecl *Result = new (Mem) ObjCProtocolDecl(0, 0, SourceLocation(), + SourceLocation(), 0); + Result->Data.setInt(!C.getLangOpts().Modules); + return Result; } ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) { @@ -1304,6 +1489,12 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel, bool isInstance) const { ObjCMethodDecl *MethodDecl = NULL; + // If there is no definition or the definition is hidden, we don't find + // anything. + const ObjCProtocolDecl *Def = getDefinition(); + if (!Def || Def->isHidden()) + return NULL; + if ((MethodDecl = getMethod(Sel, isInstance))) return MethodDecl; @@ -1314,9 +1505,9 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel, } void ObjCProtocolDecl::allocateDefinitionData() { - assert(!Data && "Protocol already has a definition!"); - Data = new (getASTContext()) DefinitionData; - Data->Definition = this; + assert(!Data.getPointer() && "Protocol already has a definition!"); + Data.setPointer(new (getASTContext()) DefinitionData); + Data.getPointer()->Definition = this; } void ObjCProtocolDecl::startDefinition() { @@ -1328,17 +1519,22 @@ void ObjCProtocolDecl::startDefinition() { RD->Data = this->Data; } -void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM) const { - for (ObjCProtocolDecl::prop_iterator P = prop_begin(), - E = prop_end(); P != E; ++P) { - ObjCPropertyDecl *Prop = *P; - // Insert into PM if not there already. - PM.insert(std::make_pair(Prop->getIdentifier(), Prop)); +void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM, + PropertyDeclOrder &PO) const { + + if (const ObjCProtocolDecl *PDecl = getDefinition()) { + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = *P; + // Insert into PM if not there already. + PM.insert(std::make_pair(Prop->getIdentifier(), Prop)); + PO.push_back(Prop); + } + // Scan through protocol's protocols. + for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), + E = PDecl->protocol_end(); PI != E; ++PI) + (*PI)->collectPropertiesToImplement(PM, PO); } - // Scan through protocol's protocols. - for (ObjCProtocolDecl::protocol_iterator PI = protocol_begin(), - E = protocol_end(); PI != E; ++PI) - (*PI)->collectPropertiesToImplement(PM); } @@ -1362,9 +1558,9 @@ ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC, IvarLBraceLoc, IvarRBraceLoc); if (IDecl) { // Link this category into its class's category list. - CatDecl->NextClassCategory = IDecl->getCategoryList(); + CatDecl->NextClassCategory = IDecl->getCategoryListRaw(); if (IDecl->hasDefinition()) { - IDecl->setCategoryList(CatDecl); + IDecl->setCategoryListRaw(CatDecl); if (ASTMutationListener *L = C.getASTMutationListener()) L->AddedObjCCategoryToInterface(CatDecl, IDecl); } @@ -1450,7 +1646,7 @@ void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) { } /// FindPropertyImplIvarDecl - This method lookup the ivar in the list of -/// properties implemented in this category \@implementation block and returns +/// properties implemented in this \@implementation block and returns /// the implemented property that uses it. /// ObjCPropertyImplDecl *ObjCImplDecl:: diff --git a/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp new file mode 100644 index 0000000..c0d10a0 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp @@ -0,0 +1,60 @@ +//===--- DeclOpenMP.cpp - Declaration OpenMP AST Node Implementation ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// \brief This file implements OMPThreadPrivateDecl class. +/// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclOpenMP.h" +#include "clang/AST/Expr.h" + +using namespace clang; + +//===----------------------------------------------------------------------===// +// OMPThreadPrivateDecl Implementation. +//===----------------------------------------------------------------------===// + +void OMPThreadPrivateDecl::anchor() { } + +OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C, + DeclContext *DC, + SourceLocation L, + ArrayRef<DeclRefExpr *> VL) { + unsigned Size = sizeof(OMPThreadPrivateDecl) + + (VL.size() * sizeof(DeclRefExpr *)); + + void *Mem = C.Allocate(Size, llvm::alignOf<OMPThreadPrivateDecl>()); + OMPThreadPrivateDecl *D = new (Mem) OMPThreadPrivateDecl(OMPThreadPrivate, + DC, L); + D->NumVars = VL.size(); + D->setVars(VL); + return D; +} + +OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C, + unsigned ID, + unsigned N) { + unsigned Size = sizeof(OMPThreadPrivateDecl) + (N * sizeof(DeclRefExpr *)); + + void *Mem = AllocateDeserializedDecl(C, ID, Size); + OMPThreadPrivateDecl *D = new (Mem) OMPThreadPrivateDecl(OMPThreadPrivate, + 0, SourceLocation()); + D->NumVars = N; + return D; +} + +void OMPThreadPrivateDecl::setVars(ArrayRef<DeclRefExpr *> VL) { + assert(VL.size() == NumVars && + "Number of variables is not the same as the preallocated buffer"); + DeclRefExpr **Vars = reinterpret_cast<DeclRefExpr **>(this + 1); + std::copy(VL.begin(), VL.end(), Vars); +} diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index 386ad66..c3bf8f8 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -7,15 +7,16 @@ // //===----------------------------------------------------------------------===// // -// This file implements the Decl::dump method, which pretty print the +// This file implements the Decl::print method, which pretty prints the // AST back out to C/Objective-C/C++/Objective-C++ code. // //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" -#include "clang/AST/DeclVisitor.h" +#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/PrettyPrinter.h" @@ -50,7 +51,9 @@ namespace { void VisitEnumDecl(EnumDecl *D); void VisitRecordDecl(RecordDecl *D); void VisitEnumConstantDecl(EnumConstantDecl *D); + void VisitEmptyDecl(EmptyDecl *D); void VisitFunctionDecl(FunctionDecl *D); + void VisitFriendDecl(FriendDecl *D); void VisitFieldDecl(FieldDecl *D); void VisitVarDecl(VarDecl *D); void VisitLabelDecl(LabelDecl *D); @@ -79,9 +82,10 @@ namespace { void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); void VisitUsingDecl(UsingDecl *D); void VisitUsingShadowDecl(UsingShadowDecl *D); + void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); void PrintTemplateParameters(const TemplateParameterList *Params, - const TemplateArgumentList *Args); + const TemplateArgumentList *Args = 0); void prettyPrintAttributes(Decl *D); }; } @@ -174,16 +178,6 @@ void DeclContext::dumpDeclContext() const { Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false); } -void Decl::dump() const { - dump(llvm::errs()); -} - -void Decl::dump(raw_ostream &Out) const { - PrintingPolicy Policy = getASTContext().getPrintingPolicy(); - Policy.DumpSourceManager = &getASTContext().getSourceManager(); - print(Out, Policy, /*Indentation*/ 0, /*PrintInstantiation*/ true); -} - raw_ostream& DeclPrinter::Indent(unsigned Indentation) { for (unsigned i = 0; i != Indentation; ++i) Out << " "; @@ -191,7 +185,7 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) { } void DeclPrinter::prettyPrintAttributes(Decl *D) { - if (Policy.SuppressAttributes) + if (Policy.PolishForDeclaration) return; if (D->hasAttrs()) { @@ -240,18 +234,18 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { if (isa<ObjCIvarDecl>(*D)) continue; - if (!Policy.DumpSourceManager) { - // Skip over implicit declarations in pretty-printing mode. - if (D->isImplicit()) continue; - // FIXME: Ugly hack so we don't pretty-print the builtin declaration - // of __builtin_va_list or __[u]int128_t. There should be some other way - // to check that. - if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) { - if (IdentifierInfo *II = ND->getIdentifier()) { - if (II->isStr("__builtin_va_list") || - II->isStr("__int128_t") || II->isStr("__uint128_t")) - continue; - } + // Skip over implicit declarations in pretty-printing mode. + if (D->isImplicit()) + continue; + + // FIXME: Ugly hack so we don't pretty-print the builtin declaration + // of __builtin_va_list or __[u]int128_t. There should be some other way + // to check that. + if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) { + if (IdentifierInfo *II = ND->getIdentifier()) { + if (II->isStr("__builtin_va_list") || + II->isStr("__int128_t") || II->isStr("__uint128_t")) + continue; } } @@ -298,8 +292,10 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { // FIXME: Need to be able to tell the DeclPrinter when const char *Terminator = 0; - if (isa<FunctionDecl>(*D) && - cast<FunctionDecl>(*D)->isThisDeclarationADefinition()) + if (isa<OMPThreadPrivateDecl>(*D)) + Terminator = 0; + else if (isa<FunctionDecl>(*D) && + cast<FunctionDecl>(*D)->isThisDeclarationADefinition()) Terminator = 0; else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody()) Terminator = 0; @@ -395,8 +391,9 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { } void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { + CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D); if (!Policy.SuppressSpecifiers) { - switch (D->getStorageClassAsWritten()) { + switch (D->getStorageClass()) { case SC_None: break; case SC_Extern: Out << "extern "; break; case SC_Static: Out << "static "; break; @@ -408,6 +405,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (D->isInlineSpecified()) Out << "inline "; if (D->isVirtualAsWritten()) Out << "virtual "; if (D->isModulePrivate()) Out << "__module_private__ "; + if (CDecl && CDecl->isExplicitSpecified()) + Out << "explicit "; } PrintingPolicy SubPolicy(Policy); @@ -483,7 +482,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } } - if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) { + if (CDecl) { bool HasInitializerList = false; for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(), E = CDecl->init_end(); @@ -545,9 +544,15 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } Out << ")"; } - } - else + if (!Proto.empty()) + Out << Proto; + } else { + if (FT && FT->hasTrailingReturn()) { + Out << "auto " << Proto << " -> "; + Proto.clear(); + } AFT->getResultType().print(Out, Policy, Proto); + } } else { Ty.print(Out, Policy, Proto); } @@ -558,6 +563,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Out << " = 0"; else if (D->isDeletedAsWritten()) Out << " = delete"; + else if (D->isExplicitlyDefaulted()) + Out << " = default"; else if (D->doesThisDeclarationHaveABody() && !Policy.TerseOutput) { if (!D->hasPrototype() && D->getNumParams()) { // This is a K&R function definition, so we need to print the @@ -579,6 +586,31 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } } +void DeclPrinter::VisitFriendDecl(FriendDecl *D) { + if (TypeSourceInfo *TSI = D->getFriendType()) { + unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists(); + for (unsigned i = 0; i < NumTPLists; ++i) + PrintTemplateParameters(D->getFriendTypeTemplateParameterList(i)); + Out << "friend "; + Out << " " << TSI->getType().getAsString(Policy); + } + else if (FunctionDecl *FD = + dyn_cast<FunctionDecl>(D->getFriendDecl())) { + Out << "friend "; + VisitFunctionDecl(FD); + } + else if (FunctionTemplateDecl *FTD = + dyn_cast<FunctionTemplateDecl>(D->getFriendDecl())) { + Out << "friend "; + VisitFunctionTemplateDecl(FTD); + } + else if (ClassTemplateDecl *CTD = + dyn_cast<ClassTemplateDecl>(D->getFriendDecl())) { + Out << "friend "; + VisitRedeclarableTemplateDecl(CTD); + } +} + void DeclPrinter::VisitFieldDecl(FieldDecl *D) { if (!Policy.SuppressSpecifiers && D->isMutable()) Out << "mutable "; @@ -609,9 +641,9 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) { void DeclPrinter::VisitVarDecl(VarDecl *D) { - StorageClass SCAsWritten = D->getStorageClassAsWritten(); - if (!Policy.SuppressSpecifiers && SCAsWritten != SC_None) - Out << VarDecl::getStorageClassSpecifierString(SCAsWritten) << " "; + StorageClass SC = D->getStorageClass(); + if (!Policy.SuppressSpecifiers && SC != SC_None) + Out << VarDecl::getStorageClassSpecifierString(SC) << " "; if (!Policy.SuppressSpecifiers && D->isThreadSpecified()) Out << "__thread "; @@ -625,9 +657,14 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { Expr *Init = D->getInit(); if (!Policy.SuppressInitializers && Init) { bool ImplicitInit = false; - if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) - ImplicitInit = D->getInitStyle() == VarDecl::CallInit && - Construct->getNumArgs() == 0 && !Construct->isListInitialization(); + if (CXXConstructExpr *Construct = + dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) { + if (D->getInitStyle() == VarDecl::CallInit && + !Construct->isListInitialization()) { + ImplicitInit = Construct->getNumArgs() == 0 || + Construct->getArg(0)->isDefaultArgument(); + } + } if (!ImplicitInit) { if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init)) Out << "("; @@ -653,7 +690,7 @@ void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { } void DeclPrinter::VisitImportDecl(ImportDecl *D) { - Out << "@__experimental_modules_import " << D->getImportedModule()->getFullModuleName() + Out << "@import " << D->getImportedModule()->getFullModuleName() << ";\n"; } @@ -690,6 +727,10 @@ void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { Out << *D->getAliasedNamespace(); } +void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) { + prettyPrintAttributes(D); +} + void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { if (!Policy.SuppressSpecifiers && D->isModulePrivate()) Out << "__module_private__ "; @@ -746,8 +787,8 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { Visit(*D->decls_begin()); } -void DeclPrinter::PrintTemplateParameters( - const TemplateParameterList *Params, const TemplateArgumentList *Args = 0) { +void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, + const TemplateArgumentList *Args) { assert(Params); assert(!Args || Params->size() == Args->size()); @@ -882,6 +923,8 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { OMD->getBody()->printPretty(Out, 0, Policy); Out << '\n'; } + else if (Policy.PolishForDeclaration) + Out << ';'; } void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { @@ -892,7 +935,17 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { Out << "@implementation " << I << " : " << *SID; else Out << "@implementation " << I; - Out << "\n"; + + if (OID->ivar_size() > 0) { + Out << "{\n"; + Indentation += Policy.Indentation; + for (ObjCImplementationDecl::ivar_iterator I = OID->ivar_begin(), + E = OID->ivar_end(); I != E; ++I) { + Indent() << I->getType().getAsString(Policy) << ' ' << **I << ";\n"; + } + Indentation -= Policy.Indentation; + Out << "}\n"; + } VisitDeclContext(OID, false); Out << "@end"; } @@ -905,7 +958,7 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { Out << "@class " << I << ";"; return; } - + bool eolnOut = false; if (SID) Out << "@interface " << I << " : " << *SID; else @@ -917,13 +970,12 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) Out << (I == Protocols.begin() ? '<' : ',') << **I; - } - - if (!Protocols.empty()) Out << "> "; + } if (OID->ivar_size() > 0) { Out << "{\n"; + eolnOut = true; Indentation += Policy.Indentation; for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(), E = OID->ivar_end(); I != E; ++I) { @@ -932,19 +984,33 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { Indentation -= Policy.Indentation; Out << "}\n"; } + else if (SID) { + Out << "\n"; + eolnOut = true; + } VisitDeclContext(OID, false); + if (!eolnOut) + Out << ' '; Out << "@end"; // FIXME: implement the rest... } void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) { if (!PID->isThisDeclarationADefinition()) { - Out << "@protocol " << PID->getIdentifier() << ";\n"; + Out << "@protocol " << *PID << ";\n"; return; } - - Out << "@protocol " << *PID << '\n'; + // Protocols? + const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols(); + if (!Protocols.empty()) { + Out << "@protocol " << *PID; + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); I != E; ++I) + Out << (I == Protocols.begin() ? '<' : ',') << **I; + Out << ">\n"; + } else + Out << "@protocol " << *PID << '\n'; VisitDeclContext(PID, false); Out << "@end"; } @@ -959,6 +1025,17 @@ void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { Out << "@interface " << *PID->getClassInterface() << '(' << *PID << ")\n"; + if (PID->ivar_size() > 0) { + Out << "{\n"; + Indentation += Policy.Indentation; + for (ObjCCategoryDecl::ivar_iterator I = PID->ivar_begin(), + E = PID->ivar_end(); I != E; ++I) { + Indent() << I->getType().getAsString(Policy) << ' ' << **I << ";\n"; + } + Indentation -= Policy.Indentation; + Out << "}\n"; + } + VisitDeclContext(PID, false); Out << "@end"; @@ -1040,6 +1117,8 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { Out << " )"; } Out << ' ' << PDecl->getType().getAsString(Policy) << ' ' << *PDecl; + if (Policy.PolishForDeclaration) + Out << ';'; } void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { @@ -1068,9 +1147,23 @@ DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { Out << "using "; D->getQualifier()->print(Out, Policy); - Out << D->getDeclName(); + Out << D->getName(); } void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) { // ignore } + +void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { + Out << "#pragma omp threadprivate"; + if (!D->varlist_empty()) { + for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(), + E = D->varlist_end(); + I != E; ++I) { + Out << (I == D->varlist_begin() ? '(' : ',') + << *cast<NamedDecl>((*I)->getDecl()); + } + Out << ")"; + } +} + diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp index a70983f..0b94f7d 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp @@ -11,13 +11,13 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/ASTContext.h" #include "clang/AST/TypeLoc.h" -#include "clang/AST/ASTMutationListener.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/STLExtras.h" #include <memory> @@ -128,12 +128,12 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params, // RedeclarableTemplateDecl Implementation //===----------------------------------------------------------------------===// -RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() { +RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const { if (!Common) { // Walk the previous-declaration chain until we either find a declaration // with a common pointer or we run out of previous declarations. - llvm::SmallVector<RedeclarableTemplateDecl *, 2> PrevDecls; - for (RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev; + SmallVector<const RedeclarableTemplateDecl *, 2> PrevDecls; + for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev; Prev = Prev->getPreviousDecl()) { if (Prev->Common) { Common = Prev->Common; @@ -184,9 +184,8 @@ static void GenerateInjectedTemplateArgs(ASTContext &Context, if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) { QualType ArgType = Context.getTypeDeclType(TTP); if (TTP->isParameterPack()) - ArgType = Context.getPackExpansionType(ArgType, - llvm::Optional<unsigned>()); - + ArgType = Context.getPackExpansionType(ArgType, None); + Arg = TemplateArgument(ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { @@ -197,13 +196,12 @@ static void GenerateInjectedTemplateArgs(ASTContext &Context, if (NTTP->isParameterPack()) E = new (Context) PackExpansionExpr(Context.DependentTy, E, - NTTP->getLocation(), - llvm::Optional<unsigned>()); + NTTP->getLocation(), None); Arg = TemplateArgument(E); } else { TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param); if (TTP->isParameterPack()) - Arg = TemplateArgument(TemplateName(TTP), llvm::Optional<unsigned>()); + Arg = TemplateArgument(TemplateName(TTP), Optional<unsigned>()); else Arg = TemplateArgument(TemplateName(TTP)); } @@ -241,7 +239,7 @@ FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C, } RedeclarableTemplateDecl::CommonBase * -FunctionTemplateDecl::newCommon(ASTContext &C) { +FunctionTemplateDecl::newCommon(ASTContext &C) const { Common *CommonPtr = new (C) Common; C.AddDeallocation(DeallocateCommon, CommonPtr); return CommonPtr; @@ -304,7 +302,7 @@ ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C, return new (Mem) ClassTemplateDecl(EmptyShell()); } -void ClassTemplateDecl::LoadLazySpecializations() { +void ClassTemplateDecl::LoadLazySpecializations() const { Common *CommonPtr = getCommonPtr(); if (CommonPtr->LazySpecializations) { ASTContext &Context = getASTContext(); @@ -316,7 +314,7 @@ void ClassTemplateDecl::LoadLazySpecializations() { } llvm::FoldingSetVector<ClassTemplateSpecializationDecl> & -ClassTemplateDecl::getSpecializations() { +ClassTemplateDecl::getSpecializations() const { LoadLazySpecializations(); return getCommonPtr()->Specializations; } @@ -328,7 +326,7 @@ ClassTemplateDecl::getPartialSpecializations() { } RedeclarableTemplateDecl::CommonBase * -ClassTemplateDecl::newCommon(ASTContext &C) { +ClassTemplateDecl::newCommon(ASTContext &C) const { Common *CommonPtr = new (C) Common; C.AddDeallocation(DeallocateCommon, CommonPtr); return CommonPtr; @@ -620,7 +618,7 @@ TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, TemplateParameterList *Params, - llvm::ArrayRef<TemplateParameterList*> Expansions) { + ArrayRef<TemplateParameterList *> Expansions) { void *Mem = C.Allocate(sizeof(TemplateTemplateParmDecl) + sizeof(TemplateParameterList*) * Expansions.size()); return new (Mem) TemplateTemplateParmDecl(DC, L, D, P, Id, Params, @@ -728,6 +726,8 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, SpecializedTemplate, Args, NumArgs, PrevDecl); + Result->MayHaveOutOfDateDef = false; + Context.getTypeDeclType(Result, PrevDecl); return Result; } @@ -737,20 +737,19 @@ ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ClassTemplateSpecializationDecl)); - return new (Mem) ClassTemplateSpecializationDecl(ClassTemplateSpecialization); + ClassTemplateSpecializationDecl *Result = + new (Mem) ClassTemplateSpecializationDecl(ClassTemplateSpecialization); + Result->MayHaveOutOfDateDef = false; + return Result; } -void -ClassTemplateSpecializationDecl::getNameForDiagnostic(std::string &S, - const PrintingPolicy &Policy, - bool Qualified) const { - NamedDecl::getNameForDiagnostic(S, Policy, Qualified); +void ClassTemplateSpecializationDecl::getNameForDiagnostic( + raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const { + NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); const TemplateArgumentList &TemplateArgs = getTemplateArgs(); - S += TemplateSpecializationType::PrintTemplateArgumentList( - TemplateArgs.data(), - TemplateArgs.size(), - Policy); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, TemplateArgs.data(), TemplateArgs.size(), Policy); } ClassTemplateDecl * @@ -857,6 +856,7 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, PrevDecl, SequenceNumber); Result->setSpecializationKind(TSK_ExplicitSpecialization); + Result->MayHaveOutOfDateDef = false; Context.getInjectedClassNameType(Result, CanonInjectedType); return Result; @@ -867,7 +867,10 @@ ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ClassTemplatePartialSpecializationDecl)); - return new (Mem) ClassTemplatePartialSpecializationDecl(); + ClassTemplatePartialSpecializationDecl *Result + = new (Mem) ClassTemplatePartialSpecializationDecl(); + Result->MayHaveOutOfDateDef = false; + return Result; } //===----------------------------------------------------------------------===// @@ -919,7 +922,7 @@ void TypeAliasTemplateDecl::DeallocateCommon(void *Ptr) { static_cast<Common *>(Ptr)->~Common(); } RedeclarableTemplateDecl::CommonBase * -TypeAliasTemplateDecl::newCommon(ASTContext &C) { +TypeAliasTemplateDecl::newCommon(ASTContext &C) const { Common *CommonPtr = new (C) Common; C.AddDeallocation(DeallocateCommon, CommonPtr); return CommonPtr; diff --git a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp index 28188d9..e4a41b6 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp @@ -364,6 +364,21 @@ DeclarationNameTable::~DeclarationNameTable() { delete LiteralNames; } +DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) { + return getCXXSpecialName(DeclarationName::CXXConstructorName, + Ty.getUnqualifiedType()); +} + +DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) { + return getCXXSpecialName(DeclarationName::CXXDestructorName, + Ty.getUnqualifiedType()); +} + +DeclarationName +DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) { + return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty); +} + DeclarationName DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, CanQualType Ty) { diff --git a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp index 5f43fbc..be22ae4 100644 --- a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp @@ -17,6 +17,7 @@ // Only pay for this in code size in assertions-enabled builds. #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" @@ -37,8 +38,6 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeLocVisitor.h" #include "clang/AST/TypeVisitor.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" #include "llvm/ADT/SmallString.h" using namespace clang; @@ -500,8 +499,8 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) dispatch(*I); - for (llvm::ArrayRef<NamedDecl*>::iterator - I = D->getDeclsInPrototypeScope().begin(), E = D->getDeclsInPrototypeScope().end(); + for (ArrayRef<NamedDecl *>::iterator I = D->getDeclsInPrototypeScope().begin(), + E = D->getDeclsInPrototypeScope().end(); I != E; ++I) dispatch(*I); if (D->doesThisDeclarationHaveABody()) @@ -749,14 +748,6 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, visitDeclContext(D); } - // ObjCInterfaceDecl - void visitCategoryList(ObjCCategoryDecl *D) { - if (!D) return; - - TemporaryContainer C(*this, "categories"); - for (; D; D = D->getNextClassCategory()) - visitDeclRef(D); - } void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) { setPointer("typeptr", D->getTypeForDecl()); setFlag("forward_decl", !D->isThisDeclarationADefinition()); @@ -771,7 +762,17 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) visitDeclRef(*I); } - visitCategoryList(D->getCategoryList()); + + if (!D->visible_categories_empty()) { + TemporaryContainer C(*this, "categories"); + + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = D->visible_categories_begin(), + CatEnd = D->visible_categories_end(); + Cat != CatEnd; ++Cat) { + visitDeclRef(*Cat); + } + } } void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) { visitDeclContext(D); @@ -923,6 +924,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, case CC_AAPCS: return set("cc", "aapcs"); case CC_AAPCS_VFP: return set("cc", "aapcs_vfp"); case CC_PnaclCall: return set("cc", "pnaclcall"); + case CC_IntelOclBicc: return set("cc", "intel_ocl_bicc"); } } diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index f3a2e05..b97f4d1 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -11,22 +11,24 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/DeclObjC.h" +#include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/EvaluatedExprVisitor.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" -#include "clang/Lex/LiteralSupport.h" -#include "clang/Lex/Lexer.h" -#include "clang/Sema/SemaDiagnostic.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/LiteralSupport.h" +#include "clang/Sema/SemaDiagnostic.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -277,7 +279,7 @@ static void computeDeclRefDependence(ASTContext &Ctx, NamedDecl *D, QualType T, // - an entity with reference type and is initialized with an // expression that is value-dependent [C++11] if (VarDecl *Var = dyn_cast<VarDecl>(D)) { - if ((Ctx.getLangOpts().CPlusPlus0x ? + if ((Ctx.getLangOpts().CPlusPlus11 ? Var->getType()->isLiteralType() : Var->getType()->isIntegralOrEnumerationType()) && (Var->getType().isConstQualified() || @@ -444,14 +446,6 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, return new (Mem) DeclRefExpr(EmptyShell()); } -SourceRange DeclRefExpr::getSourceRange() const { - SourceRange R = getNameInfo().getSourceRange(); - if (hasQualifier()) - R.setBegin(getQualifierLoc().getBeginLoc()); - if (hasExplicitTemplateArgs()) - R.setEnd(getRAngleLoc()); - return R; -} SourceLocation DeclRefExpr::getLocStart() const { if (hasQualifier()) return getQualifierLoc().getBeginLoc(); @@ -483,8 +477,9 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { } PrintingPolicy Policy(Context.getLangOpts()); - std::string Proto = FD->getQualifiedNameAsString(Policy); + std::string Proto; llvm::raw_string_ostream POut(Proto); + FD->printQualifiedName(POut, Policy); const FunctionDecl *Decl = FD; if (const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern()) @@ -509,7 +504,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { POut << ")"; if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { - const FunctionType *FT = cast<FunctionType>(MD->getType().getTypePtr()); + const FunctionType *FT = MD->getType()->castAs<FunctionType>(); if (FT->isConst()) POut << " const"; if (FT->isVolatile()) @@ -653,16 +648,14 @@ FloatingLiteral::FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L) : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false, false, false), Loc(L) { - FloatingLiteralBits.IsIEEE = - &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad; + setSemantics(V.getSemantics()); FloatingLiteralBits.IsExact = isexact; setValue(C, V); } FloatingLiteral::FloatingLiteral(ASTContext &C, EmptyShell Empty) : Expr(FloatingLiteralClass, Empty) { - FloatingLiteralBits.IsIEEE = - &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad; + setRawSemantics(IEEEhalf); FloatingLiteralBits.IsExact = false; } @@ -677,6 +670,41 @@ FloatingLiteral::Create(ASTContext &C, EmptyShell Empty) { return new (C) FloatingLiteral(C, Empty); } +const llvm::fltSemantics &FloatingLiteral::getSemantics() const { + switch(FloatingLiteralBits.Semantics) { + case IEEEhalf: + return llvm::APFloat::IEEEhalf; + case IEEEsingle: + return llvm::APFloat::IEEEsingle; + case IEEEdouble: + return llvm::APFloat::IEEEdouble; + case x87DoubleExtended: + return llvm::APFloat::x87DoubleExtended; + case IEEEquad: + return llvm::APFloat::IEEEquad; + case PPCDoubleDouble: + return llvm::APFloat::PPCDoubleDouble; + } + llvm_unreachable("Unrecognised floating semantics"); +} + +void FloatingLiteral::setSemantics(const llvm::fltSemantics &Sem) { + if (&Sem == &llvm::APFloat::IEEEhalf) + FloatingLiteralBits.Semantics = IEEEhalf; + else if (&Sem == &llvm::APFloat::IEEEsingle) + FloatingLiteralBits.Semantics = IEEEsingle; + else if (&Sem == &llvm::APFloat::IEEEdouble) + FloatingLiteralBits.Semantics = IEEEdouble; + else if (&Sem == &llvm::APFloat::x87DoubleExtended) + FloatingLiteralBits.Semantics = x87DoubleExtended; + else if (&Sem == &llvm::APFloat::IEEEquad) + FloatingLiteralBits.Semantics = IEEEquad; + else if (&Sem == &llvm::APFloat::PPCDoubleDouble) + FloatingLiteralBits.Semantics = PPCDoubleDouble; + else + llvm_unreachable("Unknown floating semantics"); +} + /// getValueAsApproximateDouble - This returns the value as an inaccurate /// double. Note that this may cause loss of precision, but is useful for /// debugging dumps, etc. @@ -745,7 +773,7 @@ StringLiteral *StringLiteral::CreateEmpty(ASTContext &C, unsigned NumStrs) { return SL; } -void StringLiteral::outputString(raw_ostream &OS) { +void StringLiteral::outputString(raw_ostream &OS) const { switch (getKind()) { case Ascii: break; // no prefix. case Wide: OS << 'L'; break; @@ -818,7 +846,7 @@ void StringLiteral::outputString(raw_ostream &OS) { assert(Char <= 0xff && "Characters above 0xff should already have been handled."); - if (isprint(Char)) + if (isPrintable(Char)) OS << (char)Char; else // Output anything hard as an octal escape. OS << '\\' @@ -1144,6 +1172,12 @@ unsigned CallExpr::isBuiltinCall() const { return FDecl->getBuiltinID(); } +bool CallExpr::isUnevaluatedBuiltinCall(ASTContext &Ctx) const { + if (unsigned BI = isBuiltinCall()) + return Ctx.BuiltinInfo.isUnevaluated(BI); + return false; +} + QualType CallExpr::getCallReturnType() const { QualType CalleeType = getCallee()->getType(); if (const PointerType *FnTypePtr = CalleeType->getAs<PointerType>()) @@ -1158,21 +1192,9 @@ QualType CallExpr::getCallReturnType() const { return FnType->getResultType(); } -SourceRange CallExpr::getSourceRange() const { - if (isa<CXXOperatorCallExpr>(this)) - return cast<CXXOperatorCallExpr>(this)->getSourceRange(); - - SourceLocation begin = getCallee()->getLocStart(); - if (begin.isInvalid() && getNumArgs() > 0) - begin = getArg(0)->getLocStart(); - SourceLocation end = getRParenLoc(); - if (end.isInvalid() && getNumArgs() > 0) - end = getArg(getNumArgs() - 1)->getLocEnd(); - return SourceRange(begin, end); -} SourceLocation CallExpr::getLocStart() const { if (isa<CXXOperatorCallExpr>(this)) - return cast<CXXOperatorCallExpr>(this)->getSourceRange().getBegin(); + return cast<CXXOperatorCallExpr>(this)->getLocStart(); SourceLocation begin = getCallee()->getLocStart(); if (begin.isInvalid() && getNumArgs() > 0) @@ -1181,7 +1203,7 @@ SourceLocation CallExpr::getLocStart() const { } SourceLocation CallExpr::getLocEnd() const { if (isa<CXXOperatorCallExpr>(this)) - return cast<CXXOperatorCallExpr>(this)->getSourceRange().getEnd(); + return cast<CXXOperatorCallExpr>(this)->getLocEnd(); SourceLocation end = getRParenLoc(); if (end.isInvalid() && getNumArgs() > 0) @@ -1309,9 +1331,6 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, return E; } -SourceRange MemberExpr::getSourceRange() const { - return SourceRange(getLocStart(), getLocEnd()); -} SourceLocation MemberExpr::getLocStart() const { if (isImplicitAccess()) { if (hasQualifier()) @@ -1416,6 +1435,7 @@ void CastExpr::CheckCastConsistency() const { case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: + case CK_ZeroToOCLEvent: assert(!getType()->isBooleanType() && "unheralded conversion to bool"); goto CheckNoBasePath; @@ -1547,6 +1567,8 @@ const char *CastExpr::getCastKindName() const { return "CopyAndAutoreleaseBlockObject"; case CK_BuiltinFnToFnPtr: return "BuiltinFnToFnPtr"; + case CK_ZeroToOCLEvent: + return "ZeroToOCLEvent"; } llvm_unreachable("Unhandled cast kind!"); @@ -1807,10 +1829,10 @@ bool InitListExpr::isStringLiteralInit() const { return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init); } -SourceRange InitListExpr::getSourceRange() const { +SourceLocation InitListExpr::getLocStart() const { if (InitListExpr *SyntacticForm = getSyntacticForm()) - return SyntacticForm->getSourceRange(); - SourceLocation Beg = LBraceLoc, End = RBraceLoc; + return SyntacticForm->getLocStart(); + SourceLocation Beg = LBraceLoc; if (Beg.isInvalid()) { // Find the first non-null initializer. for (InitExprsTy::const_iterator I = InitExprs.begin(), @@ -1822,18 +1844,25 @@ SourceRange InitListExpr::getSourceRange() const { } } } + return Beg; +} + +SourceLocation InitListExpr::getLocEnd() const { + if (InitListExpr *SyntacticForm = getSyntacticForm()) + return SyntacticForm->getLocEnd(); + SourceLocation End = RBraceLoc; if (End.isInvalid()) { // Find the first non-null initializer from the end. for (InitExprsTy::const_reverse_iterator I = InitExprs.rbegin(), - E = InitExprs.rend(); - I != E; ++I) { + E = InitExprs.rend(); + I != E; ++I) { if (Stmt *S = *I) { - End = S->getSourceRange().getEnd(); + End = S->getLocEnd(); break; - } + } } } - return SourceRange(Beg, End); + return End; } /// getFunctionType - Return the underlying function type for this block. @@ -2115,10 +2144,6 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, return false; } - // Ignore casts within macro expansions. - if (getExprLoc().isMacroID()) - return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); - // If this is a cast to a constructor conversion, check the operand. // Otherwise, the result of the cast is unused. if (CE->getCastKind() == CK_ConstructorConversion) @@ -2581,7 +2606,7 @@ bool Expr::isImplicitCXXThis() const { /// hasAnyTypeDependentArguments - Determines if any of the expressions /// in Exprs is type-dependent. -bool Expr::hasAnyTypeDependentArguments(llvm::ArrayRef<Expr *> Exprs) { +bool Expr::hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs) { for (unsigned I = 0; I < Exprs.size(); ++I) if (Exprs[I]->isTypeDependent()) return true; @@ -3025,9 +3050,9 @@ Expr::isNullPointerConstant(ASTContext &Ctx, return Source->isNullPointerConstant(Ctx, NPC); } - // C++0x nullptr_t is always a null pointer constant. + // C++11 nullptr_t is always a null pointer constant. if (getType()->isNullPtrType()) - return NPCK_CXX0X_nullptr; + return NPCK_CXX11_nullptr; if (const RecordType *UT = getType()->getAsUnionType()) if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) @@ -3045,7 +3070,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx, // test for the value 0. Don't use the C++11 constant expression semantics // for this, for now; once the dust settles on core issue 903, we might only // allow a literal 0 here in C++11 mode. - if (Ctx.getLangOpts().CPlusPlus0x) { + if (Ctx.getLangOpts().CPlusPlus11) { if (!isCXX98IntegralConstantExpr(Ctx)) return NPCK_NotNull; } else { @@ -3683,11 +3708,11 @@ SourceRange DesignatedInitExpr::getDesignatorsSourceRange() const { DesignatedInitExpr *DIE = const_cast<DesignatedInitExpr*>(this); if (size() == 1) return DIE->getDesignator(0)->getSourceRange(); - return SourceRange(DIE->getDesignator(0)->getStartLocation(), - DIE->getDesignator(size()-1)->getEndLocation()); + return SourceRange(DIE->getDesignator(0)->getLocStart(), + DIE->getDesignator(size()-1)->getLocEnd()); } -SourceRange DesignatedInitExpr::getSourceRange() const { +SourceLocation DesignatedInitExpr::getLocStart() const { SourceLocation StartLoc; Designator &First = *const_cast<DesignatedInitExpr*>(this)->designators_begin(); @@ -3699,30 +3724,37 @@ SourceRange DesignatedInitExpr::getSourceRange() const { } else StartLoc = SourceLocation::getFromRawEncoding(First.ArrayOrRange.LBracketLoc); - return SourceRange(StartLoc, getInit()->getSourceRange().getEnd()); + return StartLoc; +} + +SourceLocation DesignatedInitExpr::getLocEnd() const { + return getInit()->getLocEnd(); } -Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) { +Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) const { assert(D.Kind == Designator::ArrayDesignator && "Requires array designator"); - char* Ptr = static_cast<char*>(static_cast<void *>(this)); + char *Ptr = static_cast<char *>( + const_cast<void *>(static_cast<const void *>(this))); Ptr += sizeof(DesignatedInitExpr); Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr)); return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1)); } -Expr *DesignatedInitExpr::getArrayRangeStart(const Designator& D) { +Expr *DesignatedInitExpr::getArrayRangeStart(const Designator &D) const { assert(D.Kind == Designator::ArrayRangeDesignator && "Requires array range designator"); - char* Ptr = static_cast<char*>(static_cast<void *>(this)); + char *Ptr = static_cast<char *>( + const_cast<void *>(static_cast<const void *>(this))); Ptr += sizeof(DesignatedInitExpr); Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr)); return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1)); } -Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator& D) { +Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator &D) const { assert(D.Kind == Designator::ArrayRangeDesignator && "Requires array range designator"); - char* Ptr = static_cast<char*>(static_cast<void *>(this)); + char *Ptr = static_cast<char *>( + const_cast<void *>(static_cast<const void *>(this))); Ptr += sizeof(DesignatedInitExpr); Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr)); return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 2)); @@ -3895,7 +3927,7 @@ Stmt::child_range ObjCMessageExpr::children() { reinterpret_cast<Stmt **>(getArgs() + getNumArgs())); } -ObjCArrayLiteral::ObjCArrayLiteral(llvm::ArrayRef<Expr *> Elements, +ObjCArrayLiteral::ObjCArrayLiteral(ArrayRef<Expr *> Elements, QualType T, ObjCMethodDecl *Method, SourceRange SR) : Expr(ObjCArrayLiteralClass, T, VK_RValue, OK_Ordinary, @@ -3916,7 +3948,7 @@ ObjCArrayLiteral::ObjCArrayLiteral(llvm::ArrayRef<Expr *> Elements, } ObjCArrayLiteral *ObjCArrayLiteral::Create(ASTContext &C, - llvm::ArrayRef<Expr *> Elements, + ArrayRef<Expr *> Elements, QualType T, ObjCMethodDecl * Method, SourceRange SR) { void *Mem = C.Allocate(sizeof(ObjCArrayLiteral) diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp index 55722a2..12a47fc 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -11,12 +11,13 @@ // //===----------------------------------------------------------------------===// -#include "clang/Basic/IdentifierTable.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/TypeLoc.h" +#include "clang/Basic/IdentifierTable.h" using namespace clang; @@ -72,11 +73,8 @@ UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT) { } // CXXScalarValueInitExpr -SourceRange CXXScalarValueInitExpr::getSourceRange() const { - SourceLocation Start = RParenLoc; - if (TypeInfo) - Start = TypeInfo->getTypeLoc().getBeginLoc(); - return SourceRange(Start, RParenLoc); +SourceLocation CXXScalarValueInitExpr::getLocStart() const { + return TypeInfo ? TypeInfo->getTypeLoc().getBeginLoc() : RParenLoc; } // CXXNewExpr @@ -180,7 +178,8 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context, SourceLocation ColonColonLoc, SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType) : Expr(CXXPseudoDestructorExprClass, - Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0, + Context.getPointerType(Context.getFunctionType(Context.VoidTy, + ArrayRef<QualType>(), FunctionProtoType::ExtProtoInfo())), VK_RValue, OK_Ordinary, /*isTypeDependent=*/(Base->isTypeDependent() || @@ -217,11 +216,11 @@ QualType CXXPseudoDestructorExpr::getDestroyedType() const { return QualType(); } -SourceRange CXXPseudoDestructorExpr::getSourceRange() const { +SourceLocation CXXPseudoDestructorExpr::getLocEnd() const { SourceLocation End = DestroyedType.getLocation(); if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo()) End = TInfo->getTypeLoc().getLocalSourceRange().getEnd(); - return SourceRange(Base->getLocStart(), End); + return End; } // UnresolvedLookupExpr @@ -419,12 +418,18 @@ DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C, return E; } -SourceRange CXXConstructExpr::getSourceRange() const { +SourceLocation CXXConstructExpr::getLocStart() const { if (isa<CXXTemporaryObjectExpr>(this)) - return cast<CXXTemporaryObjectExpr>(this)->getSourceRange(); + return cast<CXXTemporaryObjectExpr>(this)->getLocStart(); + return Loc; +} + +SourceLocation CXXConstructExpr::getLocEnd() const { + if (isa<CXXTemporaryObjectExpr>(this)) + return cast<CXXTemporaryObjectExpr>(this)->getLocEnd(); if (ParenRange.isValid()) - return SourceRange(Loc, ParenRange.getEnd()); + return ParenRange.getEnd(); SourceLocation End = Loc; for (unsigned I = getNumArgs(); I > 0; --I) { @@ -438,7 +443,7 @@ SourceRange CXXConstructExpr::getSourceRange() const { } } - return SourceRange(Loc, End); + return End; } SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const { @@ -522,13 +527,14 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(ASTContext &C, QualType T, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, SourceLocation L, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + SourceRange AngleBrackets) { unsigned PathSize = (BasePath ? BasePath->size() : 0); void *Buffer = C.Allocate(sizeof(CXXStaticCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); CXXStaticCastExpr *E = new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, - RParenLoc); + RParenLoc, AngleBrackets); if (PathSize) E->setCastPath(*BasePath); return E; } @@ -546,13 +552,14 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(ASTContext &C, QualType T, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, SourceLocation L, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + SourceRange AngleBrackets) { unsigned PathSize = (BasePath ? BasePath->size() : 0); void *Buffer = C.Allocate(sizeof(CXXDynamicCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); CXXDynamicCastExpr *E = new (Buffer) CXXDynamicCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, - RParenLoc); + RParenLoc, AngleBrackets); if (PathSize) E->setCastPath(*BasePath); return E; } @@ -602,13 +609,14 @@ CXXReinterpretCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, SourceLocation L, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + SourceRange AngleBrackets) { unsigned PathSize = (BasePath ? BasePath->size() : 0); void *Buffer = C.Allocate(sizeof(CXXReinterpretCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); CXXReinterpretCastExpr *E = new (Buffer) CXXReinterpretCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, - RParenLoc); + RParenLoc, AngleBrackets); if (PathSize) E->setCastPath(*BasePath); return E; } @@ -624,8 +632,9 @@ CXXConstCastExpr *CXXConstCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK, Expr *Op, TypeSourceInfo *WrittenTy, SourceLocation L, - SourceLocation RParenLoc) { - return new (C) CXXConstCastExpr(T, VK, Op, WrittenTy, L, RParenLoc); + SourceLocation RParenLoc, + SourceRange AngleBrackets) { + return new (C) CXXConstCastExpr(T, VK, Op, WrittenTy, L, RParenLoc, AngleBrackets); } CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(ASTContext &C) { @@ -716,19 +725,24 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C, ArrayRef<Expr*> Args, SourceRange parenRange, bool HadMultipleCandidates, + bool ListInitialization, bool ZeroInitialization) : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type->getType().getNonReferenceType(), Type->getTypeLoc().getBeginLoc(), Cons, false, Args, - HadMultipleCandidates, /*FIXME*/false, ZeroInitialization, + HadMultipleCandidates, + ListInitialization, ZeroInitialization, CXXConstructExpr::CK_Complete, parenRange), Type(Type) { } -SourceRange CXXTemporaryObjectExpr::getSourceRange() const { - return SourceRange(Type->getTypeLoc().getBeginLoc(), - getParenRange().getEnd()); +SourceLocation CXXTemporaryObjectExpr::getLocStart() const { + return Type->getTypeLoc().getBeginLoc(); +} + +SourceLocation CXXTemporaryObjectExpr::getLocEnd() const { + return getParenRange().getEnd(); } CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T, @@ -963,9 +977,9 @@ CXXMethodDecl *LambdaExpr::getCallOperator() const { DeclarationName Name = Record->getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); DeclContext::lookup_result Calls = Record->lookup(Name); - assert(Calls.first != Calls.second && "Missing lambda call operator!"); - CXXMethodDecl *Result = cast<CXXMethodDecl>(*Calls.first++); - assert(Calls.first == Calls.second && "More than lambda one call operator?"); + assert(!Calls.empty() && "Missing lambda call operator!"); + assert(Calls.size() == 1 && "More than one lambda call operator!"); + CXXMethodDecl *Result = cast<CXXMethodDecl>(Calls.front()); return Result; } @@ -1057,8 +1071,8 @@ CXXUnresolvedConstructExpr::CreateEmpty(ASTContext &C, unsigned NumArgs) { return new (Mem) CXXUnresolvedConstructExpr(Empty, NumArgs); } -SourceRange CXXUnresolvedConstructExpr::getSourceRange() const { - return SourceRange(Type->getTypeLoc().getBeginLoc(), RParenLoc); +SourceLocation CXXUnresolvedConstructExpr::getLocStart() const { + return Type->getTypeLoc().getBeginLoc(); } CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, @@ -1330,7 +1344,7 @@ FunctionParmPackExpr::FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack, FunctionParmPackExpr * FunctionParmPackExpr::Create(ASTContext &Context, QualType T, ParmVarDecl *ParamPack, SourceLocation NameLoc, - llvm::ArrayRef<Decl*> Params) { + ArrayRef<Decl *> Params) { return new (Context.Allocate(sizeof(FunctionParmPackExpr) + sizeof(ParmVarDecl*) * Params.size())) FunctionParmPackExpr(T, ParamPack, NameLoc, Params.size(), Params.data()); diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp index 24ec6bb..61bc3e2 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp @@ -11,14 +11,14 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/ErrorHandling.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; typedef Expr::Classification Cl; @@ -34,21 +34,6 @@ static Cl::Kinds ClassifyConditional(ASTContext &Ctx, static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, Cl::Kinds Kind, SourceLocation &Loc); -static Cl::Kinds ClassifyExprValueKind(const LangOptions &Lang, - const Expr *E, - ExprValueKind Kind) { - switch (Kind) { - case VK_RValue: - return Lang.CPlusPlus && E->getType()->isRecordType() ? - Cl::CL_ClassTemporary : Cl::CL_PRValue; - case VK_LValue: - return Cl::CL_LValue; - case VK_XValue: - return Cl::CL_XValue; - } - llvm_unreachable("Invalid value category of implicit cast."); -} - Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const { assert(!TR->isReferenceType() && "Expressions can't have reference type."); @@ -100,6 +85,20 @@ static Cl::Kinds ClassifyTemporary(QualType T) { return Cl::CL_PRValue; } +static Cl::Kinds ClassifyExprValueKind(const LangOptions &Lang, + const Expr *E, + ExprValueKind Kind) { + switch (Kind) { + case VK_RValue: + return Lang.CPlusPlus ? ClassifyTemporary(E->getType()) : Cl::CL_PRValue; + case VK_LValue: + return Cl::CL_LValue; + case VK_XValue: + return Cl::CL_XValue; + } + llvm_unreachable("Invalid value category of implicit cast."); +} + static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { // This function takes the first stab at classifying expressions. const LangOptions &Lang = Ctx.getLangOpts(); diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index 6e0b5fc..ae86150 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -35,15 +35,16 @@ #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" -#include "clang/AST/ASTDiagnostic.h" -#include "clang/AST/Expr.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" #include <cstring> #include <functional> @@ -317,7 +318,7 @@ namespace { OptionalDiagnostic &operator<<(const APSInt &I) { if (Diag) { - llvm::SmallVector<char, 32> Buffer; + SmallVector<char, 32> Buffer; I.toString(Buffer); *Diag << StringRef(Buffer.data(), Buffer.size()); } @@ -326,7 +327,7 @@ namespace { OptionalDiagnostic &operator<<(const APFloat &F) { if (Diag) { - llvm::SmallVector<char, 32> Buffer; + SmallVector<char, 32> Buffer; F.toString(Buffer); *Diag << StringRef(Buffer.data(), Buffer.size()); } @@ -383,13 +384,17 @@ namespace { /// expression is a potential constant expression? If so, some diagnostics /// are suppressed. bool CheckingPotentialConstantExpression; + + bool IntOverflowCheckMode; - EvalInfo(const ASTContext &C, Expr::EvalStatus &S) + EvalInfo(const ASTContext &C, Expr::EvalStatus &S, + bool OverflowCheckMode=false) : Ctx(const_cast<ASTContext&>(C)), EvalStatus(S), CurrentCall(0), CallStackDepth(0), NextCallIndex(1), BottomFrame(*this, SourceLocation(), 0, 0, 0), EvaluatingDecl(0), EvaluatingDeclValue(0), HasActiveDiagnostic(false), - CheckingPotentialConstantExpression(false) {} + CheckingPotentialConstantExpression(false), + IntOverflowCheckMode(OverflowCheckMode) {} void setEvaluatingDecl(const VarDecl *VD, APValue &Value) { EvaluatingDecl = VD; @@ -473,6 +478,8 @@ namespace { return OptionalDiagnostic(); } + bool getIntOverflowCheckMode() { return IntOverflowCheckMode; } + /// Diagnose that the evaluation does not produce a C++11 core constant /// expression. template<typename LocArg> @@ -505,8 +512,11 @@ namespace { /// Should we continue evaluation as much as possible after encountering a /// construct which can't be folded? bool keepEvaluatingAfterFailure() { - return CheckingPotentialConstantExpression && - EvalStatus.Diag && EvalStatus.Diag->empty(); + // Should return true in IntOverflowCheckMode, so that we check for + // overflow even if some subexpressions can't be evaluated as constants. + return IntOverflowCheckMode || + (CheckingPotentialConstantExpression && + EvalStatus.Diag && EvalStatus.Diag->empty()); } }; @@ -534,8 +544,7 @@ namespace { public: SpeculativeEvaluationRAII(EvalInfo &Info, - llvm::SmallVectorImpl<PartialDiagnosticAt> - *NewDiag = 0) + SmallVectorImpl<PartialDiagnosticAt> *NewDiag = 0) : Info(Info), Old(Info.EvalStatus) { Info.EvalStatus.Diag = NewDiag; } @@ -586,7 +595,7 @@ CallStackFrame::~CallStackFrame() { } /// Produce a string describing the given constexpr call. -static void describeCall(CallStackFrame *Frame, llvm::raw_ostream &Out) { +static void describeCall(CallStackFrame *Frame, raw_ostream &Out) { unsigned ArgIndex = 0; bool IsMemberCall = isa<CXXMethodDecl>(Frame->Callee) && !isa<CXXConstructorDecl>(Frame->Callee) && @@ -634,7 +643,7 @@ void EvalInfo::addCallStack(unsigned Limit) { continue; } - llvm::SmallVector<char, 128> Buffer; + SmallVector<char, 128> Buffer; llvm::raw_svector_ostream Out(Buffer); describeCall(Frame, Out); addDiag(Frame->CallLoc, diag::note_constexpr_call_here) << Out.str(); @@ -737,7 +746,7 @@ namespace { bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { // Outside C++11, do not build a designator referring to a subobject of // any object: we won't use such a designator for anything. - if (!Info.getLangOpts().CPlusPlus0x) + if (!Info.getLangOpts().CPlusPlus11) Designator.setInvalid(); return checkNullPointer(Info, E, CSK) && Designator.checkSubobject(Info, E, CSK); @@ -971,7 +980,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, // manufacture when checking potential constant expressions is conservatively // assumed to be global here. if (!IsGlobalLValue(Base)) { - if (Info.getLangOpts().CPlusPlus0x) { + if (Info.getLangOpts().CPlusPlus11) { const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>(); Info.Diag(Loc, diag::note_constexpr_non_global, 1) << IsReferenceType << !Designator.Entries.empty() @@ -1025,7 +1034,7 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E) { return true; // Prvalue constant expressions must be of literal types. - if (Info.getLangOpts().CPlusPlus0x) + if (Info.getLangOpts().CPlusPlus11) Info.Diag(E, diag::note_constexpr_nonliteral) << E->getType(); else @@ -1462,7 +1471,7 @@ static bool EvaluateVarDeclInit(EvalInfo &Info, const Expr *E, // Check that we can fold the initializer. In C++, we will have already done // this in the cases where it matters for conformance. - llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + SmallVector<PartialDiagnosticAt, 8> Notes; if (!VD->evaluateValue(Notes)) { Info.Diag(E, diag::note_constexpr_var_init_non_constant, Notes.size() + 1) << VD; @@ -1526,7 +1535,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, // A diagnostic will have already been produced. return false; if (Sub.isOnePastTheEnd()) { - Info.Diag(E, Info.getLangOpts().CPlusPlus0x ? + Info.Diag(E, Info.getLangOpts().CPlusPlus11 ? (unsigned)diag::note_constexpr_read_past_end : (unsigned)diag::note_invalid_subexpr_in_const_expr); return false; @@ -1548,7 +1557,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, if (CAT->getSize().ule(Index)) { // Note, it should not be possible to form a pointer with a valid // designator which points more than one past the end of the array. - Info.Diag(E, Info.getLangOpts().CPlusPlus0x ? + Info.Diag(E, Info.getLangOpts().CPlusPlus11 ? (unsigned)diag::note_constexpr_read_past_end : (unsigned)diag::note_invalid_subexpr_in_const_expr); return false; @@ -1570,7 +1579,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, // Next subobject is a complex number. uint64_t Index = Sub.Entries[I].ArrayIndex; if (Index > 1) { - Info.Diag(E, Info.getLangOpts().CPlusPlus0x ? + Info.Diag(E, Info.getLangOpts().CPlusPlus11 ? (unsigned)diag::note_constexpr_read_past_end : (unsigned)diag::note_invalid_subexpr_in_const_expr); return false; @@ -1795,7 +1804,7 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, // We support folding of const floating-point types, in order to make // static const data members of such types (supported as an extension) // more useful. - if (Info.getLangOpts().CPlusPlus0x) { + if (Info.getLangOpts().CPlusPlus11) { Info.CCEDiag(Conv, diag::note_constexpr_ltor_non_constexpr, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { @@ -1803,7 +1812,7 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, } } else { // FIXME: Allow folding of values of any literal type in all languages. - if (Info.getLangOpts().CPlusPlus0x) { + if (Info.getLangOpts().CPlusPlus11) { Info.Diag(Conv, diag::note_constexpr_ltor_non_constexpr, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { @@ -2080,7 +2089,7 @@ static bool CheckTrivialDefaultConstructor(EvalInfo &Info, SourceLocation Loc, // call is a core constant expression whether or not the constructor is // constexpr. if (!CD->isConstexpr() && !IsValueInitialization) { - if (Info.getLangOpts().CPlusPlus0x) { + if (Info.getLangOpts().CPlusPlus11) { // FIXME: If DiagDecl is an implicitly-declared special member function, // we should be much more explicit about why it's not constexpr. Info.CCEDiag(Loc, diag::note_constexpr_invalid_function, 1) @@ -2108,7 +2117,7 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl()) return true; - if (Info.getLangOpts().CPlusPlus0x) { + if (Info.getLangOpts().CPlusPlus11) { const FunctionDecl *DiagDecl = Definition ? Definition : Declaration; // FIXME: If DiagDecl is an implicitly-declared special member function, we // should be much more explicit about why it's not constexpr. @@ -2311,7 +2320,7 @@ private: // Speculatively evaluate both arms. { - llvm::SmallVector<PartialDiagnosticAt, 8> Diag; + SmallVector<PartialDiagnosticAt, 8> Diag; SpeculativeEvaluationRAII Speculate(Info, &Diag); StmtVisitorTy::Visit(E->getFalseExpr()); @@ -2482,7 +2491,7 @@ public: const FunctionDecl *FD = 0; LValue *This = 0, ThisVal; - llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs()); + ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); bool HasQualifier = false; // Extract function decl and 'this' pointer from the callee. @@ -3487,7 +3496,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { if (ZeroInit && !ZeroInitialization(E)) return false; - llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs()); + ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); return HandleConstructorCall(E->getExprLoc(), This, Args, cast<CXXConstructorDecl>(Definition), Info, Result); @@ -3629,7 +3638,6 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { SmallVector<APValue, 4> Elts; if (EltTy->isRealFloatingType()) { const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy); - bool isIEESem = &Sem != &APFloat::PPCDoubleDouble; unsigned FloatEltSize = EltSize; if (&Sem == &APFloat::x87DoubleExtended) FloatEltSize = 80; @@ -3639,7 +3647,7 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { Elt = SValInt.rotl(i*EltSize+FloatEltSize).trunc(FloatEltSize); else Elt = SValInt.rotr(i*EltSize).trunc(FloatEltSize); - Elts.push_back(APValue(APFloat(Elt, isIEESem))); + Elts.push_back(APValue(APFloat(Sem, Elt))); } } else if (EltTy->isIntegerType()) { for (unsigned i = 0; i < NElts; i++) { @@ -3898,7 +3906,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { return false; } - llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs()); + ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); return HandleConstructorCall(E->getExprLoc(), Subobject, Args, cast<CXXConstructorDecl>(Definition), Info, *Value); @@ -4317,7 +4325,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BIstrlen: // A call to strlen is not a constant expression. - if (Info.getLangOpts().CPlusPlus0x) + if (Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_invalid_function) << /*isConstexpr*/0 << /*isConstructor*/0 << "'strlen'"; else @@ -4419,8 +4427,14 @@ static APSInt CheckedIntArithmetic(EvalInfo &Info, const Expr *E, APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false); APSInt Result = Value.trunc(LHS.getBitWidth()); - if (Result.extend(BitWidth) != Value) - HandleOverflow(Info, E, Value, E->getType()); + if (Result.extend(BitWidth) != Value) { + if (Info.getIntOverflowCheckMode()) + Info.Ctx.getDiagnostics().Report(E->getExprLoc(), + diag::warn_integer_constant_overflow) + << Result.toString(10) << E->getType(); + else + HandleOverflow(Info, E, Value, E->getType()); + } return Result; } @@ -4707,9 +4721,14 @@ bool DataRecursiveIntBinOpEvaluator:: return Success(E->getOpcode() == BO_Rem ? LHS % RHS : LHS / RHS, E, Result); case BO_Shl: { - // During constant-folding, a negative shift is an opposite shift. Such - // a shift is not a constant expression. - if (RHS.isSigned() && RHS.isNegative()) { + if (Info.getLangOpts().OpenCL) + // OpenCL 6.3j: shift values are effectively % word size of LHS. + RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), + static_cast<uint64_t>(LHS.getBitWidth() - 1)), + RHS.isUnsigned()); + else if (RHS.isSigned() && RHS.isNegative()) { + // During constant-folding, a negative shift is an opposite shift. Such + // a shift is not a constant expression. CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; RHS = -RHS; goto shift_right; @@ -4734,9 +4753,14 @@ bool DataRecursiveIntBinOpEvaluator:: return Success(LHS << SA, E, Result); } case BO_Shr: { - // During constant-folding, a negative shift is an opposite shift. Such a - // shift is not a constant expression. - if (RHS.isSigned() && RHS.isNegative()) { + if (Info.getLangOpts().OpenCL) + // OpenCL 6.3j: shift values are effectively % word size of LHS. + RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), + static_cast<uint64_t>(LHS.getBitWidth() - 1)), + RHS.isUnsigned()); + else if (RHS.isSigned() && RHS.isNegative()) { + // During constant-folding, a negative shift is an opposite shift. Such a + // shift is not a constant expression. CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; RHS = -RHS; goto shift_left; @@ -5362,6 +5386,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_IntegralComplexCast: case CK_IntegralComplexToFloatingComplex: case CK_BuiltinFnToFnPtr: + case CK_ZeroToOCLEvent: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -5849,6 +5874,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_ARCExtendBlockObject: case CK_CopyAndAutoreleaseBlockObject: case CK_BuiltinFnToFnPtr: + case CK_ZeroToOCLEvent: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: @@ -6191,12 +6217,12 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { return false; Result = Info.CurrentCall->Temporaries[E]; } else if (E->getType()->isVoidType()) { - if (!Info.getLangOpts().CPlusPlus0x) + if (!Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_nonliteral) << E->getType(); if (!EvaluateVoid(E, Info)) return false; - } else if (Info.getLangOpts().CPlusPlus0x) { + } else if (Info.getLangOpts().CPlusPlus11) { Info.Diag(E, diag::note_constexpr_nonliteral) << E->getType(); return false; } else { @@ -6249,26 +6275,39 @@ static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) { return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), Result); } -/// EvaluateAsRValue - Return true if this is a constant which we can fold using -/// any crazy technique (that has nothing to do with language standards) that -/// we want to. If this function returns true, it returns the folded constant -/// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion -/// will be applied to the result. -bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { +static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, + const ASTContext &Ctx, bool &IsConst) { // Fast-path evaluations of integer literals, since we sometimes see files // containing vast quantities of these. - if (const IntegerLiteral *L = dyn_cast<IntegerLiteral>(this)) { + if (const IntegerLiteral *L = dyn_cast<IntegerLiteral>(Exp)) { Result.Val = APValue(APSInt(L->getValue(), L->getType()->isUnsignedIntegerType())); + IsConst = true; return true; } - + // FIXME: Evaluating values of large array and record types can cause // performance problems. Only do so in C++11 for now. - if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) && - !Ctx.getLangOpts().CPlusPlus0x) - return false; + if (Exp->isRValue() && (Exp->getType()->isArrayType() || + Exp->getType()->isRecordType()) && + !Ctx.getLangOpts().CPlusPlus11) { + IsConst = false; + return true; + } + return false; +} + +/// EvaluateAsRValue - Return true if this is a constant which we can fold using +/// any crazy technique (that has nothing to do with language standards) that +/// we want to. If this function returns true, it returns the folded constant +/// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion +/// will be applied to the result. +bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { + bool IsConst; + if (FastEvaluateAsRValue(this, Result, Ctx, IsConst)) + return IsConst; + EvalInfo Info(Ctx, Result); return ::EvaluateAsRValue(Info, this, Result.Val); } @@ -6309,11 +6348,11 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const { bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, const VarDecl *VD, - llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const { + SmallVectorImpl<PartialDiagnosticAt> &Notes) const { // FIXME: Evaluating initializers for large array and record types can cause // performance problems. Only do so in C++11 for now. if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) && - !Ctx.getLangOpts().CPlusPlus0x) + !Ctx.getLangOpts().CPlusPlus11) return false; Expr::EvalStatus EStatus; @@ -6353,8 +6392,10 @@ bool Expr::isEvaluatable(const ASTContext &Ctx) const { return EvaluateAsRValue(Result, Ctx) && !Result.HasSideEffects; } -APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const { +APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx, + SmallVectorImpl<PartialDiagnosticAt> *Diag) const { EvalResult EvalResult; + EvalResult.Diag = Diag; bool Result = EvaluateAsRValue(EvalResult, Ctx); (void)Result; assert(Result && "Could not evaluate expression"); @@ -6363,6 +6404,17 @@ APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const { return EvalResult.Val.getInt(); } +void Expr::EvaluateForOverflow(const ASTContext &Ctx, + SmallVectorImpl<PartialDiagnosticAt> *Diags) const { + bool IsConst; + EvalResult EvalResult; + EvalResult.Diag = Diags; + if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) { + EvalInfo Info(Ctx, EvalResult, true); + (void)::EvaluateAsRValue(Info, this, EvalResult.Val); + } +} + bool Expr::EvalResult::isGlobalLValue() const { assert(Val.isLValue()); return IsGlobalLValue(Val.getLValueBase()); @@ -6374,54 +6426,55 @@ APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const { /// FIXME: Pass up a reason why! Invalid operation in i-c-e, division by zero, /// comma, etc -/// -/// FIXME: Handle offsetof. Two things to do: Handle GCC's __builtin_offsetof -/// to support gcc 4.0+ and handle the idiom GCC recognizes with a null pointer -/// cast+dereference. // CheckICE - This function does the fundamental ICE checking: the returned -// ICEDiag contains a Val of 0, 1, or 2, and a possibly null SourceLocation. +// ICEDiag contains an ICEKind indicating whether the expression is an ICE, +// and a (possibly null) SourceLocation indicating the location of the problem. +// // Note that to reduce code duplication, this helper does no evaluation // itself; the caller checks whether the expression is evaluatable, and // in the rare cases where CheckICE actually cares about the evaluated // value, it calls into Evalute. -// -// Meanings of Val: -// 0: This expression is an ICE. -// 1: This expression is not an ICE, but if it isn't evaluated, it's -// a legal subexpression for an ICE. This return value is used to handle -// the comma operator in C99 mode. -// 2: This expression is not an ICE, and is not a legal subexpression for one. namespace { +enum ICEKind { + /// This expression is an ICE. + IK_ICE, + /// This expression is not an ICE, but if it isn't evaluated, it's + /// a legal subexpression for an ICE. This return value is used to handle + /// the comma operator in C99 mode, and non-constant subexpressions. + IK_ICEIfUnevaluated, + /// This expression is not an ICE, and is not a legal subexpression for one. + IK_NotICE +}; + struct ICEDiag { - unsigned Val; + ICEKind Kind; SourceLocation Loc; - public: - ICEDiag(unsigned v, SourceLocation l) : Val(v), Loc(l) {} - ICEDiag() : Val(0) {} + ICEDiag(ICEKind IK, SourceLocation l) : Kind(IK), Loc(l) {} }; } -static ICEDiag NoDiag() { return ICEDiag(); } +static ICEDiag NoDiag() { return ICEDiag(IK_ICE, SourceLocation()); } + +static ICEDiag Worst(ICEDiag A, ICEDiag B) { return A.Kind >= B.Kind ? A : B; } static ICEDiag CheckEvalInICE(const Expr* E, ASTContext &Ctx) { Expr::EvalResult EVResult; if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects || - !EVResult.Val.isInt()) { - return ICEDiag(2, E->getLocStart()); - } + !EVResult.Val.isInt()) + return ICEDiag(IK_NotICE, E->getLocStart()); + return NoDiag(); } static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { assert(!E->isValueDependent() && "Should not see value dependent exprs!"); - if (!E->getType()->isIntegralOrEnumerationType()) { - return ICEDiag(2, E->getLocStart()); - } + if (!E->getType()->isIntegralOrEnumerationType()) + return ICEDiag(IK_NotICE, E->getLocStart()); switch (E->getStmtClass()) { #define ABSTRACT_STMT(Node) @@ -6490,7 +6543,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::AtomicExprClass: case Expr::InitListExprClass: case Expr::LambdaExprClass: - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); case Expr::SizeOfPackExprClass: case Expr::GNUNullExprClass: @@ -6525,7 +6578,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { const CallExpr *CE = cast<CallExpr>(E); if (CE->isBuiltinCall()) return CheckEvalInICE(E, Ctx); - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); } case Expr::DeclRefExprClass: { if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl())) @@ -6537,14 +6590,14 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // getAnyInitializer() can find a default argument, which leads // to chaos. if (isa<ParmVarDecl>(D)) - return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); + return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation()); // C++ 7.1.5.1p2 // A variable of non-volatile const-qualified integral or enumeration // type initialized by an ICE can be used in ICEs. if (const VarDecl *Dcl = dyn_cast<VarDecl>(D)) { if (!Dcl->getType()->isIntegralOrEnumerationType()) - return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); + return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation()); const VarDecl *VD; // Look for a declaration of this variable that has an initializer, and @@ -6552,10 +6605,10 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { if (Dcl->getAnyInitializer(VD) && VD->checkInitIsICE()) return NoDiag(); else - return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); + return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation()); } } - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); } case Expr::UnaryOperatorClass: { const UnaryOperator *Exp = cast<UnaryOperator>(E); @@ -6569,7 +6622,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // C99 6.6/3 allows increment and decrement within unevaluated // subexpressions of constant expressions, but they can never be ICEs // because an ICE cannot contain an lvalue operand. - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); case UO_Extension: case UO_LNot: case UO_Plus: @@ -6579,23 +6632,23 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case UO_Imag: return CheckICE(Exp->getSubExpr(), Ctx); } - + // OffsetOf falls through here. } case Expr::OffsetOfExprClass: { - // Note that per C99, offsetof must be an ICE. And AFAIK, using - // EvaluateAsRValue matches the proposed gcc behavior for cases like - // "offsetof(struct s{int x[4];}, x[1.0])". This doesn't affect - // compliance: we should warn earlier for offsetof expressions with - // array subscripts that aren't ICEs, and if the array subscripts - // are ICEs, the value of the offsetof must be an integer constant. - return CheckEvalInICE(E, Ctx); + // Note that per C99, offsetof must be an ICE. And AFAIK, using + // EvaluateAsRValue matches the proposed gcc behavior for cases like + // "offsetof(struct s{int x[4];}, x[1.0])". This doesn't affect + // compliance: we should warn earlier for offsetof expressions with + // array subscripts that aren't ICEs, and if the array subscripts + // are ICEs, the value of the offsetof must be an integer constant. + return CheckEvalInICE(E, Ctx); } case Expr::UnaryExprOrTypeTraitExprClass: { const UnaryExprOrTypeTraitExpr *Exp = cast<UnaryExprOrTypeTraitExpr>(E); if ((Exp->getKind() == UETT_SizeOf) && Exp->getTypeOfArgument()->isVariableArrayType()) - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); return NoDiag(); } case Expr::BinaryOperatorClass: { @@ -6617,7 +6670,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // C99 6.6/3 allows assignments within unevaluated subexpressions of // constant expressions, but they can never be ICEs because an ICE cannot // contain an lvalue operand. - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); case BO_Mul: case BO_Div: @@ -6642,14 +6695,14 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { Exp->getOpcode() == BO_Rem) { // EvaluateAsRValue gives an error for undefined Div/Rem, so make sure // we don't evaluate one. - if (LHSResult.Val == 0 && RHSResult.Val == 0) { + if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) { llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx); if (REval == 0) - return ICEDiag(1, E->getLocStart()); + return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); if (REval.isSigned() && REval.isAllOnesValue()) { llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx); if (LEval.isMinSignedValue()) - return ICEDiag(1, E->getLocStart()); + return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); } } } @@ -6657,22 +6710,20 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { if (Ctx.getLangOpts().C99) { // C99 6.6p3 introduces a strange edge case: comma can be in an ICE // if it isn't evaluated. - if (LHSResult.Val == 0 && RHSResult.Val == 0) - return ICEDiag(1, E->getLocStart()); + if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) + return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); } else { // In both C89 and C++, commas in ICEs are illegal. - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); } } - if (LHSResult.Val >= RHSResult.Val) - return LHSResult; - return RHSResult; + return Worst(LHSResult, RHSResult); } case BO_LAnd: case BO_LOr: { ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); - if (LHSResult.Val == 0 && RHSResult.Val == 1) { + if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICEIfUnevaluated) { // Rare case where the RHS has a comma "side-effect"; we need // to actually check the condition to see whether the side // with the comma is evaluated. @@ -6682,9 +6733,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { return NoDiag(); } - if (LHSResult.Val >= RHSResult.Val) - return LHSResult; - return RHSResult; + return Worst(LHSResult, RHSResult); } } } @@ -6709,7 +6758,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { if (FL->getValue().convertToInteger(IgnoredVal, llvm::APFloat::rmTowardZero, &Ignored) & APFloat::opInvalidOp) - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); return NoDiag(); } } @@ -6722,18 +6771,18 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case CK_IntegralCast: return CheckICE(SubExpr, Ctx); default: - return ICEDiag(2, E->getLocStart()); + return ICEDiag(IK_NotICE, E->getLocStart()); } } case Expr::BinaryConditionalOperatorClass: { const BinaryConditionalOperator *Exp = cast<BinaryConditionalOperator>(E); ICEDiag CommonResult = CheckICE(Exp->getCommon(), Ctx); - if (CommonResult.Val == 2) return CommonResult; + if (CommonResult.Kind == IK_NotICE) return CommonResult; ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); - if (FalseResult.Val == 2) return FalseResult; - if (CommonResult.Val == 1) return CommonResult; - if (FalseResult.Val == 1 && - Exp->getCommon()->EvaluateKnownConstInt(Ctx) == 0) return NoDiag(); + if (FalseResult.Kind == IK_NotICE) return FalseResult; + if (CommonResult.Kind == IK_ICEIfUnevaluated) return CommonResult; + if (FalseResult.Kind == IK_ICEIfUnevaluated && + Exp->getCommon()->EvaluateKnownConstInt(Ctx) != 0) return NoDiag(); return FalseResult; } case Expr::ConditionalOperatorClass: { @@ -6747,26 +6796,25 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p) return CheckEvalInICE(E, Ctx); ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx); - if (CondResult.Val == 2) + if (CondResult.Kind == IK_NotICE) return CondResult; ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx); ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); - if (TrueResult.Val == 2) + if (TrueResult.Kind == IK_NotICE) return TrueResult; - if (FalseResult.Val == 2) + if (FalseResult.Kind == IK_NotICE) return FalseResult; - if (CondResult.Val == 1) + if (CondResult.Kind == IK_ICEIfUnevaluated) return CondResult; - if (TrueResult.Val == 0 && FalseResult.Val == 0) + if (TrueResult.Kind == IK_ICE && FalseResult.Kind == IK_ICE) return NoDiag(); // Rare case where the diagnostics depend on which side is evaluated // Note that if we get here, CondResult is 0, and at least one of // TrueResult and FalseResult is non-zero. - if (Exp->getCond()->EvaluateKnownConstInt(Ctx) == 0) { + if (Exp->getCond()->EvaluateKnownConstInt(Ctx) == 0) return FalseResult; - } return TrueResult; } case Expr::CXXDefaultArgExprClass: @@ -6799,12 +6847,12 @@ static bool EvaluateCPlusPlus11IntegralConstantExpr(ASTContext &Ctx, } bool Expr::isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const { - if (Ctx.getLangOpts().CPlusPlus0x) + if (Ctx.getLangOpts().CPlusPlus11) return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, 0, Loc); - ICEDiag d = CheckICE(this, Ctx); - if (d.Val != 0) { - if (Loc) *Loc = d.Loc; + ICEDiag D = CheckICE(this, Ctx); + if (D.Kind != IK_ICE) { + if (Loc) *Loc = D.Loc; return false; } return true; @@ -6812,7 +6860,7 @@ bool Expr::isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const { bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, ASTContext &Ctx, SourceLocation *Loc, bool isEvaluated) const { - if (Ctx.getLangOpts().CPlusPlus0x) + if (Ctx.getLangOpts().CPlusPlus11) return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc); if (!isIntegerConstantExpr(Ctx, Loc)) @@ -6823,7 +6871,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, ASTContext &Ctx, } bool Expr::isCXX98IntegralConstantExpr(ASTContext &Ctx) const { - return CheckICE(this, Ctx).Val == 0; + return CheckICE(this, Ctx).Kind == IK_ICE; } bool Expr::isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result, @@ -6834,7 +6882,7 @@ bool Expr::isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result, // Build evaluation settings. Expr::EvalStatus Status; - llvm::SmallVector<PartialDiagnosticAt, 8> Diags; + SmallVector<PartialDiagnosticAt, 8> Diags; Status.Diag = &Diags; EvalInfo Info(Ctx, Status); @@ -6853,7 +6901,7 @@ bool Expr::isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result, } bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, - llvm::SmallVectorImpl< + SmallVectorImpl< PartialDiagnosticAt> &Diags) { // FIXME: It would be useful to check constexpr function templates, but at the // moment the constant expression evaluator cannot cope with the non-rigorous diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp index 6b9fe26..96ebe92 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp @@ -43,10 +43,10 @@ ExternalASTSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) { return 0; } -DeclContextLookupResult +bool ExternalASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) { - return DeclContext::lookup_result(); + return false; } void ExternalASTSource::completeVisibleDeclsMap(const DeclContext *DC) { diff --git a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp index b70520f..e03632a 100644 --- a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp +++ b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp @@ -134,7 +134,7 @@ InheritanceHierarchyWriter::WriteNodeReference(QualType Type, /// viewInheritance - Display the inheritance hierarchy of this C++ /// class using GraphViz. void CXXRecordDecl::viewInheritance(ASTContext& Context) const { - QualType Self = Context.getTypeDeclType(const_cast<CXXRecordDecl *>(this)); + QualType Self = Context.getTypeDeclType(this); std::string ErrMsg; sys::Path Filename = sys::Path::GetTemporaryDirectory(&ErrMsg); if (Filename.isEmpty()) { diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp index ce1244c..894eb3b 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp @@ -19,8 +19,8 @@ #include "CXXABI.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/RecordLayout.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/RecordLayout.h" #include "clang/AST/Type.h" #include "clang/Basic/TargetInfo.h" @@ -33,10 +33,15 @@ protected: public: ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { } - unsigned getMemberPointerSize(const MemberPointerType *MPT) const { - QualType Pointee = MPT->getPointeeType(); - if (Pointee->isFunctionType()) return 2; - return 1; + std::pair<uint64_t, unsigned> + getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const { + const TargetInfo &Target = Context.getTargetInfo(); + TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0); + uint64_t Width = Target.getTypeWidth(PtrDiff); + unsigned Align = Target.getTypeAlign(PtrDiff); + if (MPT->getPointeeType()->isFunctionType()) + Width = 2 * Width; + return std::make_pair(Width, Align); } CallingConv getDefaultMethodCallConv(bool isVariadic) const { diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index 851944a..21c4993 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -16,6 +16,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/Mangle.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -27,8 +28,8 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #define MANGLE_CHECKER 0 @@ -355,17 +356,6 @@ private: } -static bool isInCLinkageSpecification(const Decl *D) { - D = D->getCanonicalDecl(); - for (const DeclContext *DC = getEffectiveDeclContext(D); - !DC->isTranslationUnit(); DC = getEffectiveParentContext(DC)) { - if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) - return Linkage->getLanguage() == LinkageSpecDecl::lang_c; - } - - return false; -} - bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { // In C, functions with no attributes never need to be mangled. Fastpath them. if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs()) @@ -376,20 +366,38 @@ bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { if (D->hasAttr<AsmLabelAttr>()) return true; - // Clang's "overloadable" attribute extension to C/C++ implies name mangling - // (always) as does passing a C++ member function and a function - // whose name is not a simple identifier. const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); - if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) || - !FD->getDeclName().isIdentifier())) - return true; + if (FD) { + LanguageLinkage L = FD->getLanguageLinkage(); + // Overloadable functions need mangling. + if (FD->hasAttr<OverloadableAttr>()) + return true; + + // "main" is not mangled. + if (FD->isMain()) + return false; + + // C++ functions and those whose names are not a simple identifier need + // mangling. + if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage) + return true; + + // C functions are not mangled. + if (L == CLanguageLinkage) + return false; + } // Otherwise, no mangling is done outside C++ mode. if (!getASTContext().getLangOpts().CPlusPlus) return false; - // Variables at global scope with non-internal linkage are not mangled - if (!FD) { + const VarDecl *VD = dyn_cast<VarDecl>(D); + if (VD) { + // C variables are not mangled. + if (VD->isExternC()) + return false; + + // Variables at global scope with non-internal linkage are not mangled const DeclContext *DC = getEffectiveDeclContext(D); // Check for extern variable declared locally. if (DC->isFunctionOrMethod() && D->hasLinkage()) @@ -399,14 +407,6 @@ bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { return false; } - // Class members are always mangled. - if (getEffectiveDeclContext(D)->isRecord()) - return true; - - // C functions and "main" are not mangled. - if ((FD && FD->isMain()) || isInCLinkageSpecification(D)) - return false; - return true; } @@ -656,7 +656,7 @@ void CXXNameMangler::mangleFloat(const llvm::APFloat &f) { assert(numCharacters != 0); // Allocate a buffer of the right number of characters. - llvm::SmallVector<char, 20> buffer; + SmallVector<char, 20> buffer; buffer.set_size(numCharacters); // Fill the buffer left-to-right. @@ -1117,7 +1117,16 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, break; } } - + + int UnnamedMangle = Context.getASTContext().getUnnamedTagManglingNumber(TD); + if (UnnamedMangle != -1) { + Out << "Ut"; + if (UnnamedMangle != 0) + Out << llvm::utostr(UnnamedMangle - 1); + Out << '_'; + break; + } + // Get a unique id for the anonymous struct. uint64_t AnonStructId = Context.getAnonymousStructId(TD); @@ -1658,7 +1667,8 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { // where <address-space-number> is a source name consisting of 'AS' // followed by the address space <number>. SmallString<64> ASString; - ASString = "AS" + llvm::utostr_32(Quals.getAddressSpace()); + ASString = "AS" + llvm::utostr_32( + Context.getASTContext().getTargetAddressSpace(Quals.getAddressSpace())); Out << 'U' << ASString.size() << ASString; } @@ -1870,6 +1880,14 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::ObjCId: Out << "11objc_object"; break; case BuiltinType::ObjCClass: Out << "10objc_class"; break; case BuiltinType::ObjCSel: Out << "13objc_selector"; break; + case BuiltinType::OCLImage1d: Out << "11ocl_image1d"; break; + case BuiltinType::OCLImage1dArray: Out << "16ocl_image1darray"; break; + case BuiltinType::OCLImage1dBuffer: Out << "17ocl_image1dbuffer"; break; + case BuiltinType::OCLImage2d: Out << "11ocl_image2d"; break; + case BuiltinType::OCLImage2dArray: Out << "16ocl_image2darray"; break; + case BuiltinType::OCLImage3d: Out << "11ocl_image3d"; break; + case BuiltinType::OCLSampler: Out << "11ocl_sampler"; break; + case BuiltinType::OCLEvent: Out << "9ocl_event"; break; } } diff --git a/contrib/llvm/tools/clang/lib/AST/LambdaMangleContext.cpp b/contrib/llvm/tools/clang/lib/AST/LambdaMangleContext.cpp index 6f4fe2d..54f445d 100644 --- a/contrib/llvm/tools/clang/lib/AST/LambdaMangleContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/LambdaMangleContext.cpp @@ -23,10 +23,11 @@ unsigned LambdaMangleContext::getManglingNumber(CXXMethodDecl *CallOperator) { = CallOperator->getType()->getAs<FunctionProtoType>(); ASTContext &Context = CallOperator->getASTContext(); - QualType Key = Context.getFunctionType(Context.VoidTy, - Proto->arg_type_begin(), - Proto->getNumArgs(), - FunctionProtoType::ExtProtoInfo()); + QualType Key = + Context.getFunctionType(Context.VoidTy, + ArrayRef<QualType>(Proto->arg_type_begin(), + Proto->getNumArgs()), + FunctionProtoType::ExtProtoInfo()); Key = Context.getCanonicalType(Key); return ++ManglingNumbers[Key->castAs<FunctionProtoType>()]; } diff --git a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp index d5f8371..eb79412 100644 --- a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp @@ -20,8 +20,8 @@ #include "clang/Basic/ABI.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #define MANGLE_CHECKER 0 diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp index 51308ea..6553e9d 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "CXXABI.h" +#include "clang/AST/Attr.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/RecordLayout.h" @@ -27,13 +28,14 @@ class MicrosoftCXXABI : public CXXABI { public: MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { } - unsigned getMemberPointerSize(const MemberPointerType *MPT) const; + std::pair<uint64_t, unsigned> + getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const; CallingConv getDefaultMethodCallConv(bool isVariadic) const { - if (!isVariadic && Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) + if (!isVariadic && + Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) return CC_X86ThisCall; - else - return CC_C; + return CC_C; } bool isNearlyEmpty(const CXXRecordDecl *RD) const { @@ -52,17 +54,121 @@ public: }; } -unsigned MicrosoftCXXABI::getMemberPointerSize(const MemberPointerType *MPT) const { - QualType Pointee = MPT->getPointeeType(); - CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); - if (RD->getNumVBases() > 0) { - if (Pointee->isFunctionType()) - return 3; - else - return 2; - } else if (RD->getNumBases() > 1 && Pointee->isFunctionType()) - return 2; - return 1; +// getNumBases() seems to only give us the number of direct bases, and not the +// total. This function tells us if we inherit from anybody that uses MI, or if +// we have a non-primary base class, which uses the multiple inheritance model. +static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) { + while (RD->getNumBases() > 0) { + if (RD->getNumBases() > 1) + return true; + assert(RD->getNumBases() == 1); + const CXXRecordDecl *Base = + RD->bases_begin()->getType()->getAsCXXRecordDecl(); + if (RD->isPolymorphic() && !Base->isPolymorphic()) + return true; + RD = Base; + } + return false; +} + +static MSInheritanceModel MSInheritanceAttrToModel(attr::Kind Kind) { + switch (Kind) { + default: llvm_unreachable("expected MS inheritance attribute"); + case attr::SingleInheritance: return MSIM_Single; + case attr::MultipleInheritance: return MSIM_Multiple; + case attr::VirtualInheritance: return MSIM_Virtual; + case attr::UnspecifiedInheritance: return MSIM_Unspecified; + } +} + +MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const { + if (Attr *IA = this->getAttr<MSInheritanceAttr>()) + return MSInheritanceAttrToModel(IA->getKind()); + // If there was no explicit attribute, the record must be defined already, and + // we can figure out the inheritance model from its other properties. + if (this->getNumVBases() > 0) + return MSIM_Virtual; + if (usesMultipleInheritanceModel(this)) + return MSIM_Multiple; + return MSIM_Single; +} + +// Returns the number of pointer and integer slots used to represent a member +// pointer in the MS C++ ABI. +// +// Member function pointers have the following general form; however, fields +// are dropped as permitted (under the MSVC interpretation) by the inheritance +// model of the actual class. +// +// struct { +// // A pointer to the member function to call. If the member function is +// // virtual, this will be a thunk that forwards to the appropriate vftable +// // slot. +// void *FunctionPointerOrVirtualThunk; +// +// // An offset to add to the address of the vbtable pointer after (possibly) +// // selecting the virtual base but before resolving and calling the function. +// // Only needed if the class has any virtual bases or bases at a non-zero +// // offset. +// int NonVirtualBaseAdjustment; +// +// // An offset within the vb-table that selects the virtual base containing +// // the member. Loading from this offset produces a new offset that is +// // added to the address of the vb-table pointer to produce the base. +// int VirtualBaseAdjustmentOffset; +// +// // The offset of the vb-table pointer within the object. Only needed for +// // incomplete types. +// int VBTableOffset; +// }; +std::pair<unsigned, unsigned> +MemberPointerType::getMSMemberPointerSlots() const { + const CXXRecordDecl *RD = this->getClass()->getAsCXXRecordDecl(); + MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); + unsigned Ptrs; + unsigned Ints = 0; + if (this->isMemberFunctionPointer()) { + // Member function pointers are a struct of a function pointer followed by a + // variable number of ints depending on the inheritance model used. The + // function pointer is a real function if it is non-virtual and a vftable + // slot thunk if it is virtual. The ints select the object base passed for + // the 'this' pointer. + Ptrs = 1; // First slot is always a function pointer. + switch (Inheritance) { + case MSIM_Unspecified: ++Ints; // VBTableOffset + case MSIM_Virtual: ++Ints; // VirtualBaseAdjustmentOffset + case MSIM_Multiple: ++Ints; // NonVirtualBaseAdjustment + case MSIM_Single: break; // Nothing + } + } else { + // Data pointers are an aggregate of ints. The first int is an offset + // followed by vbtable-related offsets. + Ptrs = 0; + switch (Inheritance) { + case MSIM_Unspecified: ++Ints; // VBTableOffset + case MSIM_Virtual: ++Ints; // VirtualBaseAdjustmentOffset + case MSIM_Multiple: // Nothing + case MSIM_Single: ++Ints; // Field offset + } + } + return std::make_pair(Ptrs, Ints); +} + +std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign( + const MemberPointerType *MPT) const { + const TargetInfo &Target = Context.getTargetInfo(); + assert(Target.getTriple().getArch() == llvm::Triple::x86 || + Target.getTriple().getArch() == llvm::Triple::x86_64); + unsigned Ptrs, Ints; + llvm::tie(Ptrs, Ints) = MPT->getMSMemberPointerSlots(); + // The nominal struct is laid out with pointers followed by ints and aligned + // to a pointer width if any are present and an int width otherwise. + unsigned PtrSize = Target.getPointerWidth(0); + unsigned IntSize = Target.getIntWidth(); + uint64_t Width = Ptrs * PtrSize + Ints * IntSize; + unsigned Align = Ptrs > 0 ? Target.getPointerAlign(0) : Target.getIntAlign(); + Width = llvm::RoundUpToAlignment(Width, Align); + return std::make_pair(Width, Align); } CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) { diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp index 5d5b83d..40f8730 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp @@ -13,6 +13,7 @@ #include "clang/AST/Mangle.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" @@ -21,19 +22,31 @@ #include "clang/AST/ExprCXX.h" #include "clang/Basic/ABI.h" #include "clang/Basic/DiagnosticOptions.h" - #include <map> using namespace clang; namespace { +static const FunctionDecl *getStructor(const FunctionDecl *fn) { + if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate()) + return ftd->getTemplatedDecl(); + + return fn; +} + /// MicrosoftCXXNameMangler - Manage the mangling of a single name for the /// Microsoft Visual C++ ABI. class MicrosoftCXXNameMangler { MangleContext &Context; raw_ostream &Out; + /// The "structor" is the top-level declaration being mangled, if + /// that's not a template specialization; otherwise it's the pattern + /// for that specialization. + const NamedDecl *Structor; + unsigned StructorType; + // FIXME: audit the performance of BackRefMap as it might do way too many // copying of strings. typedef std::map<std::string, unsigned> BackRefMap; @@ -47,7 +60,15 @@ class MicrosoftCXXNameMangler { public: MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_) - : Context(C), Out(Out_), UseNameBackReferences(true) { } + : Context(C), Out(Out_), + Structor(0), StructorType(-1), + UseNameBackReferences(true) { } + + MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_, + const CXXDestructorDecl *D, CXXDtorType Type) + : Context(C), Out(Out_), + Structor(getStructor(D)), StructorType(Type), + UseNameBackReferences(true) { } raw_ostream &getStream() const { return Out; } @@ -68,12 +89,13 @@ private: void mangleSourceName(const IdentifierInfo *II); void manglePostfix(const DeclContext *DC, bool NoFunction=false); void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc); + void mangleCXXDtorType(CXXDtorType T); void mangleQualifiers(Qualifiers Quals, bool IsMember); void manglePointerQualifiers(Qualifiers Quals); void mangleUnscopedTemplateName(const TemplateDecl *ND); void mangleTemplateInstantiationName(const TemplateDecl *TD, - const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs); + const TemplateArgumentList &TemplateArgs); void mangleObjCMethodName(const ObjCMethodDecl *MD); void mangleLocalName(const FunctionDecl *FD); @@ -96,12 +118,12 @@ private: void mangleExtraDimensions(QualType T); void mangleFunctionClass(const FunctionDecl *FD); void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false); - void mangleIntegerLiteral(QualType T, const llvm::APSInt &Number); + void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean); void mangleExpression(const Expr *E); void mangleThrowSpecification(const FunctionProtoType *T); - void mangleTemplateArgs( - const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs); + void mangleTemplateArgs(const TemplateDecl *TD, + const TemplateArgumentList &TemplateArgs); }; @@ -345,47 +367,19 @@ void MicrosoftCXXNameMangler::mangleNumber(const llvm::APSInt &Value) { } static const TemplateDecl * -isTemplate(const NamedDecl *ND, - SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) { +isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { // Check if we have a function template. if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){ if (const TemplateDecl *TD = FD->getPrimaryTemplate()) { - if (FD->getTemplateSpecializationArgsAsWritten()) { - const ASTTemplateArgumentListInfo *ArgList = - FD->getTemplateSpecializationArgsAsWritten(); - TemplateArgs.append(ArgList->getTemplateArgs(), - ArgList->getTemplateArgs() + - ArgList->NumTemplateArgs); - } else { - const TemplateArgumentList *ArgList = - FD->getTemplateSpecializationArgs(); - TemplateArgumentListInfo LI; - for (unsigned i = 0, e = ArgList->size(); i != e; ++i) - TemplateArgs.push_back(TemplateArgumentLoc(ArgList->get(i), - FD->getTypeSourceInfo())); - } + TemplateArgs = FD->getTemplateSpecializationArgs(); return TD; } } // Check if we have a class template. if (const ClassTemplateSpecializationDecl *Spec = - dyn_cast<ClassTemplateSpecializationDecl>(ND)) { - TypeSourceInfo *TSI = Spec->getTypeAsWritten(); - if (TSI) { - TemplateSpecializationTypeLoc TSTL = - cast<TemplateSpecializationTypeLoc>(TSI->getTypeLoc()); - TemplateArgumentListInfo LI(TSTL.getLAngleLoc(), TSTL.getRAngleLoc()); - for (unsigned i = 0, e = TSTL.getNumArgs(); i != e; ++i) - TemplateArgs.push_back(TSTL.getArgLoc(i)); - } else { - TemplateArgumentListInfo LI; - const TemplateArgumentList &ArgList = - Spec->getTemplateArgs(); - for (unsigned i = 0, e = ArgList.size(); i != e; ++i) - TemplateArgs.push_back(TemplateArgumentLoc(ArgList[i], - TemplateArgumentLocInfo())); - } + dyn_cast<ClassTemplateSpecializationDecl>(ND)) { + TemplateArgs = &Spec->getTemplateArgs(); return Spec->getSpecializedTemplate(); } @@ -399,8 +393,9 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // ::= <ctor-dtor-name> // ::= <source-name> // ::= <template-name> - SmallVector<TemplateArgumentLoc, 2> TemplateArgs; + // Check if we have a template. + const TemplateArgumentList *TemplateArgs = 0; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { // We have a template. // Here comes the tricky thing: if we need to mangle something like @@ -430,7 +425,7 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, Found = NameBackReferences.find(BackReferenceKey); } if (!UseNameBackReferences || Found == NameBackReferences.end()) { - mangleTemplateInstantiationName(TD, TemplateArgs); + mangleTemplateInstantiationName(TD, *TemplateArgs); if (UseNameBackReferences && NameBackReferences.size() < 10) { size_t Size = NameBackReferences.size(); NameBackReferences[BackReferenceKey] = Size; @@ -453,7 +448,7 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) { if (NS->isAnonymousNamespace()) { - Out << "?A"; + Out << "?A@"; break; } } @@ -481,11 +476,22 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, llvm_unreachable("Can't mangle Objective-C selector names here!"); case DeclarationName::CXXConstructorName: + if (ND == Structor) { + assert(StructorType == Ctor_Complete && + "Should never be asked to mangle a ctor other than complete"); + } Out << "?0"; break; case DeclarationName::CXXDestructorName: - Out << "?1"; + if (ND == Structor) + // If the named decl is the C++ destructor we're mangling, + // use the type we were given. + mangleCXXDtorType(static_cast<CXXDtorType>(StructorType)); + else + // Otherwise, use the complete destructor name. This is relevant if a + // class with a destructor is declared within a destructor. + mangleCXXDtorType(Dtor_Complete); break; case DeclarationName::CXXConversionFunctionName: @@ -543,6 +549,23 @@ void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC, } } +void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) { + switch (T) { + case Dtor_Deleting: + Out << "?_G"; + return; + case Dtor_Base: + // FIXME: We should be asked to mangle base dtors. + // However, fixing this would require larger changes to the CodeGenModule. + // Please put llvm_unreachable here when CGM is changed. + // For now, just mangle a base dtor the same way as a complete dtor... + case Dtor_Complete: + Out << "?1"; + return; + } + llvm_unreachable("Unsupported dtor type?"); +} + void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc) { switch (OO) { @@ -736,19 +759,23 @@ void MicrosoftCXXNameMangler::mangleLocalName(const FunctionDecl *FD) { void MicrosoftCXXNameMangler::mangleTemplateInstantiationName( const TemplateDecl *TD, - const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) { + const TemplateArgumentList &TemplateArgs) { // <template-name> ::= <unscoped-template-name> <template-args> // ::= <substitution> // Always start with the unqualified name. // Templates have their own context for back references. - BackRefMap TemplateContext; - NameBackReferences.swap(TemplateContext); + ArgBackRefMap OuterArgsContext; + BackRefMap OuterTemplateContext; + NameBackReferences.swap(OuterTemplateContext); + TypeBackReferences.swap(OuterArgsContext); mangleUnscopedTemplateName(TD); - mangleTemplateArgs(TemplateArgs); + mangleTemplateArgs(TD, TemplateArgs); - NameBackReferences.swap(TemplateContext); + // Restore the previous back reference contexts. + NameBackReferences.swap(OuterTemplateContext); + TypeBackReferences.swap(OuterArgsContext); } void @@ -759,13 +786,13 @@ MicrosoftCXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *TD) { } void -MicrosoftCXXNameMangler::mangleIntegerLiteral(QualType T, - const llvm::APSInt &Value) { +MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value, + bool IsBoolean) { // <integer-literal> ::= $0 <number> Out << "$0"; // Make sure booleans are encoded as 0/1. - if (T->isBooleanType()) - Out << (Value.getBoolValue() ? "0" : "A@"); + if (IsBoolean && Value.getBoolValue()) + mangleNumber(1); else mangleNumber(Value); } @@ -775,7 +802,7 @@ MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { // See if this is a constant expression. llvm::APSInt Value; if (E->isIntegerConstantExpr(Value, Context.getASTContext())) { - mangleIntegerLiteral(E->getType(), Value); + mangleIntegerLiteral(Value, E->getType()->isBooleanType()); return; } @@ -788,39 +815,42 @@ MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { } void -MicrosoftCXXNameMangler::mangleTemplateArgs( - const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) { +MicrosoftCXXNameMangler::mangleTemplateArgs(const TemplateDecl *TD, + const TemplateArgumentList &TemplateArgs) { // <template-args> ::= {<type> | <integer-literal>}+ @ unsigned NumTemplateArgs = TemplateArgs.size(); for (unsigned i = 0; i < NumTemplateArgs; ++i) { - const TemplateArgumentLoc &TAL = TemplateArgs[i]; - const TemplateArgument &TA = TAL.getArgument(); + const TemplateArgument &TA = TemplateArgs[i]; switch (TA.getKind()) { case TemplateArgument::Null: llvm_unreachable("Can't mangle null template arguments!"); case TemplateArgument::Type: - mangleType(TA.getAsType(), TAL.getSourceRange()); + mangleType(TA.getAsType(), SourceRange()); + break; + case TemplateArgument::Declaration: + mangle(cast<NamedDecl>(TA.getAsDecl()), "$1?"); break; case TemplateArgument::Integral: - mangleIntegerLiteral(TA.getIntegralType(), TA.getAsIntegral()); + mangleIntegerLiteral(TA.getAsIntegral(), + TA.getIntegralType()->isBooleanType()); break; case TemplateArgument::Expression: mangleExpression(TA.getAsExpr()); break; case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: - case TemplateArgument::Declaration: case TemplateArgument::NullPtr: case TemplateArgument::Pack: { // Issue a diagnostic. DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this %select{ERROR|ERROR|pointer/reference|nullptr|" - "integral|template|template pack expansion|ERROR|parameter pack}0 " - "template argument yet"); - Diags.Report(TAL.getLocation(), DiagID) + "cannot mangle template argument %0 of kind %select{ERROR|ERROR|" + "pointer/reference|nullptr|integral|template|template pack expansion|" + "ERROR|parameter pack}1 yet"); + Diags.Report(TD->getLocation(), DiagID) + << i + 1 << TA.getKind() - << TAL.getSourceRange(); + << TD->getSourceRange(); } } } @@ -1048,6 +1078,15 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, case BuiltinType::ObjCId: Out << "PAUobjc_object@@"; break; case BuiltinType::ObjCClass: Out << "PAUobjc_class@@"; break; case BuiltinType::ObjCSel: Out << "PAUobjc_selector@@"; break; + + case BuiltinType::OCLImage1d: Out << "PAUocl_image1d@@"; break; + case BuiltinType::OCLImage1dArray: Out << "PAUocl_image1darray@@"; break; + case BuiltinType::OCLImage1dBuffer: Out << "PAUocl_image1dbuffer@@"; break; + case BuiltinType::OCLImage2d: Out << "PAUocl_image2d@@"; break; + case BuiltinType::OCLImage2dArray: Out << "PAUocl_image2darray@@"; break; + case BuiltinType::OCLImage3d: Out << "PAUocl_image3d@@"; break; + case BuiltinType::OCLSampler: Out << "PAUocl_sampler@@"; break; + case BuiltinType::OCLEvent: Out << "PAUocl_event@@"; break; case BuiltinType::NullPtr: Out << "$$T"; break; @@ -1096,9 +1135,18 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionType *T, // <return-type> ::= <type> // ::= @ # structors (they have no declared return type) - if (IsStructor) + if (IsStructor) { + if (isa<CXXDestructorDecl>(D) && D == Structor && + StructorType == Dtor_Deleting) { + // The scalar deleting destructor takes an extra int argument. + // However, the FunctionType generated has 0 arguments. + // FIXME: This is a temporary hack. + // Maybe should fix the FunctionType creation instead? + Out << "PAXI@Z"; + return; + } Out << '@'; - else { + } else { QualType Result = Proto->getResultType(); const Type* RT = Result.getTypePtr(); if (!RT->isAnyPointerType() && !RT->isReferenceType()) { @@ -1471,12 +1519,38 @@ void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, void MicrosoftCXXNameMangler::mangleType(const VectorType *T, SourceRange Range) { - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this vector type yet"); - Diags.Report(Range.getBegin(), DiagID) - << Range; + const BuiltinType *ET = T->getElementType()->getAs<BuiltinType>(); + assert(ET && "vectors with non-builtin elements are unsupported"); + uint64_t Width = getASTContext().getTypeSize(T); + // Pattern match exactly the typedefs in our intrinsic headers. Anything that + // doesn't match the Intel types uses a custom mangling below. + bool IntelVector = true; + if (Width == 64 && ET->getKind() == BuiltinType::LongLong) { + Out << "T__m64"; + } else if (Width == 128 || Width == 256) { + if (ET->getKind() == BuiltinType::Float) + Out << "T__m" << Width; + else if (ET->getKind() == BuiltinType::LongLong) + Out << "T__m" << Width << 'i'; + else if (ET->getKind() == BuiltinType::Double) + Out << "U__m" << Width << 'd'; + else + IntelVector = false; + } else { + IntelVector = false; + } + + if (!IntelVector) { + // The MS ABI doesn't have a special mangling for vector types, so we define + // our own mangling to handle uses of __vector_size__ on user-specified + // types, and for extensions like __v4sf. + Out << "T__clang_vec" << T->getNumElements() << '_'; + mangleType(ET, Range); + } + + Out << "@@"; } + void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); @@ -1697,7 +1771,7 @@ void MicrosoftMangleContext::mangleCXXCtor(const CXXConstructorDecl *D, void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, raw_ostream & Out) { - MicrosoftCXXNameMangler mangler(*this, Out); + MicrosoftCXXNameMangler mangler(*this, Out, D, Type); mangler.mangle(D); } void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *VD, diff --git a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp index 0837509..a862630 100644 --- a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp @@ -67,7 +67,7 @@ Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const { return NSStringSelectors[MK]; } -llvm::Optional<NSAPI::NSStringMethodKind> +Optional<NSAPI::NSStringMethodKind> NSAPI::getNSStringMethodKind(Selector Sel) const { for (unsigned i = 0; i != NumNSStringMethods; ++i) { NSStringMethodKind MK = NSStringMethodKind(i); @@ -75,7 +75,7 @@ NSAPI::getNSStringMethodKind(Selector Sel) const { return MK; } - return llvm::Optional<NSStringMethodKind>(); + return None; } Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const { @@ -126,15 +126,14 @@ Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const { return NSArraySelectors[MK]; } -llvm::Optional<NSAPI::NSArrayMethodKind> -NSAPI::getNSArrayMethodKind(Selector Sel) { +Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) { for (unsigned i = 0; i != NumNSArrayMethods; ++i) { NSArrayMethodKind MK = NSArrayMethodKind(i); if (Sel == getNSArraySelector(MK)) return MK; } - return llvm::Optional<NSArrayMethodKind>(); + return None; } Selector NSAPI::getNSDictionarySelector( @@ -186,6 +185,14 @@ Selector NSAPI::getNSDictionarySelector( Sel = Ctx.Selectors.getUnarySelector( &Ctx.Idents.get("initWithObjectsAndKeys")); break; + case NSDict_initWithObjectsForKeys: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("initWithObjects"), + &Ctx.Idents.get("forKeys") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } case NSDict_objectForKey: Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey")); break; @@ -204,7 +211,7 @@ Selector NSAPI::getNSDictionarySelector( return NSDictionarySelectors[MK]; } -llvm::Optional<NSAPI::NSDictionaryMethodKind> +Optional<NSAPI::NSDictionaryMethodKind> NSAPI::getNSDictionaryMethodKind(Selector Sel) { for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) { NSDictionaryMethodKind MK = NSDictionaryMethodKind(i); @@ -212,7 +219,7 @@ NSAPI::getNSDictionaryMethodKind(Selector Sel) { return MK; } - return llvm::Optional<NSDictionaryMethodKind>(); + return None; } Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, @@ -267,7 +274,7 @@ Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, return Sels[MK]; } -llvm::Optional<NSAPI::NSNumberLiteralMethodKind> +Optional<NSAPI::NSNumberLiteralMethodKind> NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const { for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) { NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i); @@ -275,14 +282,14 @@ NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const { return MK; } - return llvm::Optional<NSNumberLiteralMethodKind>(); + return None; } -llvm::Optional<NSAPI::NSNumberLiteralMethodKind> +Optional<NSAPI::NSNumberLiteralMethodKind> NSAPI::getNSNumberFactoryMethodKind(QualType T) const { const BuiltinType *BT = T->getAs<BuiltinType>(); if (!BT) - return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>(); + return None; const TypedefType *TDT = T->getAs<TypedefType>(); if (TDT) { @@ -337,6 +344,14 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const { case BuiltinType::ObjCClass: case BuiltinType::ObjCId: case BuiltinType::ObjCSel: + case BuiltinType::OCLImage1d: + case BuiltinType::OCLImage1dArray: + case BuiltinType::OCLImage1dBuffer: + case BuiltinType::OCLImage2d: + case BuiltinType::OCLImage2dArray: + case BuiltinType::OCLImage3d: + case BuiltinType::OCLSampler: + case BuiltinType::OCLEvent: case BuiltinType::BoundMember: case BuiltinType::Dependent: case BuiltinType::Overload: @@ -348,7 +363,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const { break; } - return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>(); + return None; } /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c. diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp index 49b119b..79cc21a 100644 --- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp @@ -57,7 +57,8 @@ NestedNameSpecifier::Create(const ASTContext &Context, NestedNameSpecifier * NestedNameSpecifier::Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, NamespaceDecl *NS) { + NestedNameSpecifier *Prefix, + const NamespaceDecl *NS) { assert(NS && "Namespace cannot be NULL"); assert((!Prefix || (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) && @@ -65,7 +66,7 @@ NestedNameSpecifier::Create(const ASTContext &Context, NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); Mockup.Prefix.setInt(StoredNamespaceOrAlias); - Mockup.Specifier = NS; + Mockup.Specifier = const_cast<NamespaceDecl *>(NS); return FindOrInsert(Context, Mockup); } @@ -248,7 +249,6 @@ NestedNameSpecifier::print(raw_ostream &OS, // Fall through to print the type. case TypeSpec: { - std::string TypeStr; const Type *T = getAsType(); PrintingPolicy InnerPolicy(Policy); @@ -270,15 +270,12 @@ NestedNameSpecifier::print(raw_ostream &OS, SpecType->getTemplateName().print(OS, InnerPolicy, true); // Print the template argument list. - TypeStr = TemplateSpecializationType::PrintTemplateArgumentList( - SpecType->getArgs(), - SpecType->getNumArgs(), - InnerPolicy); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, SpecType->getArgs(), SpecType->getNumArgs(), InnerPolicy); } else { // Print the type normally - TypeStr = QualType(T, 0).getAsString(InnerPolicy); + QualType(T, 0).print(OS, InnerPolicy); } - OS << TypeStr; break; } } diff --git a/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp b/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp index 80b6272..f2386a5 100644 --- a/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp @@ -10,11 +10,11 @@ #include "clang/AST/RawCommentList.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Comment.h" -#include "clang/AST/CommentLexer.h" #include "clang/AST/CommentBriefParser.h" -#include "clang/AST/CommentSema.h" -#include "clang/AST/CommentParser.h" #include "clang/AST/CommentCommandTraits.h" +#include "clang/AST/CommentLexer.h" +#include "clang/AST/CommentParser.h" +#include "clang/AST/CommentSema.h" #include "llvm/ADT/STLExtras.h" using namespace clang; diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp index 2ae0aab..f6cfe63 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp @@ -75,10 +75,9 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, #ifndef NDEBUG if (const CXXRecordDecl *PrimaryBase = getPrimaryBase()) { if (isPrimaryBaseVirtual()) { - // Microsoft ABI doesn't have primary virtual base - if (Ctx.getTargetInfo().getCXXABI() != CXXABI_Microsoft) { - assert(getVBaseClassOffset(PrimaryBase).isZero() && - "Primary virtual base must be at offset 0!"); + if (Ctx.getTargetInfo().getCXXABI().hasPrimaryVBases()) { + assert(getVBaseClassOffset(PrimaryBase).isZero() && + "Primary virtual base must be at offset 0!"); } } else { assert(getBaseClassOffset(PrimaryBase).isZero() && diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp index 4dfffc4..42c3ba3 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/RecordLayout.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/CXXInheritance.h" @@ -14,13 +15,12 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" -#include "clang/AST/RecordLayout.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/SemaDiagnostic.h" -#include "llvm/Support/Format.h" #include "llvm/ADT/SmallSet.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/CrashRecoveryContext.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/MathExtras.h" using namespace clang; @@ -676,8 +676,12 @@ protected: bool FieldPacked, const FieldDecl *D); void LayoutBitField(const FieldDecl *D); + TargetCXXABI getCXXABI() const { + return Context.getTargetInfo().getCXXABI(); + } + bool isMicrosoftCXXABI() const { - return Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft; + return getCXXABI().isMicrosoft(); } void MSLayoutVirtualBases(const CXXRecordDecl *RD); @@ -791,8 +795,6 @@ protected: RecordLayoutBuilder(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION; void operator=(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION; -public: - static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD); }; } // end anonymous namespace @@ -2343,8 +2345,8 @@ void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset, << D->getIdentifier(); } -const CXXMethodDecl * -RecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) { +static const CXXMethodDecl *computeKeyFunction(ASTContext &Context, + const CXXRecordDecl *RD) { // If a class isn't polymorphic it doesn't have a key function. if (!RD->isPolymorphic()) return 0; @@ -2362,6 +2364,9 @@ RecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) { TSK == TSK_ExplicitInstantiationDefinition) return 0; + bool allowInlineFunctions = + Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline(); + for (CXXRecordDecl::method_iterator I = RD->method_begin(), E = RD->method_end(); I != E; ++I) { const CXXMethodDecl *MD = *I; @@ -2387,6 +2392,13 @@ RecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) { if (!MD->isUserProvided()) continue; + // In certain ABIs, ignore functions with out-of-line inline definitions. + if (!allowInlineFunctions) { + const FunctionDecl *Def; + if (MD->hasBody(Def) && Def->isInlineSpecified()) + continue; + } + // We found it. return MD; } @@ -2399,6 +2411,48 @@ RecordLayoutBuilder::Diag(SourceLocation Loc, unsigned DiagID) { return Context.getDiagnostics().Report(Loc, DiagID); } +/// Does the target C++ ABI require us to skip over the tail-padding +/// of the given class (considering it as a base class) when allocating +/// objects? +static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD) { + switch (ABI.getTailPaddingUseRules()) { + case TargetCXXABI::AlwaysUseTailPadding: + return false; + + case TargetCXXABI::UseTailPaddingUnlessPOD03: + // FIXME: To the extent that this is meant to cover the Itanium ABI + // rules, we should implement the restrictions about over-sized + // bitfields: + // + // http://mentorembedded.github.com/cxx-abi/abi.html#POD : + // In general, a type is considered a POD for the purposes of + // layout if it is a POD type (in the sense of ISO C++ + // [basic.types]). However, a POD-struct or POD-union (in the + // sense of ISO C++ [class]) with a bitfield member whose + // declared width is wider than the declared type of the + // bitfield is not a POD for the purpose of layout. Similarly, + // an array type is not a POD for the purpose of layout if the + // element type of the array is not a POD for the purpose of + // layout. + // + // Where references to the ISO C++ are made in this paragraph, + // the Technical Corrigendum 1 version of the standard is + // intended. + return RD->isPOD(); + + case TargetCXXABI::UseTailPaddingUnlessPOD11: + // This is equivalent to RD->getTypeForDecl().isCXX11PODType(), + // but with a lot of abstraction penalty stripped off. This does + // assume that these properties are set correctly even in C++98 + // mode; fortunately, that is true because we want to assign + // consistently semantics to the type-traits intrinsics (or at + // least as many of them as possible). + return RD->isTrivial() && RD->isStandardLayout(); + } + + llvm_unreachable("bad tail-padding use kind"); +} + /// getASTRecordLayout - Get or compute information about the layout of the /// specified record (struct/union/class), which indicates its size and field /// position information. @@ -2443,18 +2497,17 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { Builder.Layout(RD); } - // FIXME: This is not always correct. See the part about bitfields at - // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info. - // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout. - // This does not affect the calculations of MSVC layouts - bool IsPODForThePurposeOfLayout = - (!Builder.isMicrosoftCXXABI() && cast<CXXRecordDecl>(D)->isPOD()); + // In certain situations, we are allowed to lay out objects in the + // tail-padding of base classes. This is ABI-dependent. + // FIXME: this should be stored in the record layout. + bool skipTailPadding = + mustSkipTailPadding(getTargetInfo().getCXXABI(), cast<CXXRecordDecl>(D)); // FIXME: This should be done in FinalizeLayout. CharUnits DataSize = - IsPODForThePurposeOfLayout ? Builder.getSize() : Builder.getDataSize(); + skipTailPadding ? Builder.getSize() : Builder.getDataSize(); CharUnits NonVirtualSize = - IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize; + skipTailPadding ? DataSize : Builder.NonVirtualSize; NewEntry = new (*this) ASTRecordLayout(*this, Builder.getSize(), @@ -2492,15 +2545,37 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { return *NewEntry; } -const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) { +const CXXMethodDecl *ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD) { + assert(RD->getDefinition() && "Cannot get key function for forward decl!"); RD = cast<CXXRecordDecl>(RD->getDefinition()); - assert(RD && "Cannot get key function for forward declarations!"); - const CXXMethodDecl *&Entry = KeyFunctions[RD]; - if (!Entry) - Entry = RecordLayoutBuilder::ComputeKeyFunction(RD); + const CXXMethodDecl *&entry = KeyFunctions[RD]; + if (!entry) { + entry = computeKeyFunction(*this, RD); + } - return Entry; + return entry; +} + +void ASTContext::setNonKeyFunction(const CXXMethodDecl *method) { + assert(method == method->getFirstDeclaration() && + "not working with method declaration from class definition"); + + // Look up the cache entry. Since we're working with the first + // declaration, its parent must be the class definition, which is + // the correct key for the KeyFunctions hash. + llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*>::iterator + i = KeyFunctions.find(method->getParent()); + + // If it's not cached, there's nothing to do. + if (i == KeyFunctions.end()) return; + + // If it is cached, check whether it's the target method, and if so, + // remove it from the cache. + if (i->second == method) { + // FIXME: remember that we did this for module / chained PCH state? + KeyFunctions.erase(i); + } } static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD) { @@ -2577,6 +2652,11 @@ static void PrintOffset(raw_ostream &OS, OS.indent(IndentLevel * 2); } +static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel) { + OS << " | "; + OS.indent(IndentLevel * 2); +} + static void DumpCXXRecordLayout(raw_ostream &OS, const CXXRecordDecl *RD, const ASTContext &C, CharUnits Offset, @@ -2601,7 +2681,7 @@ static void DumpCXXRecordLayout(raw_ostream &OS, // Vtable pointer. if (RD->isDynamicClass() && !PrimaryBase && - C.getTargetInfo().getCXXABI() != CXXABI_Microsoft) { + !C.getTargetInfo().getCXXABI().isMicrosoft()) { PrintOffset(OS, Offset, IndentLevel); OS << '(' << *RD << " vtable pointer)\n"; } @@ -2680,11 +2760,14 @@ static void DumpCXXRecordLayout(raw_ostream &OS, /*IncludeVirtualBases=*/false); } - OS << " sizeof=" << Layout.getSize().getQuantity(); + PrintIndentNoOffset(OS, IndentLevel - 1); + OS << "[sizeof=" << Layout.getSize().getQuantity(); OS << ", dsize=" << Layout.getDataSize().getQuantity(); OS << ", align=" << Layout.getAlignment().getQuantity() << '\n'; - OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity(); - OS << ", nvalign=" << Layout.getNonVirtualAlign().getQuantity() << '\n'; + + PrintIndentNoOffset(OS, IndentLevel - 1); + OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity(); + OS << ", nvalign=" << Layout.getNonVirtualAlign().getQuantity() << "]\n"; OS << '\n'; } diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp index eafcf92..2ae5a12 100644 --- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp @@ -11,15 +11,17 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/Stmt.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/Type.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/ASTDiagnostic.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Token.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -46,6 +48,16 @@ static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) { return StmtClassInfo[E]; } +void *Stmt::operator new(size_t bytes, ASTContext& C, + unsigned alignment) throw() { + return ::operator new(bytes, C, alignment); +} + +void *Stmt::operator new(size_t bytes, ASTContext* C, + unsigned alignment) throw() { + return ::operator new(bytes, *C, alignment); +} + const char *Stmt::getStmtClassName() const { return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name; } @@ -131,18 +143,28 @@ namespace { return bad(); } - typedef SourceRange getSourceRange_t() const; - template <class T> good implements_getSourceRange(getSourceRange_t T::*) { + typedef SourceLocation getLocStart_t() const; + template <class T> good implements_getLocStart(getLocStart_t T::*) { return good(); } - static inline bad implements_getSourceRange(getSourceRange_t Stmt::*) { + static inline bad implements_getLocStart(getLocStart_t Stmt::*) { + return bad(); + } + + typedef SourceLocation getLocEnd_t() const; + template <class T> good implements_getLocEnd(getLocEnd_t T::*) { + return good(); + } + static inline bad implements_getLocEnd(getLocEnd_t Stmt::*) { return bad(); } #define ASSERT_IMPLEMENTS_children(type) \ (void) sizeof(is_good(implements_children(&type::children))) -#define ASSERT_IMPLEMENTS_getSourceRange(type) \ - (void) sizeof(is_good(implements_getSourceRange(&type::getSourceRange))) +#define ASSERT_IMPLEMENTS_getLocStart(type) \ + (void) sizeof(is_good(implements_getLocStart(&type::getLocStart))) +#define ASSERT_IMPLEMENTS_getLocEnd(type) \ + (void) sizeof(is_good(implements_getLocEnd(&type::getLocEnd))) } /// Check whether the various Stmt classes implement their member @@ -151,7 +173,8 @@ static inline void check_implementations() { #define ABSTRACT_STMT(type) #define STMT(type, base) \ ASSERT_IMPLEMENTS_children(type); \ - ASSERT_IMPLEMENTS_getSourceRange(type); + ASSERT_IMPLEMENTS_getLocStart(type); \ + ASSERT_IMPLEMENTS_getLocEnd(type); #include "clang/AST/StmtNodes.inc" } @@ -167,67 +190,51 @@ Stmt::child_range Stmt::children() { llvm_unreachable("unknown statement kind!"); } -SourceRange Stmt::getSourceRange() const { - switch (getStmtClass()) { - case Stmt::NoStmtClass: llvm_unreachable("statement without class"); -#define ABSTRACT_STMT(type) -#define STMT(type, base) \ - case Stmt::type##Class: \ - return static_cast<const type*>(this)->getSourceRange(); -#include "clang/AST/StmtNodes.inc" - } - llvm_unreachable("unknown statement kind!"); -} - // Amusing macro metaprogramming hack: check whether a class provides -// a more specific implementation of getLocStart() and getLocEnd(). +// a more specific implementation of getSourceRange. // // See also Expr.cpp:getExprLoc(). namespace { /// This implementation is used when a class provides a custom - /// implementation of getLocStart. + /// implementation of getSourceRange. template <class S, class T> - SourceLocation getLocStartImpl(const Stmt *stmt, - SourceLocation (T::*v)() const) { - return static_cast<const S*>(stmt)->getLocStart(); + SourceRange getSourceRangeImpl(const Stmt *stmt, + SourceRange (T::*v)() const) { + return static_cast<const S*>(stmt)->getSourceRange(); } /// This implementation is used when a class doesn't provide a custom - /// implementation of getLocStart. Overload resolution should pick it over + /// implementation of getSourceRange. Overload resolution should pick it over /// the implementation above because it's more specialized according to /// function template partial ordering. template <class S> - SourceLocation getLocStartImpl(const Stmt *stmt, - SourceLocation (Stmt::*v)() const) { - return static_cast<const S*>(stmt)->getSourceRange().getBegin(); - } - - /// This implementation is used when a class provides a custom - /// implementation of getLocEnd. - template <class S, class T> - SourceLocation getLocEndImpl(const Stmt *stmt, - SourceLocation (T::*v)() const) { - return static_cast<const S*>(stmt)->getLocEnd(); + SourceRange getSourceRangeImpl(const Stmt *stmt, + SourceRange (Stmt::*v)() const) { + return SourceRange(static_cast<const S*>(stmt)->getLocStart(), + static_cast<const S*>(stmt)->getLocEnd()); } +} - /// This implementation is used when a class doesn't provide a custom - /// implementation of getLocEnd. Overload resolution should pick it over - /// the implementation above because it's more specialized according to - /// function template partial ordering. - template <class S> - SourceLocation getLocEndImpl(const Stmt *stmt, - SourceLocation (Stmt::*v)() const) { - return static_cast<const S*>(stmt)->getSourceRange().getEnd(); +SourceRange Stmt::getSourceRange() const { + switch (getStmtClass()) { + case Stmt::NoStmtClass: llvm_unreachable("statement without class"); +#define ABSTRACT_STMT(type) +#define STMT(type, base) \ + case Stmt::type##Class: \ + return getSourceRangeImpl<type>(this, &type::getSourceRange); +#include "clang/AST/StmtNodes.inc" } + llvm_unreachable("unknown statement kind!"); } SourceLocation Stmt::getLocStart() const { +// llvm::errs() << "getLocStart() for " << getStmtClassName() << "\n"; switch (getStmtClass()) { case Stmt::NoStmtClass: llvm_unreachable("statement without class"); #define ABSTRACT_STMT(type) #define STMT(type, base) \ case Stmt::type##Class: \ - return getLocStartImpl<type>(this, &type::getLocStart); + return static_cast<const type*>(this)->getLocStart(); #include "clang/AST/StmtNodes.inc" } llvm_unreachable("unknown statement kind"); @@ -239,26 +246,26 @@ SourceLocation Stmt::getLocEnd() const { #define ABSTRACT_STMT(type) #define STMT(type, base) \ case Stmt::type##Class: \ - return getLocEndImpl<type>(this, &type::getLocEnd); + return static_cast<const type*>(this)->getLocEnd(); #include "clang/AST/StmtNodes.inc" } llvm_unreachable("unknown statement kind"); } -CompoundStmt::CompoundStmt(ASTContext &C, Stmt **StmtStart, unsigned NumStmts, +CompoundStmt::CompoundStmt(ASTContext &C, ArrayRef<Stmt*> Stmts, SourceLocation LB, SourceLocation RB) : Stmt(CompoundStmtClass), LBracLoc(LB), RBracLoc(RB) { - CompoundStmtBits.NumStmts = NumStmts; - assert(CompoundStmtBits.NumStmts == NumStmts && + CompoundStmtBits.NumStmts = Stmts.size(); + assert(CompoundStmtBits.NumStmts == Stmts.size() && "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!"); - if (NumStmts == 0) { + if (Stmts.size() == 0) { Body = 0; return; } - Body = new (C) Stmt*[NumStmts]; - memcpy(Body, StmtStart, NumStmts * sizeof(*Body)); + Body = new (C) Stmt*[Stmts.size()]; + std::copy(Stmts.begin(), Stmts.end(), Body); } void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) { @@ -291,14 +298,6 @@ AttributedStmt *AttributedStmt::CreateEmpty(ASTContext &C, unsigned NumAttrs) { return new (Mem) AttributedStmt(EmptyShell(), NumAttrs); } -// This is defined here to avoid polluting Stmt.h with importing Expr.h -SourceRange ReturnStmt::getSourceRange() const { - if (RetExpr) - return SourceRange(RetLoc, RetExpr->getLocEnd()); - else - return SourceRange(RetLoc); -} - bool Stmt::hasImplicitControlFlow() const { switch (StmtBits.sClass) { default: @@ -541,7 +540,7 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, // Handle %x4 and %x[foo] by capturing x as the modifier character. char Modifier = '\0'; - if (isalpha(EscapedChar)) { + if (isLetter(EscapedChar)) { if (CurPtr == StrEnd) { // Premature end. DiagOffs = CurPtr-StrStart-1; return diag::err_asm_invalid_escape; @@ -550,12 +549,12 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, EscapedChar = *CurPtr++; } - if (isdigit(EscapedChar)) { + if (isDigit(EscapedChar)) { // %n - Assembler operand n unsigned N = 0; --CurPtr; - while (CurPtr != StrEnd && isdigit(*CurPtr)) + while (CurPtr != StrEnd && isDigit(*CurPtr)) N = N*10 + ((*CurPtr++)-'0'); unsigned NumOperands = @@ -762,26 +761,21 @@ ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(ASTContext &Context, return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally); } -SourceRange ObjCAtTryStmt::getSourceRange() const { - SourceLocation EndLoc; +SourceLocation ObjCAtTryStmt::getLocEnd() const { if (HasFinally) - EndLoc = getFinallyStmt()->getLocEnd(); - else if (NumCatchStmts) - EndLoc = getCatchStmt(NumCatchStmts - 1)->getLocEnd(); - else - EndLoc = getTryBody()->getLocEnd(); - - return SourceRange(AtTryLoc, EndLoc); + return getFinallyStmt()->getLocEnd(); + if (NumCatchStmts) + return getCatchStmt(NumCatchStmts - 1)->getLocEnd(); + return getTryBody()->getLocEnd(); } CXXTryStmt *CXXTryStmt::Create(ASTContext &C, SourceLocation tryLoc, - Stmt *tryBlock, Stmt **handlers, - unsigned numHandlers) { + Stmt *tryBlock, ArrayRef<Stmt*> handlers) { std::size_t Size = sizeof(CXXTryStmt); - Size += ((numHandlers + 1) * sizeof(Stmt)); + Size += ((handlers.size() + 1) * sizeof(Stmt)); void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>()); - return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers, numHandlers); + return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers); } CXXTryStmt *CXXTryStmt::Create(ASTContext &C, EmptyShell Empty, @@ -794,11 +788,11 @@ CXXTryStmt *CXXTryStmt::Create(ASTContext &C, EmptyShell Empty, } CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, - Stmt **handlers, unsigned numHandlers) - : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(numHandlers) { + ArrayRef<Stmt*> handlers) + : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(handlers.size()) { Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); Stmts[0] = tryBlock; - std::copy(handlers, handlers + NumHandlers, Stmts + 1); + std::copy(handlers.begin(), handlers.end(), Stmts + 1); } CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEndStmt, diff --git a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp deleted file mode 100644 index fbc990f..0000000 --- a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp +++ /dev/null @@ -1,760 +0,0 @@ -//===--- StmtDumper.cpp - Dumping implementation for Stmt ASTs ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the Stmt::dump method, which dumps out the -// AST in a form that exposes type details and other fields. -// -//===----------------------------------------------------------------------===// - -#include "clang/AST/StmtVisitor.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/PrettyPrinter.h" -#include "clang/Basic/SourceManager.h" -#include "llvm/Support/raw_ostream.h" -using namespace clang; - -//===----------------------------------------------------------------------===// -// StmtDumper Visitor -//===----------------------------------------------------------------------===// - -namespace { - class StmtDumper : public StmtVisitor<StmtDumper> { - SourceManager *SM; - raw_ostream &OS; - unsigned IndentLevel; - bool IsFirstLine; - - /// MaxDepth - When doing a normal dump (not dumpAll) we only want to dump - /// the first few levels of an AST. This keeps track of how many ast levels - /// are left. - unsigned MaxDepth; - - /// LastLocFilename/LastLocLine - Keep track of the last location we print - /// out so that we can print out deltas from then on out. - const char *LastLocFilename; - unsigned LastLocLine; - - class IndentScope { - StmtDumper &Dumper; - public: - IndentScope(StmtDumper &Dumper) : Dumper(Dumper) { - Dumper.indent(); - } - ~IndentScope() { - Dumper.unindent(); - } - }; - - public: - StmtDumper(SourceManager *sm, raw_ostream &os, unsigned maxDepth) - : SM(sm), OS(os), IndentLevel(0), IsFirstLine(true), MaxDepth(maxDepth) { - LastLocFilename = ""; - LastLocLine = ~0U; - } - - ~StmtDumper() { - OS << "\n"; - } - - void DumpSubTree(Stmt *S) { - // Prune the recursion if not using dump all. - if (MaxDepth == 0) return; - - IndentScope Indent(*this); - - if (!S) { - OS << "<<<NULL>>>"; - return; - } - - if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) { - VisitDeclStmt(DS); - return; - } - - Visit(S); - for (Stmt::child_range CI = S->children(); CI; CI++) - DumpSubTree(*CI); - } - - void DumpDeclarator(Decl *D); - - void indent() { - if (IsFirstLine) - IsFirstLine = false; - else - OS << "\n"; - OS.indent(IndentLevel * 2); - OS << "("; - IndentLevel++; - } - - void unindent() { - OS << ")"; - IndentLevel--; - } - - void DumpType(QualType T) { - SplitQualType T_split = T.split(); - OS << "'" << QualType::getAsString(T_split) << "'"; - - if (!T.isNull()) { - // If the type is sugared, also dump a (shallow) desugared type. - SplitQualType D_split = T.getSplitDesugaredType(); - if (T_split != D_split) - OS << ":'" << QualType::getAsString(D_split) << "'"; - } - } - void DumpDeclRef(Decl *node); - void DumpStmt(const Stmt *Node) { - OS << Node->getStmtClassName() - << " " << (const void*)Node; - DumpSourceRange(Node); - } - void DumpValueKind(ExprValueKind K) { - switch (K) { - case VK_RValue: break; - case VK_LValue: OS << " lvalue"; break; - case VK_XValue: OS << " xvalue"; break; - } - } - void DumpObjectKind(ExprObjectKind K) { - switch (K) { - case OK_Ordinary: break; - case OK_BitField: OS << " bitfield"; break; - case OK_ObjCProperty: OS << " objcproperty"; break; - case OK_ObjCSubscript: OS << " objcsubscript"; break; - case OK_VectorComponent: OS << " vectorcomponent"; break; - } - } - void DumpExpr(const Expr *Node) { - DumpStmt(Node); - OS << ' '; - DumpType(Node->getType()); - DumpValueKind(Node->getValueKind()); - DumpObjectKind(Node->getObjectKind()); - } - void DumpSourceRange(const Stmt *Node); - void DumpLocation(SourceLocation Loc); - - // Stmts. - void VisitStmt(Stmt *Node); - void VisitDeclStmt(DeclStmt *Node); - void VisitLabelStmt(LabelStmt *Node); - void VisitGotoStmt(GotoStmt *Node); - - // Exprs - void VisitExpr(Expr *Node); - void VisitCastExpr(CastExpr *Node); - void VisitDeclRefExpr(DeclRefExpr *Node); - void VisitPredefinedExpr(PredefinedExpr *Node); - void VisitCharacterLiteral(CharacterLiteral *Node); - void VisitIntegerLiteral(IntegerLiteral *Node); - void VisitFloatingLiteral(FloatingLiteral *Node); - void VisitStringLiteral(StringLiteral *Str); - void VisitUnaryOperator(UnaryOperator *Node); - void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node); - void VisitMemberExpr(MemberExpr *Node); - void VisitExtVectorElementExpr(ExtVectorElementExpr *Node); - void VisitBinaryOperator(BinaryOperator *Node); - void VisitCompoundAssignOperator(CompoundAssignOperator *Node); - void VisitAddrLabelExpr(AddrLabelExpr *Node); - void VisitBlockExpr(BlockExpr *Node); - void VisitOpaqueValueExpr(OpaqueValueExpr *Node); - - // C++ - void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node); - void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node); - void VisitCXXThisExpr(CXXThisExpr *Node); - void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node); - void VisitCXXConstructExpr(CXXConstructExpr *Node); - void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node); - void VisitExprWithCleanups(ExprWithCleanups *Node); - void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node); - void DumpCXXTemporary(CXXTemporary *Temporary); - - // ObjC - void VisitObjCAtCatchStmt(ObjCAtCatchStmt *Node); - void VisitObjCEncodeExpr(ObjCEncodeExpr *Node); - void VisitObjCMessageExpr(ObjCMessageExpr* Node); - void VisitObjCBoxedExpr(ObjCBoxedExpr* Node); - void VisitObjCSelectorExpr(ObjCSelectorExpr *Node); - void VisitObjCProtocolExpr(ObjCProtocolExpr *Node); - void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node); - void VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node); - void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node); - void VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node); - }; -} - -//===----------------------------------------------------------------------===// -// Utilities -//===----------------------------------------------------------------------===// - -void StmtDumper::DumpLocation(SourceLocation Loc) { - SourceLocation SpellingLoc = SM->getSpellingLoc(Loc); - - // The general format we print out is filename:line:col, but we drop pieces - // that haven't changed since the last loc printed. - PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc); - - if (PLoc.isInvalid()) { - OS << "<invalid sloc>"; - return; - } - - if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) { - OS << PLoc.getFilename() << ':' << PLoc.getLine() - << ':' << PLoc.getColumn(); - LastLocFilename = PLoc.getFilename(); - LastLocLine = PLoc.getLine(); - } else if (PLoc.getLine() != LastLocLine) { - OS << "line" << ':' << PLoc.getLine() - << ':' << PLoc.getColumn(); - LastLocLine = PLoc.getLine(); - } else { - OS << "col" << ':' << PLoc.getColumn(); - } -} - -void StmtDumper::DumpSourceRange(const Stmt *Node) { - // Can't translate locations if a SourceManager isn't available. - if (SM == 0) return; - - // TODO: If the parent expression is available, we can print a delta vs its - // location. - SourceRange R = Node->getSourceRange(); - - OS << " <"; - DumpLocation(R.getBegin()); - if (R.getBegin() != R.getEnd()) { - OS << ", "; - DumpLocation(R.getEnd()); - } - OS << ">"; - - // <t2.c:123:421[blah], t2.c:412:321> - -} - - -//===----------------------------------------------------------------------===// -// Stmt printing methods. -//===----------------------------------------------------------------------===// - -void StmtDumper::VisitStmt(Stmt *Node) { - DumpStmt(Node); -} - -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)) { - OS << "\"typedef " << localType->getUnderlyingType().getAsString() - << ' ' << *localType << '"'; - } else if (TypeAliasDecl *localType = dyn_cast<TypeAliasDecl>(D)) { - OS << "\"using " << *localType << " = " - << localType->getUnderlyingType().getAsString() << '"'; - } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) { - OS << "\""; - // Emit storage class for vardecls. - if (VarDecl *V = dyn_cast<VarDecl>(VD)) { - if (V->getStorageClass() != SC_None) - OS << VarDecl::getStorageClassSpecifierString(V->getStorageClass()) - << " "; - } - - std::string Name = VD->getNameAsString(); - VD->getType().getAsStringInternal(Name, - PrintingPolicy(VD->getASTContext().getLangOpts())); - OS << Name; - - // If this is a vardecl with an initializer, emit it. - if (VarDecl *V = dyn_cast<VarDecl>(VD)) { - if (V->getInit()) { - OS << " ="; - DumpSubTree(V->getInit()); - } - } - OS << '"'; - } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { - // print a free standing tag decl (e.g. "struct x;"). - const char *tagname; - if (const IdentifierInfo *II = TD->getIdentifier()) - tagname = II->getNameStart(); - else - tagname = "<anonymous>"; - 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;") - const char *ns; - if (const IdentifierInfo *II = UD->getNominatedNamespace()->getIdentifier()) - ns = II->getNameStart(); - else - ns = "<anonymous>"; - OS << '"' << UD->getDeclKindName() << ns << ";\""; - } else if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) { - // print using decl (e.g. "using std::string;") - const char *tn = UD->isTypeName() ? "typename " : ""; - OS << '"' << UD->getDeclKindName() << tn; - UD->getQualifier()->print(OS, - PrintingPolicy(UD->getASTContext().getLangOpts())); - OS << ";\""; - } else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) { - OS << "label " << *LD; - } else if (StaticAssertDecl *SAD = dyn_cast<StaticAssertDecl>(D)) { - OS << "\"static_assert("; - DumpSubTree(SAD->getAssertExpr()); - OS << ","; - DumpSubTree(SAD->getMessage()); - OS << ");\""; - } else { - llvm_unreachable("Unexpected decl"); - } -} - -void StmtDumper::VisitDeclStmt(DeclStmt *Node) { - DumpStmt(Node); - for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end(); - DI != DE; ++DI) { - IndentScope Indent(*this); - Decl* D = *DI; - OS << (void*) D << " "; - DumpDeclarator(D); - } -} - -void StmtDumper::VisitLabelStmt(LabelStmt *Node) { - DumpStmt(Node); - OS << " '" << Node->getName() << "'"; -} - -void StmtDumper::VisitGotoStmt(GotoStmt *Node) { - DumpStmt(Node); - OS << " '" << Node->getLabel()->getName() - << "':" << (void*)Node->getLabel(); -} - -//===----------------------------------------------------------------------===// -// Expr printing methods. -//===----------------------------------------------------------------------===// - -void StmtDumper::VisitExpr(Expr *Node) { - DumpExpr(Node); -} - -static void DumpBasePath(raw_ostream &OS, CastExpr *Node) { - if (Node->path_empty()) - return; - - OS << " ("; - bool First = true; - for (CastExpr::path_iterator - I = Node->path_begin(), E = Node->path_end(); I != E; ++I) { - const CXXBaseSpecifier *Base = *I; - if (!First) - OS << " -> "; - - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - - if (Base->isVirtual()) - OS << "virtual "; - OS << RD->getName(); - First = false; - } - - OS << ')'; -} - -void StmtDumper::VisitCastExpr(CastExpr *Node) { - DumpExpr(Node); - OS << " <" << Node->getCastKindName(); - DumpBasePath(OS, Node); - OS << ">"; -} - -void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) { - DumpExpr(Node); - - OS << " "; - DumpDeclRef(Node->getDecl()); - if (Node->getDecl() != Node->getFoundDecl()) { - OS << " ("; - DumpDeclRef(Node->getFoundDecl()); - OS << ")"; - } -} - -void StmtDumper::DumpDeclRef(Decl *d) { - OS << d->getDeclKindName() << ' ' << (void*) d; - - if (NamedDecl *nd = dyn_cast<NamedDecl>(d)) { - OS << " '"; - nd->getDeclName().printName(OS); - OS << "'"; - } - - if (ValueDecl *vd = dyn_cast<ValueDecl>(d)) { - OS << ' '; DumpType(vd->getType()); - } -} - -void StmtDumper::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { - DumpExpr(Node); - OS << " ("; - if (!Node->requiresADL()) OS << "no "; - OS << "ADL) = '" << Node->getName() << '\''; - - 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); - - OS << " " << Node->getDecl()->getDeclKindName() - << "Decl='" << *Node->getDecl() - << "' " << (void*)Node->getDecl(); - if (Node->isFreeIvar()) - OS << " isFreeIvar"; -} - -void StmtDumper::VisitPredefinedExpr(PredefinedExpr *Node) { - DumpExpr(Node); - switch (Node->getIdentType()) { - default: llvm_unreachable("unknown case"); - case PredefinedExpr::Func: OS << " __func__"; break; - case PredefinedExpr::Function: OS << " __FUNCTION__"; break; - case PredefinedExpr::LFunction: OS << " L__FUNCTION__"; break; - case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break; - } -} - -void StmtDumper::VisitCharacterLiteral(CharacterLiteral *Node) { - DumpExpr(Node); - OS << " " << Node->getValue(); -} - -void StmtDumper::VisitIntegerLiteral(IntegerLiteral *Node) { - DumpExpr(Node); - - bool isSigned = Node->getType()->isSignedIntegerType(); - OS << " " << Node->getValue().toString(10, isSigned); -} -void StmtDumper::VisitFloatingLiteral(FloatingLiteral *Node) { - DumpExpr(Node); - OS << " " << Node->getValueAsApproximateDouble(); -} - -void StmtDumper::VisitStringLiteral(StringLiteral *Str) { - DumpExpr(Str); - OS << " "; - Str->outputString(OS); -} - -void StmtDumper::VisitUnaryOperator(UnaryOperator *Node) { - DumpExpr(Node); - OS << " " << (Node->isPostfix() ? "postfix" : "prefix") - << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; -} -void StmtDumper::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) { - DumpExpr(Node); - switch(Node->getKind()) { - case UETT_SizeOf: - OS << " sizeof "; - break; - case UETT_AlignOf: - OS << " alignof "; - break; - case UETT_VecStep: - OS << " vec_step "; - break; - } - if (Node->isArgumentType()) - DumpType(Node->getArgumentType()); -} - -void StmtDumper::VisitMemberExpr(MemberExpr *Node) { - DumpExpr(Node); - OS << " " << (Node->isArrow() ? "->" : ".") - << *Node->getMemberDecl() << ' ' - << (void*)Node->getMemberDecl(); -} -void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) { - DumpExpr(Node); - OS << " " << Node->getAccessor().getNameStart(); -} -void StmtDumper::VisitBinaryOperator(BinaryOperator *Node) { - DumpExpr(Node); - OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; -} -void StmtDumper::VisitCompoundAssignOperator(CompoundAssignOperator *Node) { - DumpExpr(Node); - OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) - << "' ComputeLHSTy="; - DumpType(Node->getComputationLHSType()); - OS << " ComputeResultTy="; - DumpType(Node->getComputationResultType()); -} - -void StmtDumper::VisitBlockExpr(BlockExpr *Node) { - DumpExpr(Node); - - BlockDecl *block = Node->getBlockDecl(); - OS << " decl=" << block; - - if (block->capturesCXXThis()) { - IndentScope Indent(*this); - OS << "capture this"; - } - for (BlockDecl::capture_iterator - i = block->capture_begin(), e = block->capture_end(); i != e; ++i) { - IndentScope Indent(*this); - OS << "capture "; - if (i->isByRef()) OS << "byref "; - if (i->isNested()) OS << "nested "; - if (i->getVariable()) - DumpDeclRef(i->getVariable()); - if (i->hasCopyExpr()) DumpSubTree(i->getCopyExpr()); - } - - DumpSubTree(block->getBody()); -} - -void StmtDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) { - DumpExpr(Node); - - if (Expr *Source = Node->getSourceExpr()) - DumpSubTree(Source); -} - -// GNU extensions. - -void StmtDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) { - DumpExpr(Node); - OS << " " << Node->getLabel()->getName() - << " " << (void*)Node->getLabel(); -} - -//===----------------------------------------------------------------------===// -// C++ Expressions -//===----------------------------------------------------------------------===// - -void StmtDumper::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) { - DumpExpr(Node); - OS << " " << Node->getCastName() - << "<" << Node->getTypeAsWritten().getAsString() << ">" - << " <" << Node->getCastKindName(); - DumpBasePath(OS, Node); - OS << ">"; -} - -void StmtDumper::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) { - DumpExpr(Node); - OS << " " << (Node->getValue() ? "true" : "false"); -} - -void StmtDumper::VisitCXXThisExpr(CXXThisExpr *Node) { - DumpExpr(Node); - OS << " this"; -} - -void StmtDumper::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) { - DumpExpr(Node); - OS << " functional cast to " << Node->getTypeAsWritten().getAsString() - << " <" << Node->getCastKindName() << ">"; -} - -void StmtDumper::VisitCXXConstructExpr(CXXConstructExpr *Node) { - DumpExpr(Node); - CXXConstructorDecl *Ctor = Node->getConstructor(); - DumpType(Ctor->getType()); - if (Node->isElidable()) - OS << " elidable"; - if (Node->requiresZeroInitialization()) - OS << " zeroing"; -} - -void StmtDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) { - DumpExpr(Node); - OS << " "; - DumpCXXTemporary(Node->getTemporary()); -} - -void StmtDumper::VisitExprWithCleanups(ExprWithCleanups *Node) { - DumpExpr(Node); - for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) { - IndentScope Indent(*this); - OS << "cleanup "; - DumpDeclRef(Node->getObject(i)); - } -} - -void StmtDumper::DumpCXXTemporary(CXXTemporary *Temporary) { - OS << "(CXXTemporary " << (void *)Temporary << ")"; -} - -//===----------------------------------------------------------------------===// -// Obj-C Expressions -//===----------------------------------------------------------------------===// - -void StmtDumper::VisitObjCMessageExpr(ObjCMessageExpr* Node) { - DumpExpr(Node); - OS << " selector=" << Node->getSelector().getAsString(); - switch (Node->getReceiverKind()) { - case ObjCMessageExpr::Instance: - break; - - case ObjCMessageExpr::Class: - OS << " class="; - DumpType(Node->getClassReceiver()); - break; - - case ObjCMessageExpr::SuperInstance: - OS << " super (instance)"; - break; - - case ObjCMessageExpr::SuperClass: - OS << " super (class)"; - break; - } -} - -void StmtDumper::VisitObjCBoxedExpr(ObjCBoxedExpr* Node) { - DumpExpr(Node); - OS << " selector=" << Node->getBoxingMethod()->getSelector().getAsString(); -} - -void StmtDumper::VisitObjCAtCatchStmt(ObjCAtCatchStmt *Node) { - DumpStmt(Node); - if (VarDecl *CatchParam = Node->getCatchParamDecl()) { - OS << " catch parm = "; - DumpDeclarator(CatchParam); - } else { - OS << " catch all"; - } -} - -void StmtDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { - DumpExpr(Node); - OS << " "; - DumpType(Node->getEncodedType()); -} - -void StmtDumper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { - DumpExpr(Node); - - OS << " " << Node->getSelector().getAsString(); -} - -void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) { - DumpExpr(Node); - - OS << ' ' <<* Node->getProtocol(); -} - -void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) { - DumpExpr(Node); - if (Node->isImplicitProperty()) { - OS << " Kind=MethodRef Getter=\""; - if (Node->getImplicitPropertyGetter()) - OS << Node->getImplicitPropertyGetter()->getSelector().getAsString(); - else - OS << "(null)"; - - OS << "\" Setter=\""; - if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter()) - OS << Setter->getSelector().getAsString(); - else - OS << "(null)"; - OS << "\""; - } else { - OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() <<'"'; - } - - if (Node->isSuperReceiver()) - OS << " super"; - - OS << " Messaging="; - if (Node->isMessagingGetter() && Node->isMessagingSetter()) - OS << "Getter&Setter"; - else if (Node->isMessagingGetter()) - OS << "Getter"; - else if (Node->isMessagingSetter()) - OS << "Setter"; -} - -void StmtDumper::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) { - DumpExpr(Node); - if (Node->isArraySubscriptRefExpr()) - OS << " Kind=ArraySubscript GetterForArray=\""; - else - OS << " Kind=DictionarySubscript GetterForDictionary=\""; - if (Node->getAtIndexMethodDecl()) - OS << Node->getAtIndexMethodDecl()->getSelector().getAsString(); - else - OS << "(null)"; - - if (Node->isArraySubscriptRefExpr()) - OS << "\" SetterForArray=\""; - else - OS << "\" SetterForDictionary=\""; - if (Node->setAtIndexMethodDecl()) - OS << Node->setAtIndexMethodDecl()->getSelector().getAsString(); - else - OS << "(null)"; -} - -void StmtDumper::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node) { - DumpExpr(Node); - OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no"); -} - -//===----------------------------------------------------------------------===// -// Stmt method implementations -//===----------------------------------------------------------------------===// - -/// 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(SourceManager &SM) const { - dump(llvm::errs(), SM); -} - -void Stmt::dump(raw_ostream &OS, SourceManager &SM) const { - StmtDumper P(&SM, OS, 4); - P.DumpSubTree(const_cast<Stmt*>(this)); -} - -/// 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, llvm::errs(), 4); - P.DumpSubTree(const_cast<Stmt*>(this)); -} - -/// dumpAll - This does a dump of the specified AST fragment and all subtrees. -void Stmt::dumpAll(SourceManager &SM) const { - StmtDumper P(&SM, llvm::errs(), ~0U); - P.DumpSubTree(const_cast<Stmt*>(this)); -} - -/// dumpAll - This does a dump of the specified AST fragment and all subtrees. -void Stmt::dumpAll() const { - StmtDumper P(0, llvm::errs(), ~0U); - P.DumpSubTree(const_cast<Stmt*>(this)); -} diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp index 57eb1a9..7df7fdb 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp @@ -13,14 +13,17 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" -#include "clang/AST/StmtVisitor.h" +#include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" -#include "clang/AST/PrettyPrinter.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/Basic/CharInfo.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/Format.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -583,10 +586,8 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { OS << "template "; OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) - OS << TemplateSpecializationType::PrintTemplateArgumentList( - Node->getTemplateArgs(), - Node->getNumTemplateArgs(), - Policy); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); } void StmtPrinter::VisitDependentScopeDeclRefExpr( @@ -597,10 +598,8 @@ void StmtPrinter::VisitDependentScopeDeclRefExpr( OS << "template "; OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) - OS << TemplateSpecializationType::PrintTemplateArgumentList( - Node->getTemplateArgs(), - Node->getNumTemplateArgs(), - Policy); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); } void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { @@ -610,10 +609,8 @@ void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { OS << "template "; OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) - OS << TemplateSpecializationType::PrintTemplateArgumentList( - Node->getTemplateArgs(), - Node->getNumTemplateArgs(), - Policy); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); } void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { @@ -709,15 +706,14 @@ void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) { OS << "'\\v'"; break; default: - if (value < 256 && isprint(value)) { + if (value < 256 && isPrintable((unsigned char)value)) OS << "'" << (char)value << "'"; - } else if (value < 256) { - OS << "'\\x"; - OS.write_hex(value) << "'"; - } else { - // FIXME what to really do here? - OS << value; - } + else if (value < 256) + OS << "'\\x" << llvm::format("%02x", value) << "'"; + else if (value <= 0xFFFF) + OS << "'\\u" << llvm::format("%04x", value) << "'"; + else + OS << "'\\U" << llvm::format("%08x", value) << "'"; } } @@ -810,7 +806,8 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) { void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) { OS << "__builtin_offsetof("; - OS << Node->getTypeSourceInfo()->getType().getAsString(Policy) << ", "; + Node->getTypeSourceInfo()->getType().print(OS, Policy); + OS << ", "; bool PrintedSomething = false; for (unsigned i = 0, n = Node->getNumComponents(); i < n; ++i) { OffsetOfExpr::OffsetOfNode ON = Node->getComponent(i); @@ -858,9 +855,11 @@ void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){ OS << "vec_step"; break; } - if (Node->isArgumentType()) - OS << "(" << Node->getArgumentType().getAsString(Policy) << ")"; - else { + if (Node->isArgumentType()) { + OS << '('; + Node->getArgumentType().print(OS, Policy); + OS << ')'; + } else { OS << " "; PrintExpr(Node->getArgumentExpr()); } @@ -875,7 +874,7 @@ void StmtPrinter::VisitGenericSelectionExpr(GenericSelectionExpr *Node) { if (T.isNull()) OS << "default"; else - OS << T.getAsString(Policy); + T.print(OS, Policy); OS << ": "; PrintExpr(Node->getAssocExpr(i)); } @@ -910,20 +909,26 @@ void StmtPrinter::VisitCallExpr(CallExpr *Call) { void StmtPrinter::VisitMemberExpr(MemberExpr *Node) { // FIXME: Suppress printing implicit bases (like "this") PrintExpr(Node->getBase()); + + MemberExpr *ParentMember = dyn_cast<MemberExpr>(Node->getBase()); + FieldDecl *ParentDecl = ParentMember + ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl()) : NULL; + + if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion()) + OS << (Node->isArrow() ? "->" : "."); + if (FieldDecl *FD = dyn_cast<FieldDecl>(Node->getMemberDecl())) if (FD->isAnonymousStructOrUnion()) return; - OS << (Node->isArrow() ? "->" : "."); + if (NestedNameSpecifier *Qualifier = Node->getQualifier()) Qualifier->print(OS, Policy); if (Node->hasTemplateKeyword()) OS << "template "; OS << Node->getMemberNameInfo(); if (Node->hasExplicitTemplateArgs()) - OS << TemplateSpecializationType::PrintTemplateArgumentList( - Node->getTemplateArgs(), - Node->getNumTemplateArgs(), - Policy); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); } void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) { PrintExpr(Node->getBase()); @@ -936,11 +941,15 @@ void StmtPrinter::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) { OS << Node->getAccessor().getName(); } void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) { - OS << "(" << Node->getTypeAsWritten().getAsString(Policy) << ")"; + OS << '('; + Node->getTypeAsWritten().print(OS, Policy); + OS << ')'; PrintExpr(Node->getSubExpr()); } void StmtPrinter::VisitCompoundLiteralExpr(CompoundLiteralExpr *Node) { - OS << "(" << Node->getType().getAsString(Policy) << ")"; + OS << '('; + Node->getType().print(OS, Policy); + OS << ')'; PrintExpr(Node->getInitializer()); } void StmtPrinter::VisitImplicitCastExpr(ImplicitCastExpr *Node) { @@ -1059,10 +1068,14 @@ void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) { } void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) { - if (Policy.LangOpts.CPlusPlus) - OS << "/*implicit*/" << Node->getType().getAsString(Policy) << "()"; - else { - OS << "/*implicit*/(" << Node->getType().getAsString(Policy) << ")"; + if (Policy.LangOpts.CPlusPlus) { + OS << "/*implicit*/"; + Node->getType().print(OS, Policy); + OS << "()"; + } else { + OS << "/*implicit*/("; + Node->getType().print(OS, Policy); + OS << ')'; if (Node->getType()->isRecordType()) OS << "{}"; else @@ -1074,7 +1087,7 @@ void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) { OS << "__builtin_va_arg("; PrintExpr(Node->getSubExpr()); OS << ", "; - OS << Node->getType().getAsString(Policy); + Node->getType().print(OS, Policy); OS << ")"; } @@ -1183,7 +1196,8 @@ void StmtPrinter::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *Node) { void StmtPrinter::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) { OS << Node->getCastName() << '<'; - OS << Node->getTypeAsWritten().getAsString(Policy) << ">("; + Node->getTypeAsWritten().print(OS, Policy); + OS << ">("; PrintExpr(Node->getSubExpr()); OS << ")"; } @@ -1207,7 +1221,7 @@ void StmtPrinter::VisitCXXConstCastExpr(CXXConstCastExpr *Node) { void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) { OS << "typeid("; if (Node->isTypeOperand()) { - OS << Node->getTypeOperand().getAsString(Policy); + Node->getTypeOperand().print(OS, Policy); } else { PrintExpr(Node->getExprOperand()); } @@ -1217,7 +1231,7 @@ void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) { void StmtPrinter::VisitCXXUuidofExpr(CXXUuidofExpr *Node) { OS << "__uuidof("; if (Node->isTypeOperand()) { - OS << Node->getTypeOperand().getAsString(Policy); + Node->getTypeOperand().print(OS, Policy); } else { PrintExpr(Node->getExprOperand()); } @@ -1288,7 +1302,7 @@ void StmtPrinter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Node) { } void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) { - OS << Node->getType().getAsString(Policy); + Node->getType().print(OS, Policy); OS << "("; PrintExpr(Node->getSubExpr()); OS << ")"; @@ -1299,7 +1313,7 @@ void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) { } void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) { - OS << Node->getType().getAsString(Policy); + Node->getType().print(OS, Policy); OS << "("; for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(), ArgEnd = Node->arg_end(); @@ -1369,8 +1383,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { NeedComma = true; } std::string ParamStr = (*P)->getNameAsString(); - (*P)->getOriginalType().getAsStringInternal(ParamStr, Policy); - OS << ParamStr; + (*P)->getOriginalType().print(OS, Policy, ParamStr); } if (Method->isVariadic()) { if (NeedComma) @@ -1384,17 +1397,15 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { const FunctionProtoType *Proto = Method->getType()->getAs<FunctionProtoType>(); - { - std::string ExceptionSpec; - Proto->printExceptionSpecification(ExceptionSpec, Policy); - OS << ExceptionSpec; - } + Proto->printExceptionSpecification(OS, Policy); // FIXME: Attributes // Print the trailing return type if it was specified in the source. - if (Node->hasExplicitResultType()) - OS << " -> " << Proto->getResultType().getAsString(Policy); + if (Node->hasExplicitResultType()) { + OS << " -> "; + Proto->getResultType().print(OS, Policy); + } } // Print the body. @@ -1405,9 +1416,10 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) { if (TypeSourceInfo *TSInfo = Node->getTypeSourceInfo()) - OS << TSInfo->getType().getAsString(Policy) << "()"; + TSInfo->getType().print(OS, Policy); else - OS << Node->getType().getAsString(Policy) << "()"; + Node->getType().print(OS, Policy); + OS << "()"; } void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) { @@ -1431,12 +1443,11 @@ void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) { std::string TypeS; if (Expr *Size = E->getArraySize()) { llvm::raw_string_ostream s(TypeS); + s << '['; Size->printPretty(s, Helper, Policy); - s.flush(); - TypeS = "[" + TypeS + "]"; + s << ']'; } - E->getAllocatedType().getAsStringInternal(TypeS, Policy); - OS << TypeS; + E->getAllocatedType().print(OS, Policy, TypeS); if (E->isParenTypeId()) OS << ")"; @@ -1469,15 +1480,16 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { E->getQualifier()->print(OS, Policy); OS << "~"; - std::string TypeS; if (IdentifierInfo *II = E->getDestroyedTypeIdentifier()) OS << II->getName(); else - E->getDestroyedType().getAsStringInternal(TypeS, Policy); - OS << TypeS; + E->getDestroyedType().print(OS, Policy); } void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) { + if (E->isListInitialization()) + OS << "{ "; + for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { if (isa<CXXDefaultArgExpr>(E->getArg(i))) { // Don't print any defaulted arguments @@ -1487,6 +1499,9 @@ void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) { if (i) OS << ", "; PrintExpr(E->getArg(i)); } + + if (E->isListInitialization()) + OS << " }"; } void StmtPrinter::VisitExprWithCleanups(ExprWithCleanups *E) { @@ -1497,7 +1512,7 @@ void StmtPrinter::VisitExprWithCleanups(ExprWithCleanups *E) { void StmtPrinter::VisitCXXUnresolvedConstructExpr( CXXUnresolvedConstructExpr *Node) { - OS << Node->getTypeAsWritten().getAsString(Policy); + Node->getTypeAsWritten().print(OS, Policy); OS << "("; for (CXXUnresolvedConstructExpr::arg_iterator Arg = Node->arg_begin(), ArgEnd = Node->arg_end(); @@ -1520,12 +1535,9 @@ void StmtPrinter::VisitCXXDependentScopeMemberExpr( if (Node->hasTemplateKeyword()) OS << "template "; OS << Node->getMemberNameInfo(); - if (Node->hasExplicitTemplateArgs()) { - OS << TemplateSpecializationType::PrintTemplateArgumentList( - Node->getTemplateArgs(), - Node->getNumTemplateArgs(), - Policy); - } + if (Node->hasExplicitTemplateArgs()) + TemplateSpecializationType::PrintTemplateArgumentList( + OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); } void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { @@ -1538,20 +1550,20 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { if (Node->hasTemplateKeyword()) OS << "template "; OS << Node->getMemberNameInfo(); - if (Node->hasExplicitTemplateArgs()) { - OS << TemplateSpecializationType::PrintTemplateArgumentList( - Node->getTemplateArgs(), - Node->getNumTemplateArgs(), - Policy); - } + if (Node->hasExplicitTemplateArgs()) + TemplateSpecializationType::PrintTemplateArgumentList( + OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); } static const char *getTypeTraitName(UnaryTypeTrait UTT) { switch (UTT) { case UTT_HasNothrowAssign: return "__has_nothrow_assign"; + case UTT_HasNothrowMoveAssign: return "__has_nothrow_move_assign"; case UTT_HasNothrowConstructor: return "__has_nothrow_constructor"; case UTT_HasNothrowCopy: return "__has_nothrow_copy"; case UTT_HasTrivialAssign: return "__has_trivial_assign"; + case UTT_HasTrivialMoveAssign: return "__has_trivial_move_assign"; + case UTT_HasTrivialMoveConstructor: return "__has_trivial_move_constructor"; case UTT_HasTrivialDefaultConstructor: return "__has_trivial_constructor"; case UTT_HasTrivialCopy: return "__has_trivial_copy"; case UTT_HasTrivialDestructor: return "__has_trivial_destructor"; @@ -1631,14 +1643,17 @@ static const char *getExpressionTraitName(ExpressionTrait ET) { } void StmtPrinter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { - OS << getTypeTraitName(E->getTrait()) << "(" - << E->getQueriedType().getAsString(Policy) << ")"; + OS << getTypeTraitName(E->getTrait()) << '('; + E->getQueriedType().print(OS, Policy); + OS << ')'; } void StmtPrinter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { - OS << getTypeTraitName(E->getTrait()) << "(" - << E->getLhsType().getAsString(Policy) << "," - << E->getRhsType().getAsString(Policy) << ")"; + OS << getTypeTraitName(E->getTrait()) << '('; + E->getLhsType().print(OS, Policy); + OS << ','; + E->getRhsType().print(OS, Policy); + OS << ')'; } void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) { @@ -1646,20 +1661,21 @@ void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) { for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) { if (I > 0) OS << ", "; - OS << E->getArg(I)->getType().getAsString(Policy); + E->getArg(I)->getType().print(OS, Policy); } OS << ")"; } void StmtPrinter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { - OS << getTypeTraitName(E->getTrait()) << "(" - << E->getQueriedType().getAsString(Policy) << ")"; + OS << getTypeTraitName(E->getTrait()) << '('; + E->getQueriedType().print(OS, Policy); + OS << ')'; } void StmtPrinter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { - OS << getExpressionTraitName(E->getTrait()) << "("; - PrintExpr(E->getQueriedExpression()); - OS << ")"; + OS << getExpressionTraitName(E->getTrait()) << '('; + PrintExpr(E->getQueriedExpression()); + OS << ')'; } void StmtPrinter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { @@ -1738,7 +1754,9 @@ void StmtPrinter::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { } void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { - OS << "@encode(" << Node->getEncodedType().getAsString(Policy) << ')'; + OS << "@encode("; + Node->getEncodedType().print(OS, Policy); + OS << ')'; } void StmtPrinter::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { @@ -1757,7 +1775,7 @@ void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) { break; case ObjCMessageExpr::Class: - OS << Mess->getClassReceiver().getAsString(Policy); + Mess->getClassReceiver().print(OS, Policy); break; case ObjCMessageExpr::SuperInstance: @@ -1798,8 +1816,9 @@ StmtPrinter::VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) { void StmtPrinter::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) { - OS << "(" << E->getBridgeKindName() << E->getType().getAsString(Policy) - << ")"; + OS << '(' << E->getBridgeKindName(); + E->getType().print(OS, Policy); + OS << ')'; PrintExpr(E->getSubExpr()); } @@ -1813,13 +1832,11 @@ void StmtPrinter::VisitBlockExpr(BlockExpr *Node) { OS << "()"; } else if (!BD->param_empty() || cast<FunctionProtoType>(AFT)->isVariadic()) { OS << '('; - std::string ParamStr; for (BlockDecl::param_iterator AI = BD->param_begin(), E = BD->param_end(); AI != E; ++AI) { if (AI != BD->param_begin()) OS << ", "; - ParamStr = (*AI)->getNameAsString(); - (*AI)->getType().getAsStringInternal(ParamStr, Policy); - OS << ParamStr; + std::string ParamStr = (*AI)->getNameAsString(); + (*AI)->getType().print(OS, Policy, ParamStr); } const FunctionProtoType *FT = cast<FunctionProtoType>(AFT); @@ -1829,6 +1846,7 @@ void StmtPrinter::VisitBlockExpr(BlockExpr *Node) { } OS << ')'; } + OS << "{ }"; } void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) { @@ -1838,7 +1856,8 @@ void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) { void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) { OS << "__builtin_astype("; PrintExpr(Node->getSrcExpr()); - OS << ", " << Node->getType().getAsString(); + OS << ", "; + Node->getType().print(OS, Policy); OS << ")"; } @@ -1859,11 +1878,6 @@ void Stmt::printPretty(raw_ostream &OS, return; } - if (Policy.DumpSourceManager) { - dump(OS, *Policy.DumpSourceManager); - return; - } - StmtPrinter P(OS, Helper, Policy, Indentation); P.Visit(const_cast<Stmt*>(this)); } diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp index e9ee385..d68b95e 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp @@ -23,8 +23,8 @@ #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> -#include <cctype> using namespace clang; @@ -224,12 +224,12 @@ bool TemplateArgument::containsUnexpandedParameterPack() const { return false; } -llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const { +Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const { assert(Kind == TemplateExpansion); if (TemplateArg.NumExpansions) return TemplateArg.NumExpansions - 1; - return llvm::Optional<unsigned>(); + return None; } void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, @@ -347,9 +347,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy, case Type: { PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressStrongLifetime = true; - std::string TypeStr; - getAsType().getAsStringInternal(TypeStr, SubPolicy); - Out << TypeStr; + getAsType().print(Out, SubPolicy); break; } @@ -451,10 +449,9 @@ SourceRange TemplateArgumentLoc::getSourceRange() const { llvm_unreachable("Invalid TemplateArgument Kind!"); } -TemplateArgumentLoc -TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, - llvm::Optional<unsigned> &NumExpansions, - ASTContext &Context) const { +TemplateArgumentLoc TemplateArgumentLoc::getPackExpansionPattern( + SourceLocation &Ellipsis, Optional<unsigned> &NumExpansions, + ASTContext &Context) const { assert(Argument.isPackExpansion()); switch (Argument.getKind()) { @@ -466,8 +463,8 @@ TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, ExpansionTSInfo = Context.getTrivialTypeSourceInfo( getArgument().getAsType(), Ellipsis); - PackExpansionTypeLoc Expansion - = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc()); + PackExpansionTypeLoc Expansion = + ExpansionTSInfo->getTypeLoc().castAs<PackExpansionTypeLoc>(); Ellipsis = Expansion.getEllipsisLoc(); TypeLoc Pattern = Expansion.getPatternLoc(); diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp index e89ba53..8767c63 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp @@ -1,4 +1,4 @@ -//===--- TemplateName.h - C++ Template Name Representation-------*- C++ -*-===// +//===--- TemplateName.cpp - C++ Template Name Representation---------------===// // // The LLVM Compiler Infrastructure // @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "clang/AST/TemplateName.h" -#include "clang/AST/TemplateBase.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/TemplateBase.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LangOptions.h" #include "llvm/Support/raw_ostream.h" @@ -163,14 +163,20 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, LangOptions LO; LO.CPlusPlus = true; LO.Bool = true; + OS << '\''; N.print(OS, PrintingPolicy(LO)); + OS << '\''; OS.flush(); return DB << NameStr; } -void TemplateName::dump() const { +void TemplateName::dump(raw_ostream &OS) const { LangOptions LO; // FIXME! LO.CPlusPlus = true; LO.Bool = true; - print(llvm::errs(), PrintingPolicy(LO)); + print(OS, PrintingPolicy(LO)); +} + +void TemplateName::dump() const { + dump(llvm::errs()); } diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp index 580ec50..0c5636d 100644 --- a/contrib/llvm/tools/clang/lib/AST/Type.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp @@ -12,13 +12,14 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/CharUnits.h" -#include "clang/AST/Type.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/Type.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/APSInt.h" @@ -75,16 +76,35 @@ bool QualType::isConstant(QualType T, ASTContext &Ctx) { unsigned ConstantArrayType::getNumAddressingBits(ASTContext &Context, QualType ElementType, const llvm::APInt &NumElements) { + uint64_t ElementSize = Context.getTypeSizeInChars(ElementType).getQuantity(); + + // Fast path the common cases so we can avoid the conservative computation + // below, which in common cases allocates "large" APSInt values, which are + // slow. + + // If the element size is a power of 2, we can directly compute the additional + // number of addressing bits beyond those required for the element count. + if (llvm::isPowerOf2_64(ElementSize)) { + return NumElements.getActiveBits() + llvm::Log2_64(ElementSize); + } + + // If both the element count and element size fit in 32-bits, we can do the + // computation directly in 64-bits. + if ((ElementSize >> 32) == 0 && NumElements.getBitWidth() <= 64 && + (NumElements.getZExtValue() >> 32) == 0) { + uint64_t TotalSize = NumElements.getZExtValue() * ElementSize; + return 64 - llvm::CountLeadingZeros_64(TotalSize); + } + + // Otherwise, use APSInt to handle arbitrary sized values. llvm::APSInt SizeExtended(NumElements, true); unsigned SizeTypeBits = Context.getTypeSize(Context.getSizeType()); SizeExtended = SizeExtended.extend(std::max(SizeTypeBits, SizeExtended.getBitWidth()) * 2); - uint64_t ElementSize - = Context.getTypeSizeInChars(ElementType).getQuantity(); llvm::APSInt TotalSize(llvm::APInt(SizeExtended.getBitWidth(), ElementSize)); TotalSize *= SizeExtended; - + return TotalSize.getActiveBits(); } @@ -939,7 +959,7 @@ bool Type::isIncompleteType(NamedDecl **Def) const { bool QualType::isPODType(ASTContext &Context) const { // C++11 has a more relaxed definition of POD. - if (Context.getLangOpts().CPlusPlus0x) + if (Context.getLangOpts().CPlusPlus11) return isCXX11PODType(Context); return isCXX98PODType(Context); @@ -1052,11 +1072,13 @@ bool QualType::isTrivialType(ASTContext &Context) const { if (const RecordType *RT = CanonicalType->getAs<RecordType>()) { if (const CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { - // C++0x [class]p5: - // A trivial class is a class that has a trivial default constructor - if (!ClassDecl->hasTrivialDefaultConstructor()) return false; - // and is trivially copyable. - if (!ClassDecl->isTriviallyCopyable()) return false; + // C++11 [class]p6: + // A trivial class is a class that has a default constructor, + // has no non-trivial default constructors, and is trivially + // copyable. + return ClassDecl->hasDefaultConstructor() && + !ClassDecl->hasNonTrivialDefaultConstructor() && + ClassDecl->isTriviallyCopyable(); } return true; @@ -1509,6 +1531,14 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { case ObjCId: return "id"; case ObjCClass: return "Class"; case ObjCSel: return "SEL"; + case OCLImage1d: return "image1d_t"; + case OCLImage1dArray: return "image1d_array_t"; + case OCLImage1dBuffer: return "image1d_buffer_t"; + case OCLImage2d: return "image2d_t"; + case OCLImage2dArray: return "image2d_array_t"; + case OCLImage3d: return "image3d_t"; + case OCLSampler: return "sampler_t"; + case OCLEvent: return "event_t"; } llvm_unreachable("Invalid builtin type."); @@ -1543,29 +1573,33 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_AAPCS: return "aapcs"; case CC_AAPCS_VFP: return "aapcs-vfp"; case CC_PnaclCall: return "pnaclcall"; + case CC_IntelOclBicc: return "intel_ocl_bicc"; } llvm_unreachable("Invalid calling convention."); } -FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, - unsigned numArgs, QualType canonical, +FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> args, + QualType canonical, const ExtProtoInfo &epi) - : FunctionType(FunctionProto, result, epi.TypeQuals, epi.RefQualifier, + : FunctionType(FunctionProto, result, epi.TypeQuals, canonical, result->isDependentType(), result->isInstantiationDependentType(), result->isVariablyModifiedType(), result->containsUnexpandedParameterPack(), epi.ExtInfo), - NumArgs(numArgs), NumExceptions(epi.NumExceptions), + NumArgs(args.size()), NumExceptions(epi.NumExceptions), ExceptionSpecType(epi.ExceptionSpecType), HasAnyConsumedArgs(epi.ConsumedArguments != 0), - Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn) + Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn), + RefQualifier(epi.RefQualifier) { + assert(NumArgs == args.size() && "function has too many parameters"); + // Fill in the trailing argument array. QualType *argSlot = reinterpret_cast<QualType*>(this+1); - for (unsigned i = 0; i != numArgs; ++i) { + for (unsigned i = 0; i != NumArgs; ++i) { if (args[i]->isDependentType()) setDependent(); else if (args[i]->isInstantiationDependentType()) @@ -1579,7 +1613,7 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, if (getExceptionSpecType() == EST_Dynamic) { // Fill in the exception array. - QualType *exnSlot = argSlot + numArgs; + QualType *exnSlot = argSlot + NumArgs; for (unsigned i = 0, e = epi.NumExceptions; i != e; ++i) { if (epi.Exceptions[i]->isDependentType()) setDependent(); @@ -1593,7 +1627,7 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, } } else if (getExceptionSpecType() == EST_ComputedNoexcept) { // Store the noexcept expression and context. - Expr **noexSlot = reinterpret_cast<Expr**>(argSlot + numArgs); + Expr **noexSlot = reinterpret_cast<Expr**>(argSlot + NumArgs); *noexSlot = epi.NoexceptExpr; if (epi.NoexceptExpr) { @@ -1606,7 +1640,7 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, } else if (getExceptionSpecType() == EST_Uninstantiated) { // Store the function decl from which we will resolve our // exception specification. - FunctionDecl **slot = reinterpret_cast<FunctionDecl**>(argSlot + numArgs); + FunctionDecl **slot = reinterpret_cast<FunctionDecl**>(argSlot + NumArgs); slot[0] = epi.ExceptionSpecDecl; slot[1] = epi.ExceptionSpecTemplate; // This exception specification doesn't make the type dependent, because @@ -1614,13 +1648,13 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, } else if (getExceptionSpecType() == EST_Unevaluated) { // Store the function decl from which we will resolve our // exception specification. - FunctionDecl **slot = reinterpret_cast<FunctionDecl**>(argSlot + numArgs); + FunctionDecl **slot = reinterpret_cast<FunctionDecl**>(argSlot + NumArgs); slot[0] = epi.ExceptionSpecDecl; } if (epi.ConsumedArguments) { bool *consumedArgs = const_cast<bool*>(getConsumedArgsBuffer()); - for (unsigned i = 0; i != numArgs; ++i) + for (unsigned i = 0; i != NumArgs; ++i) consumedArgs[i] = epi.ConsumedArguments[i]; } } @@ -1987,22 +2021,18 @@ namespace { /// \brief The cached properties of a type. class CachedProperties { - NamedDecl::LinkageInfo LV; + Linkage L; bool local; - + public: - CachedProperties(NamedDecl::LinkageInfo LV, bool local) - : LV(LV), local(local) {} - - Linkage getLinkage() const { return LV.linkage(); } - Visibility getVisibility() const { return LV.visibility(); } - bool isVisibilityExplicit() const { return LV.visibilityExplicit(); } + CachedProperties(Linkage L, bool local) : L(L), local(local) {} + + Linkage getLinkage() const { return L; } bool hasLocalOrUnnamedType() const { return local; } - + friend CachedProperties merge(CachedProperties L, CachedProperties R) { - NamedDecl::LinkageInfo MergedLV = L.LV; - MergedLV.merge(R.LV); - return CachedProperties(MergedLV, + Linkage MergedLinkage = minLinkage(L.L, R.L); + return CachedProperties(MergedLinkage, L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType()); } }; @@ -2022,10 +2052,8 @@ public: static CachedProperties get(const Type *T) { ensure(T); - NamedDecl::LinkageInfo LV(T->TypeBits.getLinkage(), - T->TypeBits.getVisibility(), - T->TypeBits.isVisibilityExplicit()); - return CachedProperties(LV, T->TypeBits.hasLocalOrUnnamedType()); + return CachedProperties(T->TypeBits.getLinkage(), + T->TypeBits.hasLocalOrUnnamedType()); } static void ensure(const Type *T) { @@ -2037,10 +2065,7 @@ public: if (!T->isCanonicalUnqualified()) { const Type *CT = T->getCanonicalTypeInternal().getTypePtr(); ensure(CT); - T->TypeBits.CacheValidAndVisibility = - CT->TypeBits.CacheValidAndVisibility; - T->TypeBits.CachedExplicitVisibility = - CT->TypeBits.CachedExplicitVisibility; + T->TypeBits.CacheValid = true; T->TypeBits.CachedLinkage = CT->TypeBits.CachedLinkage; T->TypeBits.CachedLocalOrUnnamed = CT->TypeBits.CachedLocalOrUnnamed; return; @@ -2048,10 +2073,7 @@ public: // Compute the cached properties and then set the cache. CachedProperties Result = computeCachedProperties(T); - T->TypeBits.CacheValidAndVisibility = Result.getVisibility() + 1U; - T->TypeBits.CachedExplicitVisibility = Result.isVisibilityExplicit(); - assert(T->TypeBits.isCacheValid() && - T->TypeBits.getVisibility() == Result.getVisibility()); + T->TypeBits.CacheValid = true; T->TypeBits.CachedLinkage = Result.getLinkage(); T->TypeBits.CachedLocalOrUnnamed = Result.hasLocalOrUnnamedType(); } @@ -2077,13 +2099,13 @@ static CachedProperties computeCachedProperties(const Type *T) { #include "clang/AST/TypeNodes.def" // Treat instantiation-dependent types as external. assert(T->isInstantiationDependentType()); - return CachedProperties(NamedDecl::LinkageInfo(), false); + return CachedProperties(ExternalLinkage, false); case Type::Builtin: // C++ [basic.link]p8: // A type is said to have linkage if and only if: // - it is a fundamental type (3.9.1); or - return CachedProperties(NamedDecl::LinkageInfo(), false); + return CachedProperties(ExternalLinkage, false); case Type::Record: case Type::Enum: { @@ -2093,11 +2115,11 @@ static CachedProperties computeCachedProperties(const Type *T) { // - it is a class or enumeration type that is named (or has a name // for linkage purposes (7.1.3)) and the name has linkage; or // - it is a specialization of a class template (14); or - NamedDecl::LinkageInfo LV = Tag->getLinkageAndVisibility(); + Linkage L = Tag->getLinkage(); bool IsLocalOrUnnamed = Tag->getDeclContext()->isFunctionOrMethod() || - (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()); - return CachedProperties(LV, IsLocalOrUnnamed); + !Tag->hasNameForLinkage(); + return CachedProperties(L, IsLocalOrUnnamed); } // C++ [basic.link]p8: @@ -2135,9 +2157,8 @@ static CachedProperties computeCachedProperties(const Type *T) { return result; } case Type::ObjCInterface: { - NamedDecl::LinkageInfo LV = - cast<ObjCInterfaceType>(T)->getDecl()->getLinkageAndVisibility(); - return CachedProperties(LV, false); + Linkage L = cast<ObjCInterfaceType>(T)->getDecl()->getLinkage(); + return CachedProperties(L, false); } case Type::ObjCObject: return Cache::get(cast<ObjCObjectType>(T)->getBaseType()); @@ -2156,31 +2177,99 @@ Linkage Type::getLinkage() const { return TypeBits.getLinkage(); } -/// \brief Determine the linkage of this type. -Visibility Type::getVisibility() const { +bool Type::hasUnnamedOrLocalType() const { Cache::ensure(this); - return TypeBits.getVisibility(); + return TypeBits.hasLocalOrUnnamedType(); } -bool Type::isVisibilityExplicit() const { - Cache::ensure(this); - return TypeBits.isVisibilityExplicit(); +static LinkageInfo computeLinkageInfo(QualType T); + +static LinkageInfo computeLinkageInfo(const Type *T) { + switch (T->getTypeClass()) { +#define TYPE(Class,Base) +#define NON_CANONICAL_TYPE(Class,Base) case Type::Class: +#include "clang/AST/TypeNodes.def" + llvm_unreachable("didn't expect a non-canonical type here"); + +#define TYPE(Class,Base) +#define DEPENDENT_TYPE(Class,Base) case Type::Class: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class,Base) case Type::Class: +#include "clang/AST/TypeNodes.def" + // Treat instantiation-dependent types as external. + assert(T->isInstantiationDependentType()); + return LinkageInfo::external(); + + case Type::Builtin: + return LinkageInfo::external(); + + case Type::Record: + case Type::Enum: + return cast<TagType>(T)->getDecl()->getLinkageAndVisibility(); + + case Type::Complex: + return computeLinkageInfo(cast<ComplexType>(T)->getElementType()); + case Type::Pointer: + return computeLinkageInfo(cast<PointerType>(T)->getPointeeType()); + case Type::BlockPointer: + return computeLinkageInfo(cast<BlockPointerType>(T)->getPointeeType()); + case Type::LValueReference: + case Type::RValueReference: + return computeLinkageInfo(cast<ReferenceType>(T)->getPointeeType()); + case Type::MemberPointer: { + const MemberPointerType *MPT = cast<MemberPointerType>(T); + LinkageInfo LV = computeLinkageInfo(MPT->getClass()); + LV.merge(computeLinkageInfo(MPT->getPointeeType())); + return LV; + } + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + return computeLinkageInfo(cast<ArrayType>(T)->getElementType()); + case Type::Vector: + case Type::ExtVector: + return computeLinkageInfo(cast<VectorType>(T)->getElementType()); + case Type::FunctionNoProto: + return computeLinkageInfo(cast<FunctionType>(T)->getResultType()); + case Type::FunctionProto: { + const FunctionProtoType *FPT = cast<FunctionProtoType>(T); + LinkageInfo LV = computeLinkageInfo(FPT->getResultType()); + for (FunctionProtoType::arg_type_iterator ai = FPT->arg_type_begin(), + ae = FPT->arg_type_end(); ai != ae; ++ai) + LV.merge(computeLinkageInfo(*ai)); + return LV; + } + case Type::ObjCInterface: + return cast<ObjCInterfaceType>(T)->getDecl()->getLinkageAndVisibility(); + case Type::ObjCObject: + return computeLinkageInfo(cast<ObjCObjectType>(T)->getBaseType()); + case Type::ObjCObjectPointer: + return computeLinkageInfo(cast<ObjCObjectPointerType>(T)->getPointeeType()); + case Type::Atomic: + return computeLinkageInfo(cast<AtomicType>(T)->getValueType()); + } + + llvm_unreachable("unhandled type class"); } -bool Type::hasUnnamedOrLocalType() const { - Cache::ensure(this); - return TypeBits.hasLocalOrUnnamedType(); +static LinkageInfo computeLinkageInfo(QualType T) { + return computeLinkageInfo(T.getTypePtr()); } -std::pair<Linkage,Visibility> Type::getLinkageAndVisibility() const { - Cache::ensure(this); - return std::make_pair(TypeBits.getLinkage(), TypeBits.getVisibility()); +bool Type::isLinkageValid() const { + if (!TypeBits.isCacheValid()) + return true; + + return computeLinkageInfo(getCanonicalTypeInternal()).getLinkage() == + TypeBits.getLinkage(); } -void Type::ClearLinkageCache() { - TypeBits.CacheValidAndVisibility = 0; - if (QualType(this, 0) != CanonicalType) - CanonicalType->TypeBits.CacheValidAndVisibility = 0; +LinkageInfo Type::getLinkageAndVisibility() const { + if (!isCanonicalUnqualified()) + return computeLinkageInfo(getCanonicalTypeInternal()); + + LinkageInfo LV = computeLinkageInfo(this); + assert(LV.getLinkage() == getLinkage()); + return LV; } Qualifiers::ObjCLifetime Type::getObjCARCImplicitLifetime() const { @@ -2296,25 +2385,3 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) { return DK_none; } - -bool QualType::hasTrivialAssignment(ASTContext &Context, bool Copying) const { - switch (getObjCLifetime()) { - case Qualifiers::OCL_None: - break; - - case Qualifiers::OCL_ExplicitNone: - return true; - - case Qualifiers::OCL_Autoreleasing: - case Qualifiers::OCL_Strong: - case Qualifiers::OCL_Weak: - return !Context.getLangOpts().ObjCAutoRefCount; - } - - if (const CXXRecordDecl *Record - = getTypePtr()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) - return Copying ? Record->hasTrivialCopyAssignment() : - Record->hasTrivialMoveAssignment(); - - return true; -} diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp index 58c4cbd..03d4030 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp @@ -11,11 +11,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/raw_ostream.h" -#include "clang/AST/TypeLocVisitor.h" +#include "clang/AST/TypeLoc.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" +#include "clang/AST/TypeLocVisitor.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -85,7 +86,7 @@ void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ case CLASS: { \ - CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \ + CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \ TLCasted.initializeLocal(Context, Loc); \ TL = TLCasted.getNextTypeLoc(); \ if (!TL) return; \ @@ -105,7 +106,8 @@ SourceLocation TypeLoc::getBeginLoc() const { LeftMost = Cur; break; case FunctionProto: - if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn()) { + if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr() + ->hasTrailingReturn()) { LeftMost = Cur; break; } @@ -150,7 +152,7 @@ SourceLocation TypeLoc::getEndLoc() const { Last = Cur; break; case FunctionProto: - if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn()) + if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn()) Last = TypeLoc(); else Last = Cur; @@ -197,9 +199,9 @@ namespace { /// 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); +bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) { + if (TL.getType().hasLocalQualifiers()) return false; + return TSTChecker().Visit(TL); } // Reimplemented to account for GNU/C++ extension @@ -261,6 +263,14 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: + case BuiltinType::OCLImage1d: + case BuiltinType::OCLImage1dArray: + case BuiltinType::OCLImage1dBuffer: + case BuiltinType::OCLImage2d: + case BuiltinType::OCLImage2dArray: + case BuiltinType::OCLImage3d: + case BuiltinType::OCLSampler: + case BuiltinType::OCLEvent: case BuiltinType::BuiltinFn: return TST_unspecified; } @@ -269,8 +279,8 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { } TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { - while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL)) - TL = PTL->getInnerLoc(); + while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>()) + TL = PTL.getInnerLoc(); return TL; } diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp index 90b2ca9..9d1717a 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp @@ -11,19 +11,19 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/PrettyPrinter.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/Type.h" -#include "clang/AST/PrettyPrinter.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/SaveAndRestore.h" +#include "llvm/Support/raw_ostream.h" using namespace clang; namespace { @@ -647,6 +647,9 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, case CC_PnaclCall: OS << " __attribute__((pnaclcall))"; break; + case CC_IntelOclBicc: + OS << " __attribute__((intel_ocl_bicc))"; + break; } if (Info.getNoReturn()) OS << " __attribute__((noreturn))"; @@ -1168,6 +1171,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, break; } case AttributedType::attr_pnaclcall: OS << "pnaclcall"; break; + case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break; } OS << "))"; } @@ -1344,132 +1348,6 @@ PrintTemplateArgumentList(raw_ostream &OS, OS << '>'; } -void -FunctionProtoType::printExceptionSpecification(std::string &S, - const PrintingPolicy &Policy) - const { - - if (hasDynamicExceptionSpec()) { - S += " throw("; - if (getExceptionSpecType() == EST_MSAny) - S += "..."; - else - for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) { - if (I) - S += ", "; - - S += getExceptionType(I).getAsString(Policy); - } - S += ")"; - } else if (isNoexceptExceptionSpec(getExceptionSpecType())) { - S += " noexcept"; - if (getExceptionSpecType() == EST_ComputedNoexcept) { - S += "("; - llvm::raw_string_ostream EOut(S); - getNoexceptExpr()->printPretty(EOut, 0, Policy); - EOut.flush(); - S += EOut.str(); - S += ")"; - } - } -} - -std::string TemplateSpecializationType:: - PrintTemplateArgumentList(const TemplateArgumentListInfo &Args, - const PrintingPolicy &Policy) { - return PrintTemplateArgumentList(Args.getArgumentArray(), - Args.size(), - Policy); -} - -std::string -TemplateSpecializationType::PrintTemplateArgumentList( - const TemplateArgument *Args, - unsigned NumArgs, - const PrintingPolicy &Policy, - bool SkipBrackets) { - std::string SpecString; - if (!SkipBrackets) - SpecString += '<'; - - for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { - if (SpecString.size() > unsigned(!SkipBrackets)) - SpecString += ", "; - - // Print the argument into a string. - std::string ArgString; - if (Args[Arg].getKind() == TemplateArgument::Pack) { - ArgString = PrintTemplateArgumentList(Args[Arg].pack_begin(), - Args[Arg].pack_size(), - Policy, true); - } else { - llvm::raw_string_ostream ArgOut(ArgString); - Args[Arg].print(Policy, ArgOut); - } - - // If this is the first argument and its string representation - // begins with the global scope specifier ('::foo'), add a space - // to avoid printing the diagraph '<:'. - if (!Arg && !ArgString.empty() && ArgString[0] == ':') - SpecString += ' '; - - SpecString += ArgString; - } - - // If the last character of our string is '>', add another space to - // keep the two '>''s separate tokens. We don't *have* to do this in - // C++0x, but it's still good hygiene. - if (!SpecString.empty() && SpecString[SpecString.size() - 1] == '>') - SpecString += ' '; - - if (!SkipBrackets) - SpecString += '>'; - - return SpecString; -} - -// Sadly, repeat all that with TemplateArgLoc. -std::string TemplateSpecializationType:: -PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs, - const PrintingPolicy &Policy) { - std::string SpecString; - SpecString += '<'; - for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { - if (SpecString.size() > 1) - SpecString += ", "; - - // Print the argument into a string. - std::string ArgString; - if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) { - ArgString = PrintTemplateArgumentList( - Args[Arg].getArgument().pack_begin(), - Args[Arg].getArgument().pack_size(), - Policy, true); - } else { - llvm::raw_string_ostream ArgOut(ArgString); - Args[Arg].getArgument().print(Policy, ArgOut); - } - - // If this is the first argument and its string representation - // begins with the global scope specifier ('::foo'), add a space - // to avoid printing the diagraph '<:'. - if (!Arg && !ArgString.empty() && ArgString[0] == ':') - SpecString += ' '; - - SpecString += ArgString; - } - - // If the last character of our string is '>', add another space to - // keep the two '>''s separate tokens. We don't *have* to do this in - // C++0x, but it's still good hygiene. - if (SpecString[SpecString.size() - 1] == '>') - SpecString += ' '; - - SpecString += '>'; - - return SpecString; -} - void QualType::dump(const char *msg) const { if (msg) llvm::errs() << msg << ": "; @@ -1599,11 +1477,7 @@ void QualType::print(const Type *ty, Qualifiers qs, raw_ostream &OS, const PrintingPolicy &policy, const Twine &PlaceHolder) { SmallString<128> PHBuf; - StringRef PH; - if (PlaceHolder.isSingleStringRef()) - PH = PlaceHolder.getSingleStringRef(); - else - PH = PlaceHolder.toStringRef(PHBuf); + StringRef PH = PlaceHolder.toStringRef(PHBuf); TypePrinter(policy).print(ty, qs, OS, PH); } diff --git a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp index 33dad40..f80232f 100644 --- a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp @@ -17,6 +17,7 @@ #include "clang/AST/RecordLayout.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cstdio> @@ -256,11 +257,9 @@ static BaseOffset ComputeBaseOffset(ASTContext &Context, const CXXRecordDecl *DerivedRD) { CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true, /*DetectVirtual=*/false); - - if (!const_cast<CXXRecordDecl *>(DerivedRD)-> - isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) { + + if (!DerivedRD->isDerivedFrom(BaseRD, Paths)) llvm_unreachable("Class must be derived from the passed in base class!"); - } return ComputeBaseOffset(Context, DerivedRD, Paths.front()); } @@ -1001,6 +1000,10 @@ public: dumpLayout(llvm::errs()); } + bool isMicrosoftABI() const { + return VTables.isMicrosoftABI(); + } + uint64_t getNumThunks() const { return Thunks.size(); } @@ -1157,6 +1160,8 @@ void VTableBuilder::ComputeThisAdjustments() { break; case VTableComponent::CK_DeletingDtorPointer: // We've already added the thunk when we saw the complete dtor pointer. + // FIXME: check how this works in the Microsoft ABI + // while working on the multiple inheritance patch. continue; } @@ -1197,10 +1202,8 @@ VTableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base, CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/true); - if (!const_cast<CXXRecordDecl *>(DerivedRD)-> - isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) { + if (!DerivedRD->isDerivedFrom(BaseRD, Paths)) llvm_unreachable("Class must be derived from the passed in base class!"); - } // We have to go through all the paths, and see which one leads us to the // right base subobject. @@ -1295,9 +1298,15 @@ VTableBuilder::AddMethod(const CXXMethodDecl *MD, assert(ReturnAdjustment.isEmpty() && "Destructor can't have return adjustment!"); - // Add both the complete destructor and the deleting destructor. - Components.push_back(VTableComponent::MakeCompleteDtor(DD)); - Components.push_back(VTableComponent::MakeDeletingDtor(DD)); + // FIXME: Should probably add a layer of abstraction for vtable generation. + if (!isMicrosoftABI()) { + // Add both the complete destructor and the deleting destructor. + Components.push_back(VTableComponent::MakeCompleteDtor(DD)); + Components.push_back(VTableComponent::MakeDeletingDtor(DD)); + } else { + // Add the scalar deleting destructor. + Components.push_back(VTableComponent::MakeDeletingDtor(DD)); + } } else { // Add the return adjustment if necessary. if (!ReturnAdjustment.isEmpty()) @@ -1612,14 +1621,19 @@ VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base, if (Base.getBase() == MostDerivedClass) VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets(); - // Add the offset to top. - CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass; - Components.push_back( - VTableComponent::MakeOffsetToTop(OffsetToTop)); - - // Next, add the RTTI. - Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass)); - + // FIXME: Should probably add a layer of abstraction for vtable generation. + if (!isMicrosoftABI()) { + // Add the offset to top. + CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass; + Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop)); + + // Next, add the RTTI. + Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass)); + } else { + // FIXME: unclear what to do with RTTI in MS ABI as emitting it anywhere + // breaks the vftable layout. Just skip RTTI for now, can't mangle anyway. + } + uint64_t AddressPoint = Components.size(); // Now go through all virtual member functions and add them. @@ -1936,6 +1950,8 @@ void VTableBuilder::dumpLayout(raw_ostream& Out) { Out << DD->getQualifiedNameAsString(); if (IsComplete) Out << "() [complete]"; + else if (isMicrosoftABI()) + Out << "() [scalar deleting]"; else Out << "() [deleting]"; @@ -2120,10 +2136,16 @@ void VTableBuilder::dumpLayout(raw_ostream& Out) { MD); if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { - IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Complete))] = - MethodName + " [complete]"; - IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))] = - MethodName + " [deleting]"; + // FIXME: Should add a layer of abstraction for vtable generation. + if (!isMicrosoftABI()) { + IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Complete))] + = MethodName + " [complete]"; + IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))] + = MethodName + " [deleting]"; + } else { + IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))] + = MethodName + " [scalar deleting]"; + } } else { IndicesMap[VTables.getMethodVTableIndex(MD)] = MethodName; } @@ -2154,12 +2176,14 @@ VTableLayout::VTableLayout(uint64_t NumVTableComponents, const VTableComponent *VTableComponents, uint64_t NumVTableThunks, const VTableThunkTy *VTableThunks, - const AddressPointsMapTy &AddressPoints) + const AddressPointsMapTy &AddressPoints, + bool IsMicrosoftABI) : NumVTableComponents(NumVTableComponents), VTableComponents(new VTableComponent[NumVTableComponents]), NumVTableThunks(NumVTableThunks), VTableThunks(new VTableThunkTy[NumVTableThunks]), - AddressPoints(AddressPoints) { + AddressPoints(AddressPoints), + IsMicrosoftABI(IsMicrosoftABI) { std::copy(VTableComponents, VTableComponents+NumVTableComponents, this->VTableComponents.get()); std::copy(VTableThunks, VTableThunks+NumVTableThunks, @@ -2168,6 +2192,11 @@ VTableLayout::VTableLayout(uint64_t NumVTableComponents, VTableLayout::~VTableLayout() { } +VTableContext::VTableContext(ASTContext &Context) + : Context(Context), + IsMicrosoftABI(Context.getTargetInfo().getCXXABI().isMicrosoft()) { +} + VTableContext::~VTableContext() { llvm::DeleteContainerSeconds(VTableLayouts); } @@ -2239,12 +2268,18 @@ void VTableContext::ComputeMethodVTableIndices(const CXXRecordDecl *RD) { if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { const CXXDestructorDecl *OverriddenDD = cast<CXXDestructorDecl>(OverriddenMD); - - // Add both the complete and deleting entries. - MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = - getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Complete)); - MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = - getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting)); + + if (!isMicrosoftABI()) { + // Add both the complete and deleting entries. + MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = + getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Complete)); + MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = + getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting)); + } else { + // Add the scalar deleting destructor. + MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = + getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting)); + } } else { MethodVTableIndices[MD] = getMethodVTableIndex(OverriddenMD); } @@ -2262,11 +2297,16 @@ void VTableContext::ComputeMethodVTableIndices(const CXXRecordDecl *RD) { continue; } - // Add the complete dtor. - MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++; - - // Add the deleting dtor. - MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++; + if (!isMicrosoftABI()) { + // Add the complete dtor. + MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++; + + // Add the deleting dtor. + MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++; + } else { + // Add the scalar deleting dtor. + MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++; + } } else { // Add the entry. MethodVTableIndices[MD] = CurrentIndex++; @@ -2278,6 +2318,11 @@ void VTableContext::ComputeMethodVTableIndices(const CXXRecordDecl *RD) { // If a class has an implicitly-defined virtual destructor, // its entries come after the declared virtual function pointers. + if (isMicrosoftABI()) { + ErrorUnsupported("implicit virtual destructor in the Microsoft ABI", + ImplicitVirtualDtor->getLocation()); + } + // Add the complete dtor. MethodVTableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Complete)] = CurrentIndex++; @@ -2357,7 +2402,8 @@ static VTableLayout *CreateVTableLayout(const VTableBuilder &Builder) { Builder.vtable_component_begin(), VTableThunks.size(), VTableThunks.data(), - Builder.getAddressPoints()); + Builder.getAddressPoints(), + Builder.isMicrosoftABI()); } void VTableContext::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) { @@ -2397,6 +2443,14 @@ void VTableContext::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) { } } +void VTableContext::ErrorUnsupported(StringRef Feature, + SourceLocation Location) { + clang::DiagnosticsEngine &Diags = Context.getDiagnostics(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "v-table layout for %0 is not supported yet"); + Diags.Report(Context.getFullLoc(Location), DiagID) << Feature; +} + VTableLayout *VTableContext::createConstructionVTableLayout( const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, |