From 9cedb8bb69b89b0f0c529937247a6a80cabdbaec Mon Sep 17 00:00:00 2001 From: dim Date: Fri, 21 Mar 2014 17:53:59 +0000 Subject: MFC 261991: Upgrade our copy of llvm/clang to 3.4 release. This version supports all of the features in the current working draft of the upcoming C++ standard, provisionally named C++1y. The code generator's performance is greatly increased, and the loop auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The PowerPC backend has made several major improvements to code generation quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ backends have all seen major feature work. Release notes for llvm and clang can be found here: MFC 262121 (by emaste): Update lldb for clang/llvm 3.4 import This commit largely restores the lldb source to the upstream r196259 snapshot with the addition of threaded inferior support and a few bug fixes. Specific upstream lldb revisions restored include: SVN git 181387 779e6ac 181703 7bef4e2 182099 b31044e 182650 f2dcf35 182683 0d91b80 183862 15c1774 183929 99447a6 184177 0b2934b 184948 4dc3761 184954 007e7bc 186990 eebd175 Sponsored by: DARPA, AFRL MFC 262186 (by emaste): Fix mismerge in r262121 A break statement was lost in the merge. The error had no functional impact, but restore it to reduce the diff against upstream. MFC 262303: Pull in r197521 from upstream clang trunk (by rdivacky): Use the integrated assembler by default on FreeBSD/ppc and ppc64. Requested by: jhibbits MFC 262611: Pull in r196874 from upstream llvm trunk: Fix a crash that occurs when PWD is invalid. MCJIT needs to be able to run in hostile environments, even when PWD is invalid. There's no need to crash MCJIT in this case. The obvious fix is to simply leave MCContext's CompilationDir empty when PWD can't be determined. This way, MCJIT clients, and other clients that link with LLVM don't need a valid working directory. If we do want to guarantee valid CompilationDir, that should be done only for clients of getCompilationDir(). This is as simple as checking for an empty string. The only current use of getCompilationDir is EmitGenDwarfInfo, which won't conceivably run with an invalid working dir. However, in the purely hypothetically and untestable case that this happens, the AT_comp_dir will be omitted from the compilation_unit DIE. This should help fix assertions occurring with ports-mgmt/tinderbox, when it is using jails, and sometimes invalidates clang's current working directory. Reported by: decke MFC 262809: Pull in r203007 from upstream clang trunk: Don't produce an alias between destructors with different calling conventions. Fixes pr19007. (Please note that is an LLVM PR identifier, not a FreeBSD one.) This should fix Firefox and/or libxul crashes (due to problems with regparm/stdcall calling conventions) on i386. Reported by: multiple users on freebsd-current PR: bin/187103 MFC 263048: Repair recognition of "CC" as an alias for the C++ compiler, since it was silently broken by upstream for a Windows-specific use-case. Apparently some versions of CMake still rely on this archaic feature... Reported by: rakuco MFC 263049: Garbage collect the old way of adding the libstdc++ include directories in clang's InitHeaderSearch.cpp. This has been superseded by David Chisnall's commit in r255321. Moreover, if libc++ is used, the libstdc++ include directories should not be in the search path at all. These directories are now only used if you pass -stdlib=libstdc++. --- contrib/llvm/tools/clang/lib/AST/APValue.cpp | 34 + contrib/llvm/tools/clang/lib/AST/ASTContext.cpp | 816 +++++--- contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp | 83 +- contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp | 219 ++- contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp | 291 ++- contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp | 105 ++ contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp | 1 + contrib/llvm/tools/clang/lib/AST/CXXABI.h | 8 +- .../llvm/tools/clang/lib/AST/CXXInheritance.cpp | 14 +- contrib/llvm/tools/clang/lib/AST/Comment.cpp | 15 +- .../tools/clang/lib/AST/CommentCommandTraits.cpp | 43 + contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp | 21 +- contrib/llvm/tools/clang/lib/AST/CommentParser.cpp | 21 + contrib/llvm/tools/clang/lib/AST/CommentSema.cpp | 145 +- contrib/llvm/tools/clang/lib/AST/Decl.cpp | 800 +++++--- contrib/llvm/tools/clang/lib/AST/DeclBase.cpp | 195 +- contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp | 198 +- contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp | 5 + contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp | 86 +- contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp | 11 +- contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp | 29 +- contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp | 357 +++- .../llvm/tools/clang/lib/AST/DeclarationName.cpp | 142 +- contrib/llvm/tools/clang/lib/AST/DumpXML.cpp | 1055 ----------- contrib/llvm/tools/clang/lib/AST/Expr.cpp | 462 +++-- contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp | 268 ++- .../tools/clang/lib/AST/ExprClassification.cpp | 13 +- contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp | 1981 +++++++++++++++----- contrib/llvm/tools/clang/lib/AST/InheritViz.cpp | 38 +- contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp | 18 + contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp | 577 ++++-- .../tools/clang/lib/AST/LambdaMangleContext.cpp | 33 - contrib/llvm/tools/clang/lib/AST/Mangle.cpp | 153 +- .../tools/clang/lib/AST/MangleNumberingContext.cpp | 43 + .../llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp | 21 + .../llvm/tools/clang/lib/AST/MicrosoftMangle.cpp | 990 ++++++---- .../tools/clang/lib/AST/NestedNameSpecifier.cpp | 3 +- contrib/llvm/tools/clang/lib/AST/ParentMap.cpp | 30 +- .../llvm/tools/clang/lib/AST/RawCommentList.cpp | 106 +- contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp | 9 +- .../tools/clang/lib/AST/RecordLayoutBuilder.cpp | 1484 +++++++++------ contrib/llvm/tools/clang/lib/AST/Stmt.cpp | 266 ++- contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp | 63 +- contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp | 112 +- contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp | 75 +- contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp | 81 +- contrib/llvm/tools/clang/lib/AST/Type.cpp | 126 +- contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp | 53 +- contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp | 134 +- contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp | 1662 ++++++++++++---- 50 files changed, 8705 insertions(+), 4790 deletions(-) create mode 100644 contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp delete mode 100644 contrib/llvm/tools/clang/lib/AST/DumpXML.cpp delete mode 100644 contrib/llvm/tools/clang/lib/AST/LambdaMangleContext.cpp create mode 100644 contrib/llvm/tools/clang/lib/AST/MangleNumberingContext.cpp (limited to 'contrib/llvm/tools/clang/lib/AST') diff --git a/contrib/llvm/tools/clang/lib/AST/APValue.cpp b/contrib/llvm/tools/clang/lib/AST/APValue.cpp index 98e825b..541836b21b 100644 --- a/contrib/llvm/tools/clang/lib/AST/APValue.cpp +++ b/contrib/llvm/tools/clang/lib/AST/APValue.cpp @@ -212,6 +212,40 @@ void APValue::DestroyDataAndMakeUninit() { Kind = Uninitialized; } +bool APValue::needsCleanup() const { + switch (getKind()) { + case Uninitialized: + case AddrLabelDiff: + return false; + case Struct: + case Union: + case Array: + case Vector: + return true; + case Int: + return getInt().needsCleanup(); + case Float: + return getFloat().needsCleanup(); + case ComplexFloat: + assert(getComplexFloatImag().needsCleanup() == + getComplexFloatReal().needsCleanup() && + "In _Complex float types, real and imaginary values always have the " + "same size."); + return getComplexFloatReal().needsCleanup(); + case ComplexInt: + assert(getComplexIntImag().needsCleanup() == + getComplexIntReal().needsCleanup() && + "In _Complex int types, real and imaginary values must have the " + "same size."); + return getComplexIntReal().needsCleanup(); + case LValue: + return reinterpret_cast(Data)->hasPathPtr(); + case MemberPointer: + return reinterpret_cast(Data)->hasPathPtr(); + } + llvm_unreachable("Unknown APValue kind!"); +} + void APValue::swap(APValue &RHS) { std::swap(Kind, RHS.Kind); char TmpData[MaxSize]; diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index 176aec5..a03cf9e7 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -25,13 +25,16 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Mangle.h" +#include "clang/AST/MangleNumberingContext.h" #include "clang/AST/RecordLayout.h" +#include "clang/AST/RecursiveASTVisitor.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/ADT/Triple.h" #include "llvm/Support/Capacity.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -132,8 +135,14 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { isa(D) || isa(D)) DeclLoc = D->getLocStart(); - else + else { DeclLoc = D->getLocation(); + // If location of the typedef name is in a macro, it is because being + // declared via a macro. Try using declaration's starting location + // as the "declaration location". + if (DeclLoc.isMacroID() && isa(D)) + DeclLoc = D->getLocStart(); + } // If the declaration doesn't map directly to a location in a file, we // can't find the comment. @@ -175,7 +184,8 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // First check whether we have a trailing comment. if (Comment != RawComments.end() && (*Comment)->isDocumentation() && (*Comment)->isTrailingComment() && - (isa(D) || isa(D) || isa(D))) { + (isa(D) || isa(D) || isa(D) || + isa(D) || isa(D))) { std::pair CommentBeginDecomp = SourceMgr.getDecomposedLoc((*Comment)->getSourceRange().getBegin()); // Check that Doxygen trailing comment comes after the declaration, starts @@ -220,7 +230,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // There should be no other declarations or preprocessor directives between // comment and declaration. - if (Text.find_first_of(",;{}#@") != StringRef::npos) + if (Text.find_first_of(";{}#@") != StringRef::npos) return NULL; return *Comment; @@ -406,9 +416,16 @@ comments::FullComment *ASTContext::cloneFullComment(comments::FullComment *FC, } +comments::FullComment *ASTContext::getLocalCommentForDeclUncached(const Decl *D) const { + const RawComment *RC = getRawCommentForDeclNoCache(D); + return RC ? RC->parse(*this, 0, D) : 0; +} + comments::FullComment *ASTContext::getCommentForDecl( const Decl *D, const Preprocessor *PP) const { + if (D->isInvalidDecl()) + return NULL; D = adjustDeclToTemplate(D); const Decl *Canonical = D->getCanonicalDecl(); @@ -679,6 +696,19 @@ static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T, } } +static bool isAddrSpaceMapManglingEnabled(const TargetInfo &TI, + const LangOptions &LangOpts) { + switch (LangOpts.getAddressSpaceMapMangling()) { + case LangOptions::ASMM_Target: + return TI.useAddressSpaceMapMangling(); + case LangOptions::ASMM_On: + return true; + case LangOptions::ASMM_Off: + return false; + } + llvm_unreachable("getAddressSpaceMapMangling() doesn't cover anything."); +} + ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, const TargetInfo *t, IdentifierTable &idents, SelectorTable &sels, @@ -690,7 +720,7 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, DependentTemplateSpecializationTypes(this_()), SubstTemplateTemplateParmPacks(this_()), GlobalNestedNameSpecifier(0), - Int128Decl(0), UInt128Decl(0), + Int128Decl(0), UInt128Decl(0), Float128StubDecl(0), BuiltinVaListDecl(0), ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0), ObjCProtocolClassDecl(0), BOOLDecl(0), @@ -709,8 +739,7 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, ExternalSource(0), Listener(0), Comments(SM), CommentsLoaded(false), CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), - LastSDM(0, 0), - UniqueBlockByRefTypeID(0) + LastSDM(0, 0) { if (size_reserve > 0) Types.reserve(size_reserve); TUDecl = TranslationUnitDecl::Create(*this); @@ -726,10 +755,12 @@ ASTContext::~ASTContext() { // FIXME: Is this the ideal solution? ReleaseDeclContextMaps(); - // Call all of the deallocation functions. - for (unsigned I = 0, N = Deallocations.size(); I != N; ++I) - Deallocations[I].first(Deallocations[I].second); - + // Call all of the deallocation functions on all of their targets. + for (DeallocationMap::const_iterator I = Deallocations.begin(), + E = Deallocations.end(); I != E; ++I) + for (unsigned J = 0, N = I->second.size(); J != N; ++J) + (I->first)((I->second)[J]); + // ASTRecordLayout objects in ASTRecordLayouts must always be destroyed // because they can contain DenseMaps. for (llvm::DenseMapsecond->~AttrVec(); + + for (llvm::DenseMap::iterator + I = MangleNumberingContexts.begin(), + E = MangleNumberingContexts.end(); + I != E; ++I) + delete I->second; } void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { - Deallocations.push_back(std::make_pair(Callback, Data)); + Deallocations[Callback].push_back(Data); } void @@ -848,6 +885,20 @@ TypedefDecl *ASTContext::getUInt128Decl() const { return UInt128Decl; } +TypeDecl *ASTContext::getFloat128StubType() const { + assert(LangOpts.CPlusPlus && "should only be called for c++"); + if (!Float128StubDecl) { + Float128StubDecl = CXXRecordDecl::Create(const_cast(*this), + TTK_Struct, + getTranslationUnitDecl(), + SourceLocation(), + SourceLocation(), + &Idents.get("__float128")); + } + + return Float128StubDecl; +} + void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) { BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K); R = CanQualType::CreateUnsafe(QualType(Ty, 0)); @@ -863,6 +914,7 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { ABI.reset(createCXXABI(Target)); AddrSpaceMap = getAddressSpaceMap(Target, LangOpts); + AddrSpaceMapMangling = isAddrSpaceMapManglingEnabled(Target, LangOpts); // C99 6.2.5p19. InitBuiltinType(VoidTy, BuiltinType::Void); @@ -897,13 +949,17 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { InitBuiltinType(Int128Ty, BuiltinType::Int128); InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128); - if (LangOpts.CPlusPlus && LangOpts.WChar) { // C++ 3.9.1p5 - if (TargetInfo::isTypeSigned(Target.getWCharType())) - InitBuiltinType(WCharTy, BuiltinType::WChar_S); - else // -fshort-wchar makes wchar_t be unsigned. - InitBuiltinType(WCharTy, BuiltinType::WChar_U); - } else // C99 (or C++ using -fno-wchar) - WCharTy = getFromTargetType(Target.getWCharType()); + // C++ 3.9.1p5 + if (TargetInfo::isTypeSigned(Target.getWCharType())) + InitBuiltinType(WCharTy, BuiltinType::WChar_S); + else // -fshort-wchar makes wchar_t be unsigned. + InitBuiltinType(WCharTy, BuiltinType::WChar_U); + if (LangOpts.CPlusPlus && LangOpts.WChar) + WideCharTy = WCharTy; + else { + // C99 (or C++ using -fno-wchar). + WideCharTy = getFromTargetType(Target.getWCharType()); + } WIntTy = getFromTargetType(Target.getWIntType()); @@ -1008,13 +1064,20 @@ void ASTContext::eraseDeclAttrs(const Decl *D) { } } +// FIXME: Remove ? MemberSpecializationInfo * ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) { assert(Var->isStaticDataMember() && "Not a static data member"); - llvm::DenseMap::iterator Pos - = InstantiatedFromStaticDataMember.find(Var); - if (Pos == InstantiatedFromStaticDataMember.end()) - return 0; + return getTemplateOrSpecializationInfo(Var) + .dyn_cast(); +} + +ASTContext::TemplateOrSpecializationInfo +ASTContext::getTemplateOrSpecializationInfo(const VarDecl *Var) { + llvm::DenseMap::iterator Pos = + TemplateOrInstantiation.find(Var); + if (Pos == TemplateOrInstantiation.end()) + return TemplateOrSpecializationInfo(); return Pos->second; } @@ -1025,10 +1088,16 @@ ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, SourceLocation PointOfInstantiation) { assert(Inst->isStaticDataMember() && "Not a static data member"); assert(Tmpl->isStaticDataMember() && "Not a static data member"); - assert(!InstantiatedFromStaticDataMember[Inst] && - "Already noted what static data member was instantiated from"); - InstantiatedFromStaticDataMember[Inst] - = new (*this) MemberSpecializationInfo(Tmpl, TSK, PointOfInstantiation); + setTemplateOrSpecializationInfo(Inst, new (*this) MemberSpecializationInfo( + Tmpl, TSK, PointOfInstantiation)); +} + +void +ASTContext::setTemplateOrSpecializationInfo(VarDecl *Inst, + TemplateOrSpecializationInfo TSI) { + assert(!TemplateOrInstantiation[Inst] && + "Already noted what the variable was instantiated from"); + TemplateOrInstantiation[Inst] = TSI; } FunctionDecl *ASTContext::getClassScopeSpecializationPattern( @@ -1105,38 +1174,6 @@ void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, InstantiatedFromUnnamedFieldDecl[Inst] = Tmpl; } -bool ASTContext::ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const { - return (FD->isBitField() && LastFD && !LastFD->isBitField() && - FD->getBitWidthValue(*this) == 0); -} - -bool ASTContext::ZeroBitfieldFollowsBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const { - return (FD->isBitField() && LastFD && LastFD->isBitField() && - FD->getBitWidthValue(*this) == 0 && - LastFD->getBitWidthValue(*this) != 0); -} - -bool ASTContext::BitfieldFollowsBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const { - return (FD->isBitField() && LastFD && LastFD->isBitField() && - FD->getBitWidthValue(*this) && - LastFD->getBitWidthValue(*this)); -} - -bool ASTContext::NonBitfieldFollowsBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const { - return (!FD->isBitField() && LastFD && LastFD->isBitField() && - LastFD->getBitWidthValue(*this)); -} - -bool ASTContext::BitfieldFollowsNonBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const { - return (FD->isBitField() && LastFD && !LastFD->isBitField() && - FD->getBitWidthValue(*this)); -} - ASTContext::overridden_cxx_method_iterator ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const { llvm::DenseMap::const_iterator Pos @@ -1224,12 +1261,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { } } -/// getDeclAlign - Return a conservative estimate of the alignment of the -/// specified decl. Note that bitfields do not have a valid alignment, so -/// this method will assert on them. -/// If @p RefAsPointee, references are treated like their underlying type -/// (for alignof), else they're treated like pointers (for CodeGen). -CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { +CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { unsigned Align = Target->getCharWidth(); bool UseAlignAttrOnly = false; @@ -1262,7 +1294,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { } else if (const ValueDecl *VD = dyn_cast(D)) { QualType T = VD->getType(); if (const ReferenceType* RT = T->getAs()) { - if (RefAsPointee) + if (ForAlignof) T = RT->getPointeeType(); else T = getPointerType(RT->getPointeeType()); @@ -1270,14 +1302,15 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { if (!T->isIncompleteType() && !T->isFunctionType()) { // Adjust alignments of declarations with array type by the // large-array alignment on the target. - unsigned MinWidth = Target->getLargeArrayMinWidth(); - const ArrayType *arrayType; - if (MinWidth && (arrayType = getAsArrayType(T))) { - if (isa(arrayType)) - Align = std::max(Align, Target->getLargeArrayAlign()); - else if (isa(arrayType) && - MinWidth <= getTypeSize(cast(arrayType))) - Align = std::max(Align, Target->getLargeArrayAlign()); + if (const ArrayType *arrayType = getAsArrayType(T)) { + unsigned MinWidth = Target->getLargeArrayMinWidth(); + if (!ForAlignof && MinWidth) { + if (isa(arrayType)) + Align = std::max(Align, Target->getLargeArrayAlign()); + else if (isa(arrayType) && + MinWidth <= getTypeSize(cast(arrayType))) + Align = std::max(Align, Target->getLargeArrayAlign()); + } // Walk through any array types while we're at it. T = getBaseElementType(arrayType); @@ -1294,24 +1327,27 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { // a max-field-alignment constraint (#pragma pack). So calculate // the actual alignment of the field within the struct, and then // (as we're expected to) constrain that by the alignment of the type. - if (const FieldDecl *field = dyn_cast(VD)) { - // So calculate the alignment of the field. - const ASTRecordLayout &layout = getASTRecordLayout(field->getParent()); - - // Start with the record's overall alignment. - unsigned fieldAlign = toBits(layout.getAlignment()); - - // Use the GCD of that and the offset within the record. - uint64_t offset = layout.getFieldOffset(field->getFieldIndex()); - if (offset > 0) { - // Alignment is always a power of 2, so the GCD will be a power of 2, - // which means we get to do this crazy thing instead of Euclid's. - uint64_t lowBitOfOffset = offset & (~offset + 1); - if (lowBitOfOffset < fieldAlign) - fieldAlign = static_cast(lowBitOfOffset); - } + if (const FieldDecl *Field = dyn_cast(VD)) { + const RecordDecl *Parent = Field->getParent(); + // We can only produce a sensible answer if the record is valid. + if (!Parent->isInvalidDecl()) { + const ASTRecordLayout &Layout = getASTRecordLayout(Parent); + + // Start with the record's overall alignment. + unsigned FieldAlign = toBits(Layout.getAlignment()); + + // Use the GCD of that and the offset within the record. + uint64_t Offset = Layout.getFieldOffset(Field->getFieldIndex()); + if (Offset > 0) { + // Alignment is always a power of 2, so the GCD will be a power of 2, + // which means we get to do this crazy thing instead of Euclid's. + uint64_t LowBitOfOffset = Offset & (~Offset + 1); + if (LowBitOfOffset < FieldAlign) + FieldAlign = static_cast(LowBitOfOffset); + } - Align = std::min(Align, fieldAlign); + Align = std::min(Align, FieldAlign); + } } } @@ -1339,8 +1375,30 @@ ASTContext::getTypeInfoDataSizeInChars(QualType T) const { return sizeAndAlign; } +/// getConstantArrayInfoInChars - Performing the computation in CharUnits +/// instead of in bits prevents overflowing the uint64_t for some large arrays. +std::pair +static getConstantArrayInfoInChars(const ASTContext &Context, + const ConstantArrayType *CAT) { + std::pair EltInfo = + Context.getTypeInfoInChars(CAT->getElementType()); + uint64_t Size = CAT->getSize().getZExtValue(); + assert((Size == 0 || static_cast(EltInfo.first.getQuantity()) <= + (uint64_t)(-1)/Size) && + "Overflow in array type char size evaluation"); + uint64_t Width = EltInfo.first.getQuantity() * Size; + unsigned Align = EltInfo.second.getQuantity(); + if (!Context.getTargetInfo().getCXXABI().isMicrosoft() || + Context.getTargetInfo().getPointerWidth(0) == 64) + Width = llvm::RoundUpToAlignment(Width, Align); + return std::make_pair(CharUnits::fromQuantity(Width), + CharUnits::fromQuantity(Align)); +} + std::pair ASTContext::getTypeInfoInChars(const Type *T) const { + if (const ConstantArrayType *CAT = dyn_cast(T)) + return getConstantArrayInfoInChars(*this, CAT); std::pair Info = getTypeInfo(T); return std::make_pair(toCharUnitsFromBits(Info.first), toCharUnitsFromBits(Info.second)); @@ -1376,6 +1434,10 @@ ASTContext::getTypeInfoImpl(const Type *T) const { #define ABSTRACT_TYPE(Class, Base) #define NON_CANONICAL_TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) \ + case Type::Class: \ + assert(!T->isDependentType() && "should not see dependent types here"); \ + return getTypeInfo(cast(T)->desugar().getTypePtr()); #include "clang/AST/TypeNodes.def" llvm_unreachable("Should not see dependent types"); @@ -1401,7 +1463,9 @@ ASTContext::getTypeInfoImpl(const Type *T) const { "Overflow in array type bit size evaluation"); Width = EltInfo.first*Size; Align = EltInfo.second; - Width = llvm::RoundUpToAlignment(Width, Align); + if (!getTargetInfo().getCXXABI().isMicrosoft() || + getTargetInfo().getPointerWidth(0) == 64) + Width = llvm::RoundUpToAlignment(Width, Align); break; } case Type::ExtVector: @@ -1568,6 +1632,8 @@ ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::ObjCObject: return getTypeInfo(cast(T)->getBaseType().getTypePtr()); + case Type::Decayed: + return getTypeInfo(cast(T)->getDecayedType().getTypePtr()); case Type::ObjCInterface: { const ObjCInterfaceType *ObjCI = cast(T); const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl()); @@ -1624,20 +1690,6 @@ ASTContext::getTypeInfoImpl(const Type *T) const { break; } - case Type::TypeOfExpr: - return getTypeInfo(cast(T)->getUnderlyingExpr()->getType() - .getTypePtr()); - - case Type::TypeOf: - return getTypeInfo(cast(T)->getUnderlyingType().getTypePtr()); - - case Type::Decltype: - return getTypeInfo(cast(T)->getUnderlyingExpr()->getType() - .getTypePtr()); - - case Type::UnaryTransform: - return getTypeInfo(cast(T)->getUnderlyingType()); - case Type::Elaborated: return getTypeInfo(cast(T)->getNamedType().getTypePtr()); @@ -1645,18 +1697,6 @@ ASTContext::getTypeInfoImpl(const Type *T) const { return getTypeInfo( cast(T)->getEquivalentType().getTypePtr()); - case Type::TemplateSpecialization: { - assert(getCanonicalType(T) != T && - "Cannot request the size of a dependent type"); - const TemplateSpecializationType *TST = cast(T); - // A type alias template specialization may refer to a typedef with the - // aligned attribute on it. - if (TST->isTypeAlias()) - return getTypeInfo(TST->getAliasedType().getTypePtr()); - else - return getTypeInfo(getCanonicalType(T)); - } - case Type::Atomic: { // Start with the base type information. std::pair Info @@ -1696,10 +1736,10 @@ int64_t ASTContext::toBits(CharUnits CharSize) const { /// getTypeSizeInChars - Return the size of the specified type, in characters. /// This method does not work on incomplete types. CharUnits ASTContext::getTypeSizeInChars(QualType T) const { - return toCharUnitsFromBits(getTypeSize(T)); + return getTypeInfoInChars(T).first; } CharUnits ASTContext::getTypeSizeInChars(const Type *T) const { - return toCharUnitsFromBits(getTypeSize(T)); + return getTypeInfoInChars(T).first; } /// getTypeAlignInChars - Return the ABI-specified alignment of a type, in @@ -1718,6 +1758,9 @@ CharUnits ASTContext::getTypeAlignInChars(const Type *T) const { unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { unsigned ABIAlign = getTypeAlign(T); + if (Target->getTriple().getArch() == llvm::Triple::xcore) + return ABIAlign; // Never overalign on XCore. + // Double and long long should be naturally aligned if possible. if (const ComplexType* CT = T->getAs()) T = CT->getElementType().getTypePtr(); @@ -2042,10 +2085,7 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, const FunctionProtoType *FPT = cast(T); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = Info; - Result = getFunctionType(FPT->getResultType(), - ArrayRef(FPT->arg_type_begin(), - FPT->getNumArgs()), - EPI); + Result = getFunctionType(FPT->getResultType(), FPT->getArgTypes(), EPI); } return cast(Result.getTypePtr()); @@ -2053,12 +2093,18 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType) { - // FIXME: Need to inform serialization code about this! - for (FD = FD->getMostRecentDecl(); FD; FD = FD->getPreviousDecl()) { + FD = FD->getMostRecentDecl(); + while (true) { const FunctionProtoType *FPT = FD->getType()->castAs(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); FD->setType(getFunctionType(ResultType, FPT->getArgTypes(), EPI)); + if (FunctionDecl *Next = FD->getPreviousDecl()) + FD = Next; + else + break; } + if (ASTMutationListener *L = getASTMutationListener()) + L->DeducedReturnType(FD, ResultType); } /// getComplexType - Return the uniqued reference to the type for a complex @@ -2117,6 +2163,45 @@ QualType ASTContext::getPointerType(QualType T) const { return QualType(New, 0); } +QualType ASTContext::getDecayedType(QualType T) const { + assert((T->isArrayType() || T->isFunctionType()) && "T does not decay"); + + llvm::FoldingSetNodeID ID; + DecayedType::Profile(ID, T); + void *InsertPos = 0; + if (DecayedType *DT = DecayedTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(DT, 0); + + QualType Decayed; + + // C99 6.7.5.3p7: + // A declaration of a parameter as "array of type" shall be + // adjusted to "qualified pointer to type", where the type + // qualifiers (if any) are those specified within the [ and ] of + // the array type derivation. + if (T->isArrayType()) + Decayed = getArrayDecayedType(T); + + // C99 6.7.5.3p8: + // A declaration of a parameter as "function returning type" + // shall be adjusted to "pointer to function returning type", as + // in 6.3.2.1. + if (T->isFunctionType()) + Decayed = getPointerType(T); + + QualType Canonical = getCanonicalType(Decayed); + + // Get the new insert position for the node we care about. + DecayedType *NewIP = DecayedTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + + DecayedType *New = + new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical); + Types.push_back(New); + DecayedTypes.InsertNode(New, InsertPos); + return QualType(New, 0); +} + /// getBlockPointerType - Return the uniqued reference to the type for /// a pointer to the specified block. QualType ASTContext::getBlockPointerType(QualType T) const { @@ -2676,9 +2761,8 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType, QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const { - const CallingConv DefaultCC = Info.getCC(); - const CallingConv CallConv = (LangOpts.MRTD && DefaultCC == CC_Default) ? - CC_X86StdCall : DefaultCC; + const CallingConv CallConv = Info.getCC(); + // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; @@ -2690,11 +2774,8 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy, return QualType(FT, 0); QualType Canonical; - if (!ResultTy.isCanonical() || - getCanonicalCallConv(CallConv) != CallConv) { - Canonical = - getFunctionNoProtoType(getCanonicalType(ResultTy), - Info.withCallingConv(getCanonicalCallConv(CallConv))); + if (!ResultTy.isCanonical()) { + Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), Info); // Get the new insert position for the node we care about. FunctionNoProtoType *NewIP = @@ -2743,14 +2824,10 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef ArgArray, if (!ArgArray[i].isCanonicalAsParam()) isCanonical = false; - const CallingConv DefaultCC = EPI.ExtInfo.getCC(); - const CallingConv CallConv = (LangOpts.MRTD && DefaultCC == CC_Default) ? - CC_X86StdCall : DefaultCC; - // If this type isn't canonical, get the canonical version of it. // The exception spec is not part of the canonical type. QualType Canonical; - if (!isCanonical || getCanonicalCallConv(CallConv) != CallConv) { + if (!isCanonical) { SmallVector CanonicalArgs; CanonicalArgs.reserve(NumArgs); for (unsigned i = 0; i != NumArgs; ++i) @@ -2760,8 +2837,6 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef ArgArray, CanonicalEPI.HasTrailingReturn = false; CanonicalEPI.ExceptionSpecType = EST_None; CanonicalEPI.NumExceptions = 0; - CanonicalEPI.ExtInfo - = CanonicalEPI.ExtInfo.withCallingConv(getCanonicalCallConv(CallConv)); // Result types do not have ARC lifetime qualifiers. QualType CanResultTy = getCanonicalType(ResultTy); @@ -2803,7 +2878,6 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef ArgArray, FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); FunctionProtoType::ExtProtoInfo newEPI = EPI; - newEPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallConv); new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI); Types.push_back(FTP); FunctionProtoTypes.InsertNode(FTP, InsertPos); @@ -2856,13 +2930,11 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const { "Template type parameter types are always available."); if (const RecordDecl *Record = dyn_cast(Decl)) { - assert(!Record->getPreviousDecl() && - "struct/union has previous declaration"); + assert(Record->isFirstDecl() && "struct/union has previous declaration"); assert(!NeedsInjectedClassNameType(Record)); return getRecordType(Record); } else if (const EnumDecl *Enum = dyn_cast(Decl)) { - assert(!Enum->getPreviousDecl() && - "enum has previous declaration"); + assert(Enum->isFirstDecl() && "enum has previous declaration"); return getEnumType(Enum); } else if (const UnresolvedUsingTypenameDecl *Using = dyn_cast(Decl)) { @@ -4104,22 +4176,9 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { } QualType ASTContext::getAdjustedParameterType(QualType T) const { - // C99 6.7.5.3p7: - // A declaration of a parameter as "array of type" shall be - // adjusted to "qualified pointer to type", where the type - // qualifiers (if any) are those specified within the [ and ] of - // the array type derivation. - if (T->isArrayType()) - return getArrayDecayedType(T); - - // C99 6.7.5.3p8: - // A declaration of a parameter as "function returning type" - // shall be adjusted to "pointer to function returning type", as - // in 6.3.2.1. - if (T->isFunctionType()) - return getPointerType(T); - - return T; + if (T->isArrayType() || T->isFunctionType()) + return getDecayedType(T); + return T; } QualType ASTContext::getSignatureParameterType(QualType T) const { @@ -4364,12 +4423,27 @@ Qualifiers::ObjCLifetime ASTContext::getInnerObjCOwnership(QualType T) const { return Qualifiers::OCL_None; } +static const Type *getIntegerTypeForEnum(const EnumType *ET) { + // Incomplete enum types are not treated as integer types. + // FIXME: In C++, enum types are never integer types. + if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped()) + return ET->getDecl()->getIntegerType().getTypePtr(); + return NULL; +} + /// getIntegerTypeOrder - Returns the highest ranked integer type: /// C99 6.3.1.8p1. If LHS > RHS, return 1. If LHS == RHS, return 0. If /// LHS < RHS, return -1. int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) const { const Type *LHSC = getCanonicalType(LHS).getTypePtr(); const Type *RHSC = getCanonicalType(RHS).getTypePtr(); + + // Unwrap enums to their underlying type. + if (const EnumType *ET = dyn_cast(LHSC)) + LHSC = getIntegerTypeForEnum(ET); + if (const EnumType *ET = dyn_cast(RHSC)) + RHSC = getIntegerTypeForEnum(ET); + if (LHSC == RHSC) return 0; bool LHSUnsigned = LHSC->isUnsignedIntegerType(); @@ -4484,7 +4558,7 @@ QualType ASTContext::getBlockDescriptorType() const { UnsignedLongTy, }; - const char *FieldNames[] = { + static const char *const FieldNames[] = { "reserved", "Size" }; @@ -4525,7 +4599,7 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { getPointerType(VoidPtrTy) }; - const char *FieldNames[] = { + static const char *const FieldNames[] = { "reserved", "Size", "CopyFuncPtr", @@ -4910,6 +4984,10 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, if (PD->isReadOnly()) { S += ",R"; + if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) + S += ",C"; + if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) + S += ",&"; } else { switch (PD->getSetterKind()) { case ObjCPropertyDecl::Assign: break; @@ -5200,12 +5278,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } else { S += '['; - if (const ConstantArrayType *CAT = dyn_cast(AT)) { - if (getTypeSize(CAT->getElementType()) == 0) - S += '0'; - else - S += llvm::utostr(CAT->getSize().getZExtValue()); - } else { + if (const ConstantArrayType *CAT = dyn_cast(AT)) + S += llvm::utostr(CAT->getSize().getZExtValue()); + else { //Variable length arrays are encoded as a regular array with 0 elements. assert((isa(AT) || isa(AT)) && "Unknown array type!"); @@ -5384,6 +5459,20 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // We encode the underlying type which comes out as // {...}; S += '^'; + if (FD && OPT->getInterfaceDecl()) { + // Prevent recursive encoding of fields in some rare cases. + ObjCInterfaceDecl *OI = OPT->getInterfaceDecl(); + SmallVector Ivars; + DeepCollectObjCIvars(OI, true, Ivars); + for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { + if (cast(Ivars[i]) == FD) { + S += '{'; + S += OI->getIdentifier()->getName(); + S += '}'; + return; + } + } + } getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures, NULL, @@ -5484,7 +5573,8 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, if (base->isEmpty()) continue; uint64_t offs = toBits(layout.getVBaseClassOffset(base)); - if (FieldOrBaseOffsets.find(offs) == FieldOrBaseOffsets.end()) + if (offs >= uint64_t(toBits(layout.getNonVirtualSize())) && + FieldOrBaseOffsets.find(offs) == FieldOrBaseOffsets.end()) FieldOrBaseOffsets.insert(FieldOrBaseOffsets.end(), std::make_pair(offs, base)); } @@ -6267,6 +6357,8 @@ ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, CanQualType ASTContext::getFromTargetType(unsigned Type) const { switch (Type) { case TargetInfo::NoInt: return CanQualType(); + case TargetInfo::SignedChar: return SignedCharTy; + case TargetInfo::UnsignedChar: return UnsignedCharTy; case TargetInfo::SignedShort: return ShortTy; case TargetInfo::UnsignedShort: return UnsignedShortTy; case TargetInfo::SignedInt: return IntTy; @@ -6369,15 +6461,6 @@ ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, return false; } -/// QualifiedIdConformsQualifiedId - compare id with id -/// return true if lhs's protocols conform to rhs's protocol; false -/// otherwise. -bool ASTContext::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) { - if (lhs->isObjCQualifiedIdType() && rhs->isObjCQualifiedIdType()) - return ObjCQualifiedIdTypesAreCompatible(lhs, rhs, false); - return false; -} - /// ObjCQualifiedClassTypesAreCompatible - compare Class and /// Class. bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs, @@ -6890,7 +6973,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, FunctionType::ExtInfo rbaseInfo = rbase->getExtInfo(); // Compatible functions must have compatible calling conventions - if (!isSameCallConv(lbaseInfo.getCC(), rbaseInfo.getCC())) + if (lbaseInfo.getCC() != rbaseInfo.getCC()) return QualType(); // Regparm is part of the calling convention. @@ -7000,10 +7083,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, FunctionProtoType::ExtProtoInfo EPI = proto->getExtProtoInfo(); EPI.ExtInfo = einfo; - return getFunctionType(retType, - ArrayRef(proto->arg_type_begin(), - proto->getNumArgs()), - EPI); + return getFunctionType(retType, proto->getArgTypes(), EPI); } if (allLTypes) return lhs; @@ -7351,11 +7431,8 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { if (const FunctionProtoType *FPT = cast(F)) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = getFunctionExtInfo(LHS); - QualType ResultType - = getFunctionType(OldReturnType, - ArrayRef(FPT->arg_type_begin(), - FPT->getNumArgs()), - EPI); + QualType ResultType = + getFunctionType(OldReturnType, FPT->getArgTypes(), EPI); return ResultType; } } @@ -7407,7 +7484,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { //===----------------------------------------------------------------------===// unsigned ASTContext::getIntWidth(QualType T) const { - if (const EnumType *ET = dyn_cast(T)) + if (const EnumType *ET = T->getAs()) T = ET->getDecl()->getIntegerType(); if (T->isBooleanType()) return 1; @@ -7450,6 +7527,8 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const { ASTMutationListener::~ASTMutationListener() { } +void ASTMutationListener::DeducedReturnType(const FunctionDecl *FD, + QualType ReturnType) {} //===----------------------------------------------------------------------===// // Builtin Type Computation @@ -7507,6 +7586,11 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, "Bad modifiers used with 'v'!"); Type = Context.VoidTy; break; + case 'h': + assert(HowLong == 0 && !Signed && !Unsigned && + "Bad modifiers used with 'f'!"); + Type = Context.HalfTy; + break; case 'f': assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers used with 'f'!"); @@ -7734,7 +7818,7 @@ QualType ASTContext::GetBuiltinType(unsigned Id, assert((TypeStr[0] != '.' || TypeStr[1] == 0) && "'.' should only occur at end of builtin type list!"); - FunctionType::ExtInfo EI; + FunctionType::ExtInfo EI(CC_C); if (BuiltinInfo.isNoReturn(Id)) EI = EI.withNoReturn(true); bool Variadic = (TypeStr[0] == '.'); @@ -7751,36 +7835,30 @@ QualType ASTContext::GetBuiltinType(unsigned Id, } GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) { - GVALinkage External = GVA_StrongExternal; - - Linkage L = FD->getLinkage(); - switch (L) { - case NoLinkage: - case InternalLinkage: - case UniqueExternalLinkage: + if (!FD->isExternallyVisible()) return GVA_Internal; - - case ExternalLinkage: - switch (FD->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - External = GVA_StrongExternal; - break; - case TSK_ExplicitInstantiationDefinition: - return GVA_ExplicitTemplateInstantiation; + GVALinkage External = GVA_StrongExternal; + switch (FD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + External = GVA_StrongExternal; + break; - case TSK_ExplicitInstantiationDeclaration: - case TSK_ImplicitInstantiation: - External = GVA_TemplateInstantiation; - break; - } + case TSK_ExplicitInstantiationDefinition: + return GVA_ExplicitTemplateInstantiation; + + case TSK_ExplicitInstantiationDeclaration: + case TSK_ImplicitInstantiation: + External = GVA_TemplateInstantiation; + break; } if (!FD->isInlined()) return External; - - if (!getLangOpts().CPlusPlus || FD->hasAttr()) { + + if ((!getLangOpts().CPlusPlus && !getLangOpts().MicrosoftMode) || + FD->hasAttr()) { // GNU or C99 inline semantics. Determine whether this symbol should be // externally visible. if (FD->isInlineDefinitionExternallyVisible()) @@ -7804,37 +7882,23 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) { } GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { - // If this is a static data member, compute the kind of template - // specialization. Otherwise, this variable is not part of a - // template. - TemplateSpecializationKind TSK = TSK_Undeclared; - if (VD->isStaticDataMember()) - TSK = VD->getTemplateSpecializationKind(); - - Linkage L = VD->getLinkage(); - - switch (L) { - case NoLinkage: - case InternalLinkage: - case UniqueExternalLinkage: + if (!VD->isExternallyVisible()) return GVA_Internal; - case ExternalLinkage: - switch (TSK) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - return GVA_StrongExternal; + switch (VD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + return GVA_StrongExternal; - case TSK_ExplicitInstantiationDeclaration: - llvm_unreachable("Variable should not be instantiated"); - // Fall through to treat this like any other instantiation. - - case TSK_ExplicitInstantiationDefinition: - return GVA_ExplicitTemplateInstantiation; + case TSK_ExplicitInstantiationDeclaration: + llvm_unreachable("Variable should not be instantiated"); + // Fall through to treat this like any other instantiation. - case TSK_ImplicitInstantiation: - return GVA_TemplateInstantiation; - } + case TSK_ExplicitInstantiationDefinition: + return GVA_ExplicitTemplateInstantiation; + + case TSK_ImplicitInstantiation: + return GVA_TemplateInstantiation; } llvm_unreachable("Invalid Linkage!"); @@ -7918,16 +7982,13 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return false; } -CallingConv ASTContext::getDefaultCXXMethodCallConv(bool isVariadic) { +CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic, + bool IsCXXMethod) const { // Pass through to the C++ ABI object - return ABI->getDefaultMethodCallConv(isVariadic); -} + if (IsCXXMethod) + return ABI->getDefaultMethodCallConv(IsVariadic); -CallingConv ASTContext::getCanonicalCallConv(CallingConv CC) const { - if (CC == CC_C && !LangOpts.MRTD && - getTargetInfo().getCXXABI().isMemberFunctionCCDefault()) - return CC_Default; - return CC; + return (LangOpts.MRTD && !IsVariadic) ? CC_X86StdCall : CC_C; } bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const { @@ -7941,9 +8002,9 @@ MangleContext *ASTContext::createMangleContext() { case TargetCXXABI::GenericItanium: case TargetCXXABI::GenericARM: case TargetCXXABI::iOS: - return createItaniumMangleContext(*this, getDiagnostics()); + return ItaniumMangleContext::create(*this, getDiagnostics()); case TargetCXXABI::Microsoft: - return createMicrosoftMangleContext(*this, getDiagnostics()); + return MicrosoftMangleContext::create(*this, getDiagnostics()); } llvm_unreachable("Unsupported ABI"); } @@ -7951,45 +8012,77 @@ MangleContext *ASTContext::createMangleContext() { CXXABI::~CXXABI() {} size_t ASTContext::getSideTableAllocatedMemory() const { - return ASTRecordLayouts.getMemorySize() - + llvm::capacity_in_bytes(ObjCLayouts) - + llvm::capacity_in_bytes(KeyFunctions) - + llvm::capacity_in_bytes(ObjCImpls) - + llvm::capacity_in_bytes(BlockVarCopyInits) - + llvm::capacity_in_bytes(DeclAttrs) - + llvm::capacity_in_bytes(InstantiatedFromStaticDataMember) - + llvm::capacity_in_bytes(InstantiatedFromUsingDecl) - + llvm::capacity_in_bytes(InstantiatedFromUsingShadowDecl) - + llvm::capacity_in_bytes(InstantiatedFromUnnamedFieldDecl) - + llvm::capacity_in_bytes(OverriddenMethods) - + llvm::capacity_in_bytes(Types) - + llvm::capacity_in_bytes(VariableArrayTypes) - + 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(Tag->getParent()) || Tag->getLinkage() != ExternalLinkage) - return; + return ASTRecordLayouts.getMemorySize() + + llvm::capacity_in_bytes(ObjCLayouts) + + llvm::capacity_in_bytes(KeyFunctions) + + llvm::capacity_in_bytes(ObjCImpls) + + llvm::capacity_in_bytes(BlockVarCopyInits) + + llvm::capacity_in_bytes(DeclAttrs) + + llvm::capacity_in_bytes(TemplateOrInstantiation) + + llvm::capacity_in_bytes(InstantiatedFromUsingDecl) + + llvm::capacity_in_bytes(InstantiatedFromUsingShadowDecl) + + llvm::capacity_in_bytes(InstantiatedFromUnnamedFieldDecl) + + llvm::capacity_in_bytes(OverriddenMethods) + + llvm::capacity_in_bytes(Types) + + llvm::capacity_in_bytes(VariableArrayTypes) + + llvm::capacity_in_bytes(ClassScopeSpecializationPattern); +} + +/// getIntTypeForBitwidth - +/// sets integer QualTy according to specified details: +/// bitwidth, signed/unsigned. +/// Returns empty type if there is no appropriate target types. +QualType ASTContext::getIntTypeForBitwidth(unsigned DestWidth, + unsigned Signed) const { + TargetInfo::IntType Ty = getTargetInfo().getIntTypeByWidth(DestWidth, Signed); + CanQualType QualTy = getFromTargetType(Ty); + if (!QualTy && DestWidth == 128) + return Signed ? Int128Ty : UnsignedInt128Ty; + return QualTy; +} + +/// getRealTypeForBitwidth - +/// sets floating point QualTy according to specified bitwidth. +/// Returns empty type if there is no appropriate target types. +QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth) const { + TargetInfo::RealType Ty = getTargetInfo().getRealTypeByWidth(DestWidth); + switch (Ty) { + case TargetInfo::Float: + return FloatTy; + case TargetInfo::Double: + return DoubleTy; + case TargetInfo::LongDouble: + return LongDoubleTy; + case TargetInfo::NoFloat: + return QualType(); + } - std::pair::iterator, bool> P = - UnnamedMangleContexts.insert(std::make_pair(Tag->getParent(), 0)); - UnnamedMangleNumbers.insert(std::make_pair(Tag, P.first->second++)); + llvm_unreachable("Unhandled TargetInfo::RealType value"); } -int ASTContext::getUnnamedTagManglingNumber(const TagDecl *Tag) const { - llvm::DenseMap::const_iterator I = - UnnamedMangleNumbers.find(Tag); - return I != UnnamedMangleNumbers.end() ? I->second : -1; +void ASTContext::setManglingNumber(const NamedDecl *ND, unsigned Number) { + if (Number > 1) + MangleNumbers[ND] = Number; } -unsigned ASTContext::getLambdaManglingNumber(CXXMethodDecl *CallOperator) { - CXXRecordDecl *Lambda = CallOperator->getParent(); - return LambdaMangleContexts[Lambda->getDeclContext()] - .getManglingNumber(CallOperator); +unsigned ASTContext::getManglingNumber(const NamedDecl *ND) const { + llvm::DenseMap::const_iterator I = + MangleNumbers.find(ND); + return I != MangleNumbers.end() ? I->second : 1; } +MangleNumberingContext & +ASTContext::getManglingNumberContext(const DeclContext *DC) { + assert(LangOpts.CPlusPlus); // We don't need mangling numbers for plain C. + MangleNumberingContext *&MCtx = MangleNumberingContexts[DC]; + if (!MCtx) + MCtx = createMangleNumberingContext(); + return *MCtx; +} + +MangleNumberingContext *ASTContext::createMangleNumberingContext() const { + return ABI->createMangleNumberingContext(); +} void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) { ParamIndices[D] = index; @@ -8001,3 +8094,160 @@ unsigned ASTContext::getParameterIndex(const ParmVarDecl *D) const { "ParmIndices lacks entry set by ParmVarDecl"); return I->second; } + +APValue * +ASTContext::getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, + bool MayCreate) { + assert(E && E->getStorageDuration() == SD_Static && + "don't need to cache the computed value for this temporary"); + if (MayCreate) + return &MaterializedTemporaryValues[E]; + + llvm::DenseMap::iterator I = + MaterializedTemporaryValues.find(E); + return I == MaterializedTemporaryValues.end() ? 0 : &I->second; +} + +bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const { + const llvm::Triple &T = getTargetInfo().getTriple(); + if (!T.isOSDarwin()) + return false; + + if (!(T.isiOS() && T.isOSVersionLT(7)) && + !(T.isMacOSX() && T.isOSVersionLT(10, 9))) + return false; + + QualType AtomicTy = E->getPtr()->getType()->getPointeeType(); + CharUnits sizeChars = getTypeSizeInChars(AtomicTy); + uint64_t Size = sizeChars.getQuantity(); + CharUnits alignChars = getTypeAlignInChars(AtomicTy); + unsigned Align = alignChars.getQuantity(); + unsigned MaxInlineWidthInBits = getTargetInfo().getMaxAtomicInlineWidth(); + return (Size != Align || toBits(sizeChars) > MaxInlineWidthInBits); +} + +namespace { + + /// \brief A \c RecursiveASTVisitor that builds a map from nodes to their + /// parents as defined by the \c RecursiveASTVisitor. + /// + /// Note that the relationship described here is purely in terms of AST + /// traversal - there are other relationships (for example declaration context) + /// in the AST that are better modeled by special matchers. + /// + /// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes. + class ParentMapASTVisitor : public RecursiveASTVisitor { + + public: + /// \brief Builds and returns the translation unit's parent map. + /// + /// The caller takes ownership of the returned \c ParentMap. + static ASTContext::ParentMap *buildMap(TranslationUnitDecl &TU) { + ParentMapASTVisitor Visitor(new ASTContext::ParentMap); + Visitor.TraverseDecl(&TU); + return Visitor.Parents; + } + + private: + typedef RecursiveASTVisitor VisitorBase; + + ParentMapASTVisitor(ASTContext::ParentMap *Parents) : Parents(Parents) { + } + + bool shouldVisitTemplateInstantiations() const { + return true; + } + bool shouldVisitImplicitCode() const { + return true; + } + // Disables data recursion. We intercept Traverse* methods in the RAV, which + // are not triggered during data recursion. + bool shouldUseDataRecursionFor(clang::Stmt *S) const { + return false; + } + + template + bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) { + if (Node == NULL) + return true; + if (ParentStack.size() > 0) + // FIXME: Currently we add the same parent multiple times, for example + // when we visit all subexpressions of template instantiations; this is + // suboptimal, bug benign: the only way to visit those is with + // hasAncestor / hasParent, and those do not create new matches. + // The plan is to enable DynTypedNode to be storable in a map or hash + // map. The main problem there is to implement hash functions / + // comparison operators for all types that DynTypedNode supports that + // do not have pointer identity. + (*Parents)[Node].push_back(ParentStack.back()); + ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node)); + bool Result = (this ->* traverse) (Node); + ParentStack.pop_back(); + return Result; + } + + bool TraverseDecl(Decl *DeclNode) { + return TraverseNode(DeclNode, &VisitorBase::TraverseDecl); + } + + bool TraverseStmt(Stmt *StmtNode) { + return TraverseNode(StmtNode, &VisitorBase::TraverseStmt); + } + + ASTContext::ParentMap *Parents; + llvm::SmallVector ParentStack; + + friend class RecursiveASTVisitor; + }; + +} // end namespace + +ASTContext::ParentVector +ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { + assert(Node.getMemoizationData() && + "Invariant broken: only nodes that support memoization may be " + "used in the parent map."); + if (!AllParents) { + // We always need to run over the whole translation unit, as + // hasAncestor can escape any subtree. + AllParents.reset( + ParentMapASTVisitor::buildMap(*getTranslationUnitDecl())); + } + ParentMap::const_iterator I = AllParents->find(Node.getMemoizationData()); + if (I == AllParents->end()) { + return ParentVector(); + } + return I->second; +} + +bool +ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, + const ObjCMethodDecl *MethodImpl) { + // No point trying to match an unavailable/deprecated mothod. + if (MethodDecl->hasAttr() + || MethodDecl->hasAttr()) + return false; + if (MethodDecl->getObjCDeclQualifier() != + MethodImpl->getObjCDeclQualifier()) + return false; + if (!hasSameType(MethodDecl->getResultType(), + MethodImpl->getResultType())) + return false; + + if (MethodDecl->param_size() != MethodImpl->param_size()) + return false; + + for (ObjCMethodDecl::param_const_iterator IM = MethodImpl->param_begin(), + IF = MethodDecl->param_begin(), EM = MethodImpl->param_end(), + EF = MethodDecl->param_end(); + IM != EM && IF != EF; ++IM, ++IF) { + const ParmVarDecl *DeclVar = (*IF); + const ParmVarDecl *ImplVar = (*IM); + if (ImplVar->getObjCDeclQualifier() != DeclVar->getObjCDeclQualifier()) + return false; + if (!hasSameType(DeclVar->getType(), ImplVar->getType())) + return false; + } + return (MethodDecl->isVariadic() == MethodImpl->isVariadic()); + +} diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp index 1ed65e4..fce8f64 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp @@ -300,8 +300,7 @@ void clang::FormatASTNodeDiagnosticArgument( assert(ModLen == 0 && ArgLen == 0 && "Invalid modifier for DeclarationName argument"); - DeclarationName N = DeclarationName::getFromOpaqueInteger(Val); - N.printName(OS); + OS << DeclarationName::getFromOpaqueInteger(Val); break; } case DiagnosticsEngine::ak_nameddecl: { @@ -459,6 +458,10 @@ class TemplateDiff { /// FromValueDecl, ToValueDecl - Whether the argument is a decl. ValueDecl *FromValueDecl, *ToValueDecl; + /// FromAddressOf, ToAddressOf - Whether the ValueDecl needs an address of + /// operator before it. + bool FromAddressOf, ToAddressOf; + /// FromDefault, ToDefault - Whether the argument is a default argument. bool FromDefault, ToDefault; @@ -469,7 +472,8 @@ class TemplateDiff { : Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode), FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0), IsValidFromInt(false), IsValidToInt(false), FromValueDecl(0), - ToValueDecl(0), FromDefault(false), ToDefault(false), Same(false) { } + ToValueDecl(0), FromAddressOf(false), ToAddressOf(false), + FromDefault(false), ToDefault(false), Same(false) { } }; /// FlatTree - A flattened tree used to store the DiffNodes. @@ -526,9 +530,12 @@ class TemplateDiff { } /// SetNode - Set FromValueDecl and ToValueDecl of the current node. - void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl) { + void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, + bool FromAddressOf, bool ToAddressOf) { FlatTree[CurrentNode].FromValueDecl = FromValueDecl; FlatTree[CurrentNode].ToValueDecl = ToValueDecl; + FlatTree[CurrentNode].FromAddressOf = FromAddressOf; + FlatTree[CurrentNode].ToAddressOf = ToAddressOf; } /// SetSame - Sets the same flag of the current node. @@ -620,9 +627,12 @@ class TemplateDiff { } /// GetNode - Gets the FromValueDecl and ToValueDecl. - void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl) { + void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl, + bool &FromAddressOf, bool &ToAddressOf) { FromValueDecl = FlatTree[ReadNode].FromValueDecl; ToValueDecl = FlatTree[ReadNode].ToValueDecl; + FromAddressOf = FlatTree[ReadNode].FromAddressOf; + ToAddressOf = FlatTree[ReadNode].ToAddressOf; } /// NodeIsSame - Returns true the arguments are the same. @@ -821,8 +831,10 @@ class TemplateDiff { void DiffTemplate(const TemplateSpecializationType *FromTST, const TemplateSpecializationType *ToTST) { // Begin descent into diffing template tree. - TemplateParameterList *Params = + TemplateParameterList *ParamsFrom = FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters(); + TemplateParameterList *ParamsTo = + ToTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters(); unsigned TotalArgs = 0; for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST); !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) { @@ -831,15 +843,18 @@ class TemplateDiff { // Get the parameter at index TotalArgs. If index is larger // than the total number of parameters, then there is an // argument pack, so re-use the last parameter. - NamedDecl *ParamND = Params->getParam( - (TotalArgs < Params->size()) ? TotalArgs - : Params->size() - 1); + unsigned ParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1); + NamedDecl *ParamND = ParamsFrom->getParam(ParamIndex); + // Handle Types if (TemplateTypeParmDecl *DefaultTTPD = dyn_cast(ParamND)) { QualType FromType, ToType; FromType = GetType(FromIter, DefaultTTPD); - ToType = GetType(ToIter, DefaultTTPD); + // A forward declaration can have no default arg but the actual class + // can, don't mix up iterators and get the original parameter. + ToType = GetType( + ToIter, cast(ParamsTo->getParam(ParamIndex))); Tree.SetNode(FromType, ToType); Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(), ToIter.isEnd() && !ToType.isNull()); @@ -942,7 +957,14 @@ class TemplateDiff { FromValueDecl = GetValueDecl(FromIter, FromExpr); if (!HasToValueDecl && ToExpr) ToValueDecl = GetValueDecl(ToIter, ToExpr); - Tree.SetNode(FromValueDecl, ToValueDecl); + QualType ArgumentType = DefaultNTTPD->getType(); + bool FromAddressOf = FromValueDecl && + !ArgumentType->isReferenceType() && + !FromValueDecl->getType()->isArrayType(); + bool ToAddressOf = ToValueDecl && + !ArgumentType->isReferenceType() && + !ToValueDecl->getType()->isArrayType(); + Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); Tree.SetSame(FromValueDecl && ToValueDecl && FromValueDecl->getCanonicalDecl() == ToValueDecl->getCanonicalDecl()); @@ -973,7 +995,7 @@ class TemplateDiff { /// makeTemplateList - Dump every template alias into the vector. static void makeTemplateList( - SmallVector &TemplateList, + SmallVectorImpl &TemplateList, const TemplateSpecializationType *TST) { while (TST) { TemplateList.push_back(TST); @@ -1008,7 +1030,7 @@ class TemplateDiff { makeTemplateList(FromTemplateList, FromTST); makeTemplateList(ToTemplateList, ToTST); - SmallVector::reverse_iterator + SmallVectorImpl::reverse_iterator FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(), ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend(); @@ -1037,10 +1059,14 @@ class TemplateDiff { if (!Iter.isEnd()) return Iter->getAsType(); - if (!isVariadic) - return DefaultTTPD->getDefaultArgument(); + if (isVariadic) + return QualType(); + + QualType ArgType = DefaultTTPD->getDefaultArgument(); + if (ArgType->isDependentType()) + return Iter.getDesugar().getAsType(); - return QualType(); + return ArgType; } /// GetExpr - Retrieves the template expression argument, including default @@ -1080,7 +1106,7 @@ class TemplateDiff { return ArgExpr->EvaluateKnownConstInt(Context); } - /// GetValueDecl - Retrieves the template integer argument, including + /// GetValueDecl - Retrieves the template Decl argument, including /// default expression argument. ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) { // Default, value-depenedent expressions require fetching @@ -1095,7 +1121,12 @@ class TemplateDiff { default: assert(0 && "Unexpected template argument kind"); } - return cast(ArgExpr)->getDecl(); + DeclRefExpr *DRE = dyn_cast(ArgExpr); + if (!DRE) { + DRE = cast(cast(ArgExpr)->getSubExpr()); + } + + return DRE->getDecl(); } /// GetTemplateDecl - Retrieves the template template arguments, including @@ -1228,9 +1259,10 @@ class TemplateDiff { } case DiffTree::Declaration: { ValueDecl *FromValueDecl, *ToValueDecl; - Tree.GetNode(FromValueDecl, ToValueDecl); - PrintValueDecl(FromValueDecl, ToValueDecl, Tree.FromDefault(), - Tree.ToDefault(), Tree.NodeIsSame()); + bool FromAddressOf, ToAddressOf; + Tree.GetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); + PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf, + Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); return; } case DiffTree::Template: { @@ -1478,7 +1510,8 @@ class TemplateDiff { /// PrintDecl - Handles printing of Decl arguments, highlighting /// argument differences. void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, - bool FromDefault, bool ToDefault, bool Same) { + bool FromAddressOf, bool ToAddressOf, bool FromDefault, + bool ToDefault, bool Same) { assert((FromValueDecl || ToValueDecl) && "Only one Decl argument may be NULL"); @@ -1487,15 +1520,21 @@ class TemplateDiff { } else if (!PrintTree) { OS << (FromDefault ? "(default) " : ""); Bold(); + if (FromAddressOf) + OS << "&"; OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); Unbold(); } else { OS << (FromDefault ? "[(default) " : "["); Bold(); + if (FromAddressOf) + OS << "&"; OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); Unbold(); OS << " != " << (ToDefault ? "(default) " : ""); Bold(); + if (ToAddressOf) + OS << "&"; OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)"); Unbold(); OS << ']'; diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp index 340cc41..2f40255 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp @@ -16,6 +16,7 @@ #include "clang/AST/Attr.h" #include "clang/AST/CommentVisitor.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclLookups.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/StmtVisitor.h" @@ -62,6 +63,9 @@ namespace { // Null statements static const TerminalColor NullColor = { raw_ostream::BLUE, false }; + // Undeserialized entities + static const TerminalColor UndeserializedColor = { raw_ostream::GREEN, true }; + // CastKind from CastExpr's static const TerminalColor CastColor = { raw_ostream::RED, false }; @@ -173,6 +177,7 @@ namespace { void dumpName(const NamedDecl *D); bool hasNodes(const DeclContext *DC); void dumpDeclContext(const DeclContext *DC); + void dumpLookups(const DeclContext *DC); void dumpAttr(const Attr *A); // C++ Utilities @@ -214,6 +219,11 @@ namespace { const ClassTemplatePartialSpecializationDecl *D); void VisitClassScopeFunctionSpecializationDecl( const ClassScopeFunctionSpecializationDecl *D); + void VisitVarTemplateDecl(const VarTemplateDecl *D); + void VisitVarTemplateSpecializationDecl( + const VarTemplateSpecializationDecl *D); + void VisitVarTemplatePartialSpecializationDecl( + const VarTemplatePartialSpecializationDecl *D); void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); @@ -244,6 +254,7 @@ namespace { void VisitAttributedStmt(const AttributedStmt *Node); void VisitLabelStmt(const LabelStmt *Node); void VisitGotoStmt(const GotoStmt *Node); + void VisitCXXCatchStmt(const CXXCatchStmt *Node); // Exprs void VisitExpr(const Expr *Node); @@ -271,9 +282,14 @@ namespace { void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node); void VisitCXXConstructExpr(const CXXConstructExpr *Node); void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node); + void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node); void VisitExprWithCleanups(const ExprWithCleanups *Node); void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node); void dumpCXXTemporary(const CXXTemporary *Temporary); + void VisitLambdaExpr(const LambdaExpr *Node) { + VisitExpr(Node); + dumpDecl(Node->getLambdaClass()); + } // ObjC void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node); @@ -329,8 +345,8 @@ void ASTDumper::indent() { OS << "\n"; ColorScope Color(*this, IndentColor); - for (llvm::SmallVector::const_iterator I = Indents.begin(), - E = Indents.end(); + for (SmallVectorImpl::const_iterator I = Indents.begin(), + E = Indents.end(); I != E; ++I) { switch (*I) { case IT_Child: @@ -449,9 +465,7 @@ void ASTDumper::dumpBareDeclRef(const Decl *D) { if (const NamedDecl *ND = dyn_cast(D)) { ColorScope Color(*this, DeclNameColor); - OS << " '"; - ND->getDeclName().printName(OS); - OS << "'"; + OS << " '" << ND->getDeclName() << '\''; } if (const ValueDecl *VD = dyn_cast(D)) @@ -479,20 +493,76 @@ bool ASTDumper::hasNodes(const DeclContext *DC) { if (!DC) return false; - return DC->decls_begin() != DC->decls_end(); + return DC->hasExternalLexicalStorage() || + DC->noload_decls_begin() != DC->noload_decls_end(); } void ASTDumper::dumpDeclContext(const DeclContext *DC) { if (!DC) return; - for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end(); + bool HasUndeserializedDecls = DC->hasExternalLexicalStorage(); + for (DeclContext::decl_iterator I = DC->noload_decls_begin(), + E = DC->noload_decls_end(); I != E; ++I) { DeclContext::decl_iterator Next = I; ++Next; - if (Next == E) + if (Next == E && !HasUndeserializedDecls) lastChild(); dumpDecl(*I); } + if (HasUndeserializedDecls) { + lastChild(); + IndentScope Indent(*this); + ColorScope Color(*this, UndeserializedColor); + OS << ""; + } +} + +void ASTDumper::dumpLookups(const DeclContext *DC) { + IndentScope Indent(*this); + + OS << "StoredDeclsMap "; + dumpBareDeclRef(cast(DC)); + + const DeclContext *Primary = DC->getPrimaryContext(); + if (Primary != DC) { + OS << " primary"; + dumpPointer(cast(Primary)); + } + + bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage(); + + DeclContext::all_lookups_iterator I = Primary->noload_lookups_begin(), + E = Primary->noload_lookups_end(); + while (I != E) { + DeclarationName Name = I.getLookupName(); + DeclContextLookupResult R = *I++; + if (I == E && !HasUndeserializedLookups) + lastChild(); + + IndentScope Indent(*this); + OS << "DeclarationName "; + { + ColorScope Color(*this, DeclNameColor); + OS << '\'' << Name << '\''; + } + + for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end(); + RI != RE; ++RI) { + if (RI + 1 == RE) + lastChild(); + dumpDeclRef(*RI); + if ((*RI)->isHidden()) + OS << " hidden"; + } + } + + if (HasUndeserializedLookups) { + lastChild(); + IndentScope Indent(*this); + ColorScope Color(*this, UndeserializedColor); + OS << ""; + } } void ASTDumper::dumpAttr(const Attr *A) { @@ -511,21 +581,29 @@ void ASTDumper::dumpAttr(const Attr *A) { #include "clang/AST/AttrDump.inc" } -static Decl *getPreviousDeclImpl(...) { - return 0; +static void dumpPreviousDeclImpl(raw_ostream &OS, ...) {} + +template +static void dumpPreviousDeclImpl(raw_ostream &OS, const Mergeable *D) { + const T *First = D->getFirstDecl(); + if (First != D) + OS << " first " << First; } template -static const Decl *getPreviousDeclImpl(const Redeclarable *D) { - return D->getPreviousDecl(); +static void dumpPreviousDeclImpl(raw_ostream &OS, const Redeclarable *D) { + const T *Prev = D->getPreviousDecl(); + if (Prev) + OS << " prev " << Prev; } -/// Get the previous declaration in the redeclaration chain for a declaration. -static const Decl *getPreviousDecl(const Decl *D) { +/// Dump the previous declaration in the redeclaration chain for a declaration, +/// if any. +static void dumpPreviousDecl(raw_ostream &OS, const Decl *D) { switch (D->getKind()) { #define DECL(DERIVED, BASE) \ case Decl::DERIVED: \ - return getPreviousDeclImpl(cast(D)); + return dumpPreviousDeclImpl(OS, cast(D)); #define ABSTRACT_DECL(DECL) #include "clang/AST/DeclNodes.inc" } @@ -662,20 +740,25 @@ void ASTDumper::dumpDecl(const Decl *D) { dumpPointer(D); if (D->getLexicalDeclContext() != D->getDeclContext()) OS << " parent " << cast(D->getDeclContext()); - if (const Decl *Prev = getPreviousDecl(D)) - OS << " prev " << Prev; + dumpPreviousDecl(OS, D); dumpSourceRange(D->getSourceRange()); + if (Module *M = D->getOwningModule()) + OS << " in " << M->getFullModuleName(); + if (const NamedDecl *ND = dyn_cast(D)) + if (ND->isHidden()) + OS << " hidden"; bool HasAttrs = D->attr_begin() != D->attr_end(); - bool HasComment = D->getASTContext().getCommentForDecl(D, 0); + const FullComment *Comment = + D->getASTContext().getLocalCommentForDeclUncached(D); // Decls within functions are visited by the body bool HasDeclContext = !isa(*D) && !isa(*D) && hasNodes(dyn_cast(D)); - setMoreChildren(HasAttrs || HasComment || HasDeclContext); + setMoreChildren(HasAttrs || Comment || HasDeclContext); ConstDeclVisitor::Visit(D); - setMoreChildren(HasComment || HasDeclContext); + setMoreChildren(Comment || HasDeclContext); for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end(); I != E; ++I) { if (I + 1 == E) @@ -685,7 +768,10 @@ void ASTDumper::dumpDecl(const Decl *D) { setMoreChildren(HasDeclContext); lastChild(); - dumpFullComment(D->getASTContext().getCommentForDecl(D, 0)); + dumpFullComment(Comment); + + if (D->isInvalidDecl()) + OS << " invalid"; setMoreChildren(false); if (HasDeclContext) @@ -722,6 +808,8 @@ void ASTDumper::VisitRecordDecl(const RecordDecl *D) { dumpName(D); if (D->isModulePrivate()) OS << " __module_private__"; + if (D->isCompleteDefinition()) + OS << " definition"; } void ASTDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) { @@ -764,6 +852,19 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { else if (D->isDeletedAsWritten()) OS << " delete"; + if (const FunctionProtoType *FPT = D->getType()->getAs()) { + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + switch (EPI.ExceptionSpecType) { + default: break; + case EST_Unevaluated: + OS << " noexcept-unevaluated " << EPI.ExceptionSpecDecl; + break; + case EST_Uninstantiated: + OS << " noexcept-uninstantiated " << EPI.ExceptionSpecTemplate; + break; + } + } + bool OldMoreChildren = hasMoreChildren(); const FunctionTemplateSpecializationInfo *FTSI = D->getTemplateSpecializationInfo(); @@ -1012,6 +1113,49 @@ void ASTDumper::VisitClassScopeFunctionSpecializationDecl( dumpTemplateArgumentListInfo(D->templateArgs()); } +void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) { + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); + + VarTemplateDecl::spec_iterator I = D->spec_begin(); + VarTemplateDecl::spec_iterator E = D->spec_end(); + if (I == E) + lastChild(); + dumpDecl(D->getTemplatedDecl()); + for (; I != E; ++I) { + VarTemplateDecl::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::VisitVarTemplateSpecializationDecl( + const VarTemplateSpecializationDecl *D) { + dumpTemplateArgumentList(D->getTemplateArgs()); + VisitVarDecl(D); +} + +void ASTDumper::VisitVarTemplatePartialSpecializationDecl( + const VarTemplatePartialSpecializationDecl *D) { + dumpTemplateParameters(D->getTemplateParameters()); + VisitVarTemplateSpecializationDecl(D); +} + void ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { if (D->wasDeclaredWithTypename()) OS << " typename"; @@ -1097,6 +1241,8 @@ void ASTDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) { dumpType(D->getType()); if (D->getSynthesize()) OS << " synthesize"; + if (D->getBackingIvarReferencedInAccessor()) + OS << " BackingIvarReferencedInAccessor"; switch (D->getAccessControl()) { case ObjCIvarDecl::None: @@ -1331,7 +1477,7 @@ void ASTDumper::dumpStmt(const Stmt *S) { return; } - setMoreChildren(S->children()); + setMoreChildren(!S->children().empty()); ConstStmtVisitor::Visit(S); setMoreChildren(false); for (Stmt::const_child_range CI = S->children(); CI; ++CI) { @@ -1385,6 +1531,11 @@ void ASTDumper::VisitGotoStmt(const GotoStmt *Node) { dumpPointer(Node->getLabel()); } +void ASTDumper::VisitCXXCatchStmt(const CXXCatchStmt *Node) { + VisitStmt(Node); + dumpDecl(Node->getExceptionDecl()); +} + //===----------------------------------------------------------------------===// // Expr dumping methods. //===----------------------------------------------------------------------===// @@ -1510,6 +1661,7 @@ void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) { default: llvm_unreachable("unknown case"); case PredefinedExpr::Func: OS << " __func__"; break; case PredefinedExpr::Function: OS << " __FUNCTION__"; break; + case PredefinedExpr::FuncDName: OS << " __FUNCDNAME__"; break; case PredefinedExpr::LFunction: OS << " L__FUNCTION__"; break; case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break; } @@ -1659,6 +1811,15 @@ void ASTDumper::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node) { dumpCXXTemporary(Node->getTemporary()); } +void +ASTDumper::VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node) { + VisitExpr(Node); + if (const ValueDecl *VD = Node->getExtendingDecl()) { + OS << " extended by "; + dumpBareDeclRef(VD); + } +} + void ASTDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) { VisitExpr(Node); for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) @@ -1949,6 +2110,20 @@ void Decl::dumpColor() const { &getASTContext().getSourceManager(), /*ShowColors*/true); P.dumpDecl(this); } + +void DeclContext::dumpLookups() const { + dumpLookups(llvm::errs()); +} + +void DeclContext::dumpLookups(raw_ostream &OS) const { + const DeclContext *DC = this; + while (!DC->isTranslationUnit()) + DC = DC->getParent(); + ASTContext &Ctx = cast(DC)->getASTContext(); + ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager()); + P.dumpLookups(this); +} + //===----------------------------------------------------------------------===// // Stmt method implementations //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index 915eb6f..e16015b 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -106,6 +106,8 @@ namespace clang { bool ImportDefinition(RecordDecl *From, RecordDecl *To, ImportDefinitionKind Kind = IDK_Default); + bool ImportDefinition(VarDecl *From, VarDecl *To, + ImportDefinitionKind Kind = IDK_Default); bool ImportDefinition(EnumDecl *From, EnumDecl *To, ImportDefinitionKind Kind = IDK_Default); bool ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, @@ -120,9 +122,12 @@ namespace clang { SmallVectorImpl &ToArgs); bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, bool Complain = true); + bool IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, + bool Complain = true); bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord); bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC); bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); + bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); Decl *VisitDecl(Decl *D); Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); @@ -157,7 +162,9 @@ namespace clang { Decl *VisitClassTemplateDecl(ClassTemplateDecl *D); Decl *VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *D); - + Decl *VisitVarTemplateDecl(VarTemplateDecl *D); + Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D); + // Importing statements Stmt *VisitStmt(Stmt *S); @@ -400,6 +407,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; break; + case Type::Decayed: + if (!IsStructurallyEquivalent(Context, + cast(T1)->getPointeeType(), + cast(T2)->getPointeeType())) + return false; + break; + case Type::Pointer: if (!IsStructurallyEquivalent(Context, cast(T1)->getPointeeType(), @@ -1695,7 +1709,8 @@ QualType ASTNodeImporter::VisitAutoType(const AutoType *T) { return QualType(); } - return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto()); + return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto(), + /*IsDependent*/false); } QualType ASTNodeImporter::VisitRecordType(const RecordType *T) { @@ -1968,9 +1983,6 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, = FromData.HasDeclaredCopyConstructorWithConstParam; ToData.HasDeclaredCopyAssignmentWithConstParam = FromData.HasDeclaredCopyAssignmentWithConstParam; - ToData.FailedImplicitMoveConstructor - = FromData.FailedImplicitMoveConstructor; - ToData.FailedImplicitMoveAssignment = FromData.FailedImplicitMoveAssignment; ToData.IsLambda = FromData.IsLambda; SmallVector Bases; @@ -2010,6 +2022,21 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, return false; } +bool ASTNodeImporter::ImportDefinition(VarDecl *From, VarDecl *To, + ImportDefinitionKind Kind) { + if (To->getDefinition()) + return false; + + // FIXME: Can we really import any initializer? Alternatively, we could force + // ourselves to import every declaration of a variable and then only use + // getInit() here. + To->setInit(Importer.Import(const_cast(From->getAnyInitializer()))); + + // FIXME: Other bits to merge? + + return false; +} + bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To, ImportDefinitionKind Kind) { if (To->getDefinition() || To->isBeingDefined()) { @@ -2148,13 +2175,30 @@ bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs, bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, bool Complain) { + // Eliminate a potential failure point where we attempt to re-import + // something we're trying to import while completing ToRecord. + Decl *ToOrigin = Importer.GetOriginalDecl(ToRecord); + if (ToOrigin) { + RecordDecl *ToOriginRecord = dyn_cast(ToOrigin); + if (ToOriginRecord) + ToRecord = ToOriginRecord; + } + StructuralEquivalenceContext Ctx(Importer.getFromContext(), - Importer.getToContext(), + ToRecord->getASTContext(), Importer.getNonEquivalentDecls(), false, Complain); return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord); } +bool ASTNodeImporter::IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, + bool Complain) { + StructuralEquivalenceContext Ctx( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), false, Complain); + return Ctx.IsStructurallyEquivalent(FromVar, ToVar); +} + bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) { StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), @@ -2181,6 +2225,14 @@ bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From, return Ctx.IsStructurallyEquivalent(From, To); } +bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From, + VarTemplateDecl *To) { + StructuralEquivalenceContext Ctx(Importer.getFromContext(), + Importer.getToContext(), + Importer.getNonEquivalentDecls()); + return Ctx.IsStructurallyEquivalent(From, To); +} + Decl *ASTNodeImporter::VisitDecl(Decl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); @@ -2610,8 +2662,8 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { continue; if (FunctionDecl *FoundFunction = dyn_cast(FoundDecls[I])) { - if (isExternalLinkage(FoundFunction->getLinkage()) && - isExternalLinkage(D->getLinkage())) { + if (FoundFunction->hasExternalFormalLinkage() && + D->hasExternalFormalLinkage()) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundFunction->getType())) { // FIXME: Actually try to merge the body and other attributes. @@ -2664,10 +2716,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { FromEPI.NoexceptExpr) { FunctionProtoType::ExtProtoInfo DefaultEPI; FromTy = Importer.getFromContext().getFunctionType( - FromFPT->getResultType(), - ArrayRef(FromFPT->arg_type_begin(), - FromFPT->getNumArgs()), - DefaultEPI); + FromFPT->getResultType(), FromFPT->getArgTypes(), DefaultEPI); usedDifferentExceptionSpec = true; } } @@ -2878,7 +2927,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType(), - Name)) { + !Name.isEmpty())) { Importer.Imported(D, FoundField); return FoundField; } @@ -2965,7 +3014,8 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getAccessControl(), - BitWidth, D->getSynthesize()); + BitWidth, D->getSynthesize(), + D->getBackingIvarReferencedInAccessor()); ToIvar->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToIvar); LexicalDC->addDeclInternal(ToIvar); @@ -2995,8 +3045,8 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { if (VarDecl *FoundVar = dyn_cast(FoundDecls[I])) { // We have found a variable that we may need to merge with. Check it. - if (isExternalLinkage(FoundVar->getLinkage()) && - isExternalLinkage(D->getLinkage())) { + if (FoundVar->hasExternalFormalLinkage() && + D->hasExternalFormalLinkage()) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundVar->getType())) { MergeWithVar = FoundVar; @@ -3088,13 +3138,9 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { LexicalDC->addDeclInternal(ToVar); // Merge the initializer. - // FIXME: Can we really import any initializer? Alternatively, we could force - // ourselves to import every declaration of a variable and then only use - // getInit() here. - ToVar->setInit(Importer.Import(const_cast(D->getAnyInitializer()))); + if (ImportDefinition(D, ToVar)) + return 0; - // FIXME: Other bits to merge? - return ToVar; } @@ -4108,6 +4154,205 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( return D2; } +Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { + // If this variable has a definition in the translation unit we're coming + // from, + // but this particular declaration is not that definition, import the + // definition and map to that. + VarDecl *Definition = + cast_or_null(D->getTemplatedDecl()->getDefinition()); + if (Definition && Definition != D->getTemplatedDecl()) { + Decl *ImportedDef = Importer.Import(Definition->getDescribedVarTemplate()); + if (!ImportedDef) + return 0; + + return Importer.Imported(D, ImportedDef); + } + + // Import the major distinguishing characteristics of this variable template. + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + return 0; + + // We may already have a template of the same name; try to find and match it. + assert(!DC->isFunctionOrMethod() && + "Variable templates cannot be declared at function scope"); + SmallVector ConflictingDecls; + SmallVector FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + continue; + + Decl *Found = FoundDecls[I]; + if (VarTemplateDecl *FoundTemplate = dyn_cast(Found)) { + if (IsStructuralMatch(D, FoundTemplate)) { + // The variable templates structurally match; call it the same template. + Importer.Imported(D->getTemplatedDecl(), + FoundTemplate->getTemplatedDecl()); + return Importer.Imported(D, FoundTemplate); + } + } + + ConflictingDecls.push_back(FoundDecls[I]); + } + + if (!ConflictingDecls.empty()) { + Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Ordinary, + ConflictingDecls.data(), + ConflictingDecls.size()); + } + + if (!Name) + return 0; + + VarDecl *DTemplated = D->getTemplatedDecl(); + + // Import the type. + QualType T = Importer.Import(DTemplated->getType()); + if (T.isNull()) + return 0; + + // Create the declaration that is being templated. + SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart()); + SourceLocation IdLoc = Importer.Import(DTemplated->getLocation()); + TypeSourceInfo *TInfo = Importer.Import(DTemplated->getTypeSourceInfo()); + VarDecl *D2Templated = VarDecl::Create(Importer.getToContext(), DC, StartLoc, + IdLoc, Name.getAsIdentifierInfo(), T, + TInfo, DTemplated->getStorageClass()); + D2Templated->setAccess(DTemplated->getAccess()); + D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc())); + D2Templated->setLexicalDeclContext(LexicalDC); + + // Importer.Imported(DTemplated, D2Templated); + // LexicalDC->addDeclInternal(D2Templated); + + // Merge the initializer. + if (ImportDefinition(DTemplated, D2Templated)) + return 0; + + // Create the variable template declaration itself. + TemplateParameterList *TemplateParams = + ImportTemplateParameterList(D->getTemplateParameters()); + if (!TemplateParams) + return 0; + + VarTemplateDecl *D2 = VarTemplateDecl::Create( + Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated, + /*PrevDecl=*/0); + D2Templated->setDescribedVarTemplate(D2); + + D2->setAccess(D->getAccess()); + D2->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(D2); + + // Note the relationship between the variable templates. + Importer.Imported(D, D2); + Importer.Imported(DTemplated, D2Templated); + + if (DTemplated->isThisDeclarationADefinition() && + !D2Templated->isThisDeclarationADefinition()) { + // FIXME: Import definition! + } + + return D2; +} + +Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( + VarTemplateSpecializationDecl *D) { + // If this record has a definition in the translation unit we're coming from, + // but this particular declaration is not that definition, import the + // definition and map to that. + VarDecl *Definition = D->getDefinition(); + if (Definition && Definition != D) { + Decl *ImportedDef = Importer.Import(Definition); + if (!ImportedDef) + return 0; + + return Importer.Imported(D, ImportedDef); + } + + VarTemplateDecl *VarTemplate = cast_or_null( + Importer.Import(D->getSpecializedTemplate())); + if (!VarTemplate) + return 0; + + // Import the context of this declaration. + DeclContext *DC = VarTemplate->getDeclContext(); + if (!DC) + return 0; + + DeclContext *LexicalDC = DC; + if (D->getDeclContext() != D->getLexicalDeclContext()) { + LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); + if (!LexicalDC) + return 0; + } + + // Import the location of this declaration. + SourceLocation StartLoc = Importer.Import(D->getLocStart()); + SourceLocation IdLoc = Importer.Import(D->getLocation()); + + // Import template arguments. + SmallVector TemplateArgs; + if (ImportTemplateArguments(D->getTemplateArgs().data(), + D->getTemplateArgs().size(), TemplateArgs)) + return 0; + + // Try to find an existing specialization with these template arguments. + void *InsertPos = 0; + VarTemplateSpecializationDecl *D2 = VarTemplate->findSpecialization( + TemplateArgs.data(), TemplateArgs.size(), InsertPos); + if (D2) { + // We already have a variable template specialization with these template + // arguments. + + // FIXME: Check for specialization vs. instantiation errors. + + if (VarDecl *FoundDef = D2->getDefinition()) { + if (!D->isThisDeclarationADefinition() || + IsStructuralMatch(D, FoundDef)) { + // The record types structurally match, or the "from" translation + // unit only had a forward declaration anyway; call it the same + // variable. + return Importer.Imported(D, FoundDef); + } + } + } else { + + // Import the type. + QualType T = Importer.Import(D->getType()); + if (T.isNull()) + return 0; + TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); + + // Create a new specialization. + D2 = VarTemplateSpecializationDecl::Create( + Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, TInfo, + D->getStorageClass(), TemplateArgs.data(), TemplateArgs.size()); + D2->setSpecializationKind(D->getSpecializationKind()); + D2->setTemplateArgsInfo(D->getTemplateArgsInfo()); + + // Add this specialization to the class template. + VarTemplate->AddSpecialization(D2, InsertPos); + + // Import the qualifier, if any. + D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); + + // Add the specialization to this context. + D2->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(D2); + } + Importer.Imported(D, D2); + + if (D->isThisDeclarationADefinition() && ImportDefinition(D, D2)) + return 0; + + return D2; +} + //---------------------------------------------------------------------------- // Import Statements //---------------------------------------------------------------------------- @@ -4406,7 +4651,7 @@ Decl *ASTImporter::Import(Decl *FromD) { } else if (TypedefNameDecl *FromTypedef = dyn_cast(FromD)) { // When we've finished transforming a typedef, see whether it was the // typedef for an anonymous tag. - for (SmallVector::iterator + for (SmallVectorImpl::iterator FromTag = AnonTagsWithPendingTypedefs.begin(), FromTagEnd = AnonTagsWithPendingTypedefs.end(); FromTag != FromTagEnd; ++FromTag) { diff --git a/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp b/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp new file mode 100644 index 0000000..ae47ea9 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp @@ -0,0 +1,105 @@ +//===--- ASTTypeTraits.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Provides a dynamic type identifier and a dynamically typed node container +// that can be used to store an AST base node at runtime in the same storage in +// a type safe way. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTTypeTraits.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" + +namespace clang { +namespace ast_type_traits { + +const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { + { NKI_None, "" }, + { NKI_None, "CXXCtorInitializer" }, + { NKI_None, "TemplateArgument" }, + { NKI_None, "NestedNameSpecifier" }, + { NKI_None, "NestedNameSpecifierLoc" }, + { NKI_None, "QualType" }, + { NKI_None, "TypeLoc" }, + { NKI_None, "Decl" }, +#define DECL(DERIVED, BASE) { NKI_##BASE, #DERIVED "Decl" }, +#include "clang/AST/DeclNodes.inc" + { NKI_None, "Stmt" }, +#define STMT(DERIVED, BASE) { NKI_##BASE, #DERIVED }, +#include "clang/AST/StmtNodes.inc" + { NKI_None, "Type" }, +#define TYPE(DERIVED, BASE) { NKI_##BASE, #DERIVED "Type" }, +#include "clang/AST/TypeNodes.def" +}; + +bool ASTNodeKind::isBaseOf(ASTNodeKind Other) const { + return isBaseOf(KindId, Other.KindId); +} + +bool ASTNodeKind::isSame(ASTNodeKind Other) const { + return KindId != NKI_None && KindId == Other.KindId; +} + +bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived) { + if (Base == NKI_None || Derived == NKI_None) return false; + while (Derived != Base && Derived != NKI_None) + Derived = AllKindInfo[Derived].ParentId; + return Derived == Base; +} + +StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; } + +void DynTypedNode::print(llvm::raw_ostream &OS, + const PrintingPolicy &PP) const { + if (const TemplateArgument *TA = get()) + TA->print(PP, OS); + else if (const NestedNameSpecifier *NNS = get()) + NNS->print(OS, PP); + else if (const NestedNameSpecifierLoc *NNSL = get()) + NNSL->getNestedNameSpecifier()->print(OS, PP); + else if (const QualType *QT = get()) + QT->print(OS, PP); + else if (const TypeLoc *TL = get()) + TL->getType().print(OS, PP); + else if (const Decl *D = get()) + D->print(OS, PP); + else if (const Stmt *S = get()) + S->printPretty(OS, 0, PP); + else if (const Type *T = get()) + QualType(T, 0).print(OS, PP); + else + OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n"; +} + +void DynTypedNode::dump(llvm::raw_ostream &OS, SourceManager &SM) const { + if (const Decl *D = get()) + D->dump(OS); + else if (const Stmt *S = get()) + S->dump(OS, SM); + else + OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n"; +} + +SourceRange DynTypedNode::getSourceRange() const { + if (const CXXCtorInitializer *CCI = get()) + return CCI->getSourceRange(); + if (const NestedNameSpecifierLoc *NNSL = get()) + return NNSL->getSourceRange(); + if (const TypeLoc *TL = get()) + return TL->getSourceRange(); + if (const Decl *D = get()) + return D->getSourceRange(); + if (const Stmt *S = get()) + return S->getSourceRange(); + return SourceRange(); +} + +} // end namespace ast_type_traits +} // end namespace clang diff --git a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp index daf65e5..7af3c8b 100644 --- a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp @@ -15,6 +15,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/AST/Type.h" +#include "llvm/ADT/StringSwitch.h" using namespace clang; Attr::~Attr() { } diff --git a/contrib/llvm/tools/clang/lib/AST/CXXABI.h b/contrib/llvm/tools/clang/lib/AST/CXXABI.h index 6d67d9a..89203f1 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXABI.h +++ b/contrib/llvm/tools/clang/lib/AST/CXXABI.h @@ -21,6 +21,7 @@ namespace clang { class ASTContext; class MemberPointerType; +class MangleNumberingContext; /// Implements C++ ABI-specific semantic analysis functions. class CXXABI { @@ -34,9 +35,12 @@ public: /// Returns the default calling convention for C++ methods. virtual CallingConv getDefaultMethodCallConv(bool isVariadic) const = 0; - // Returns whether the given class is nearly empty, with just virtual pointers - // and no data except possibly virtual bases. + /// Returns whether the given class is nearly empty, with just virtual + /// pointers and no data except possibly virtual bases. virtual bool isNearlyEmpty(const CXXRecordDecl *RD) const = 0; + + /// Returns a new mangling number context for this C++ ABI. + virtual MangleNumberingContext *createMangleNumberingContext() const = 0; }; /// Creates an instance of a C++ ABI class. diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp index 0e0b35d..b51014b 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp @@ -168,9 +168,9 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches, } } - if (Queue.empty()) break; - Record = Queue.back(); // not actually a queue. - Queue.pop_back(); + if (Queue.empty()) + break; + Record = Queue.pop_back_val(); // not actually a queue. } return AllMatches; @@ -447,7 +447,7 @@ FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, void OverridingMethods::add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding) { - SmallVector &SubobjectOverrides + SmallVectorImpl &SubobjectOverrides = Overrides[OverriddenSubobject]; if (std::find(SubobjectOverrides.begin(), SubobjectOverrides.end(), Overriding) == SubobjectOverrides.end()) @@ -650,11 +650,11 @@ CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const { SOEnd = OM->second.end(); SO != SOEnd; ++SO) { - SmallVector &Overriding = SO->second; + SmallVectorImpl &Overriding = SO->second; if (Overriding.size() < 2) continue; - for (SmallVector::iterator + for (SmallVectorImpl::iterator Pos = Overriding.begin(), PosEnd = Overriding.end(); Pos != PosEnd; /* increment in loop */) { @@ -669,7 +669,7 @@ CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const { // in a base class subobject that hides the virtual base class // subobject. bool Hidden = false; - for (SmallVector::iterator + for (SmallVectorImpl::iterator OP = Overriding.begin(), OPEnd = Overriding.end(); OP != OPEnd && !Hidden; ++OP) { diff --git a/contrib/llvm/tools/clang/lib/AST/Comment.cpp b/contrib/llvm/tools/clang/lib/AST/Comment.cpp index 68c73fd..f24a23d 100644 --- a/contrib/llvm/tools/clang/lib/AST/Comment.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Comment.cpp @@ -12,6 +12,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/Basic/CharInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -41,14 +42,16 @@ good implements_child_begin_end(Comment::child_iterator (T::*)() const) { return good(); } +LLVM_ATTRIBUTE_UNUSED static inline bad implements_child_begin_end( Comment::child_iterator (Comment::*)() const) { return bad(); } #define ASSERT_IMPLEMENTS_child_begin(function) \ - (void) sizeof(good(implements_child_begin_end(function))) + (void) good(implements_child_begin_end(function)) +LLVM_ATTRIBUTE_UNUSED static inline void CheckCommentASTNodes() { #define ABSTRACT_COMMENT(COMMENT) #define COMMENT(CLASS, PARENT) \ @@ -94,9 +97,7 @@ Comment::child_iterator Comment::child_end() const { bool TextComment::isWhitespaceNoCache() const { for (StringRef::const_iterator I = Text.begin(), E = Text.end(); I != E; ++I) { - const char C = *I; - if (C != ' ' && C != '\n' && C != '\r' && - C != '\t' && C != '\f' && C != '\v') + if (!clang::isWhitespace(*I)) return false; } return true; @@ -293,12 +294,14 @@ void DeclInfo::fill() { StringRef ParamCommandComment::getParamName(const FullComment *FC) const { assert(isParamIndexValid()); - return FC->getThisDeclInfo()->ParamVars[getParamIndex()]->getName(); + if (isVarArgParam()) + return "..."; + return FC->getDeclInfo()->ParamVars[getParamIndex()]->getName(); } StringRef TParamCommandComment::getParamName(const FullComment *FC) const { assert(isPositionValid()); - const TemplateParameterList *TPL = FC->getThisDeclInfo()->TemplateParameters; + const TemplateParameterList *TPL = FC->getDeclInfo()->TemplateParameters; for (unsigned i = 0, e = getDepth(); i != e; ++i) { if (i == e-1) return TPL->getParam(getIndex(i))->getName(); diff --git a/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp b/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp index e24d542..01bd12e 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp @@ -43,6 +43,49 @@ const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const { return getRegisteredCommandInfo(CommandID); } +static void +HelperTypoCorrectCommandInfo(SmallVectorImpl &BestCommand, + StringRef Typo, const CommandInfo *Command) { + const unsigned MaxEditDistance = 1; + unsigned BestEditDistance = MaxEditDistance + 1; + StringRef Name = Command->Name; + + unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size()); + if (MinPossibleEditDistance > 0 && + Typo.size() / MinPossibleEditDistance < 1) + return; + unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance); + if (EditDistance > MaxEditDistance) + return; + if (EditDistance == BestEditDistance) + BestCommand.push_back(Command); + else if (EditDistance < BestEditDistance) { + BestCommand.clear(); + BestCommand.push_back(Command); + BestEditDistance = EditDistance; + } +} + +const CommandInfo * +CommandTraits::getTypoCorrectCommandInfo(StringRef Typo) const { + // single character command impostures, such as \t or \n must not go + // through the fixit logic. + if (Typo.size() <= 1) + return NULL; + + SmallVector BestCommand; + + const int NumOfCommands = llvm::array_lengthof(Commands); + for (int i = 0; i < NumOfCommands; i++) + HelperTypoCorrectCommandInfo(BestCommand, Typo, &Commands[i]); + + for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) + if (!RegisteredCommands[i]->IsUnknownCommand) + HelperTypoCorrectCommandInfo(BestCommand, Typo, RegisteredCommands[i]); + + return (BestCommand.size() != 1) ? NULL : BestCommand[0]; +} + CommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) { char *Name = Allocator.Allocate(CommandName.size() + 1); memcpy(Name, CommandName.data(), CommandName.size()); diff --git a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp index 70410d6..01ed3ce 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp @@ -157,7 +157,7 @@ const char *skipDecimalCharacterReference(const char *BufferPtr, } const char *skipHexCharacterReference(const char *BufferPtr, - const char *BufferEnd) { + const char *BufferEnd) { for ( ; BufferPtr != BufferEnd; ++BufferPtr) { if (!isHTMLHexCharacterReferenceCharacter(*BufferPtr)) return BufferPtr; @@ -265,6 +265,7 @@ const char *findCCommentEnd(const char *BufferPtr, const char *BufferEnd) { } llvm_unreachable("buffer end hit before '*/' was seen"); } + } // unnamed namespace void Lexer::lexCommentText(Token &T) { @@ -352,10 +353,20 @@ void Lexer::lexCommentText(Token &T) { const CommandInfo *Info = Traits.getCommandInfoOrNULL(CommandName); if (!Info) { - formTokenWithChars(T, TokenPtr, tok::unknown_command); - T.setUnknownCommandName(CommandName); - Diag(T.getLocation(), diag::warn_unknown_comment_command_name); - return; + if ((Info = Traits.getTypoCorrectCommandInfo(CommandName))) { + StringRef CorrectedName = Info->Name; + SourceLocation Loc = getSourceLocation(BufferPtr); + SourceRange CommandRange(Loc.getLocWithOffset(1), + getSourceLocation(TokenPtr)); + Diag(Loc, diag::warn_correct_comment_command_name) + << CommandName << CorrectedName + << FixItHint::CreateReplacement(CommandRange, CorrectedName); + } else { + formTokenWithChars(T, TokenPtr, tok::unknown_command); + T.setUnknownCommandName(CommandName); + Diag(T.getLocation(), diag::warn_unknown_comment_command_name); + return; + } } if (Info->IsVerbatimBlockCommand) { setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, Info); diff --git a/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp b/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp index d89c79b..03e0101 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp @@ -16,6 +16,15 @@ #include "llvm/Support/ErrorHandling.h" namespace clang { + +static inline bool isWhitespace(llvm::StringRef S) { + for (StringRef::const_iterator I = S.begin(), E = S.end(); I != E; ++I) { + if (!isWhitespace(*I)) + return false; + } + return true; +} + namespace comments { /// Re-lexes a sequence of tok::text tokens. @@ -594,6 +603,18 @@ BlockContentComment *Parser::parseParagraphOrBlockCommand() { consumeToken(); break; // Two newlines -- end of paragraph. } + // Also allow [tok::newline, tok::text, tok::newline] if the middle + // tok::text is just whitespace. + if (Tok.is(tok::text) && isWhitespace(Tok.getText())) { + Token WhitespaceTok = Tok; + consumeToken(); + if (Tok.is(tok::newline) || Tok.is(tok::eof)) { + consumeToken(); + break; + } + // We have [tok::newline, tok::text, non-newline]. Put back tok::text. + putBack(WhitespaceTok); + } if (Content.size() > 0) Content.back()->addTrailingNewline(); continue; diff --git a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp index e0138d5..1c6222f 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp @@ -29,8 +29,7 @@ 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), - HeaderfileCommand(NULL) { + PP(PP), ThisDeclInfo(NULL), BriefCommand(NULL), HeaderfileCommand(NULL) { } void Sema::setDecl(const Decl *D) { @@ -99,10 +98,10 @@ void Sema::checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment) { unsigned DiagSelect; switch (Comment->getCommandID()) { case CommandTraits::KCI_function: - DiagSelect = !isAnyFunctionDecl() ? 1 : 0; + DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 1 : 0; break; case CommandTraits::KCI_functiongroup: - DiagSelect = !isAnyFunctionDecl() ? 2 : 0; + DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 2 : 0; break; case CommandTraits::KCI_method: DiagSelect = !isObjCMethodDecl() ? 3 : 0; @@ -131,7 +130,12 @@ void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) { unsigned DiagSelect; switch (Comment->getCommandID()) { case CommandTraits::KCI_class: - DiagSelect = !isClassOrStructDecl() ? 1 : 0; + DiagSelect = (!isClassOrStructDecl() && !isClassTemplateDecl()) ? 1 : 0; + // Allow @class command on @interface declarations. + // FIXME. Currently, \class and @class are indistinguishable. So, + // \class is also allowed on an @interface declaration + if (DiagSelect && Comment->getCommandMarker() && isObjCInterfaceDecl()) + DiagSelect = 0; break; case CommandTraits::KCI_interface: DiagSelect = !isObjCInterfaceDecl() ? 2 : 0; @@ -206,59 +210,43 @@ void Sema::checkContainerDecl(const BlockCommandComment *Comment) { << Comment->getSourceRange(); } +/// \brief Turn a string into the corresponding PassDirection or -1 if it's not +/// valid. +static int getParamPassDirection(StringRef Arg) { + return llvm::StringSwitch(Arg) + .Case("[in]", ParamCommandComment::In) + .Case("[out]", ParamCommandComment::Out) + .Cases("[in,out]", "[out,in]", ParamCommandComment::InOut) + .Default(-1); +} + void Sema::actOnParamCommandDirectionArg(ParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg) { - ParamCommandComment::PassDirection Direction; std::string ArgLower = Arg.lower(); - // TODO: optimize: lower Name first (need an API in SmallString for that), - // after that StringSwitch. - if (ArgLower == "[in]") - Direction = ParamCommandComment::In; - else if (ArgLower == "[out]") - Direction = ParamCommandComment::Out; - else if (ArgLower == "[in,out]" || ArgLower == "[out,in]") - Direction = ParamCommandComment::InOut; - else { - // Remove spaces. - std::string::iterator O = ArgLower.begin(); - for (std::string::iterator I = ArgLower.begin(), E = ArgLower.end(); - I != E; ++I) { - const char C = *I; - if (C != ' ' && C != '\n' && C != '\r' && - C != '\t' && C != '\v' && C != '\f') - *O++ = C; - } - ArgLower.resize(O - ArgLower.begin()); - - bool RemovingWhitespaceHelped = false; - if (ArgLower == "[in]") { - Direction = ParamCommandComment::In; - RemovingWhitespaceHelped = true; - } else if (ArgLower == "[out]") { - Direction = ParamCommandComment::Out; - RemovingWhitespaceHelped = true; - } else if (ArgLower == "[in,out]" || ArgLower == "[out,in]") { - Direction = ParamCommandComment::InOut; - RemovingWhitespaceHelped = true; - } else { - Direction = ParamCommandComment::In; - RemovingWhitespaceHelped = false; - } + int Direction = getParamPassDirection(ArgLower); + + if (Direction == -1) { + // Try again with whitespace removed. + ArgLower.erase( + std::remove_if(ArgLower.begin(), ArgLower.end(), clang::isWhitespace), + ArgLower.end()); + Direction = getParamPassDirection(ArgLower); SourceRange ArgRange(ArgLocBegin, ArgLocEnd); - if (RemovingWhitespaceHelped) + if (Direction != -1) { + const char *FixedName = ParamCommandComment::getDirectionAsString( + (ParamCommandComment::PassDirection)Direction); Diag(ArgLocBegin, diag::warn_doc_param_spaces_in_direction) - << ArgRange - << FixItHint::CreateReplacement( - ArgRange, - ParamCommandComment::getDirectionAsString(Direction)); - else - Diag(ArgLocBegin, diag::warn_doc_param_invalid_direction) - << ArgRange; + << ArgRange << FixItHint::CreateReplacement(ArgRange, FixedName); + } else { + Diag(ArgLocBegin, diag::warn_doc_param_invalid_direction) << ArgRange; + Direction = ParamCommandComment::In; // Sane fall back. + } } - Command->setDirection(Direction, /* Explicit = */ true); + Command->setDirection((ParamCommandComment::PassDirection)Direction, + /*Explicit=*/true); } void Sema::actOnParamCommandParamNameArg(ParamCommandComment *Command, @@ -326,17 +314,15 @@ void Sema::actOnTParamCommandParamNameArg(TParamCommandComment *Command, SmallVector Position; if (resolveTParamReference(Arg, TemplateParameters, &Position)) { Command->setPosition(copyArray(llvm::makeArrayRef(Position))); - llvm::StringMap::iterator PrevCommandIt = - TemplateParameterDocs.find(Arg); - if (PrevCommandIt != TemplateParameterDocs.end()) { + TParamCommandComment *&PrevCommand = TemplateParameterDocs[Arg]; + if (PrevCommand) { SourceRange ArgRange(ArgLocBegin, ArgLocEnd); Diag(ArgLocBegin, diag::warn_doc_tparam_duplicate) << Arg << ArgRange; - TParamCommandComment *PrevCommand = PrevCommandIt->second; Diag(PrevCommand->getLocation(), diag::note_doc_tparam_previous) << PrevCommand->getParamNameRange(); } - TemplateParameterDocs[Arg] = Command; + PrevCommand = Command; return; } @@ -511,8 +497,7 @@ HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin, } while (!HTMLOpenTags.empty()) { - const HTMLStartTagComment *HST = HTMLOpenTags.back(); - HTMLOpenTags.pop_back(); + const HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val(); StringRef LastNotClosedTagName = HST->getTagName(); if (LastNotClosedTagName == TagName) break; @@ -618,12 +603,6 @@ void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) { return; } PrevCommand = BriefCommand; - } else if (Info->IsReturnsCommand) { - if (!ReturnsCommand) { - ReturnsCommand = Command; - return; - } - PrevCommand = ReturnsCommand; } else if (Info->IsHeaderfileCommand) { if (!HeaderfileCommand) { HeaderfileCommand = Command; @@ -728,6 +707,10 @@ void Sema::resolveParamCommandIndexes(const FullComment *FC) { // Check that referenced parameter name is in the function decl. const unsigned ResolvedParamIndex = resolveParmVarReference(ParamName, ParamVars); + if (ResolvedParamIndex == ParamCommandComment::VarArgParamIndex) { + PCC->setIsVarArgParam(); + continue; + } if (ResolvedParamIndex == ParamCommandComment::InvalidParamIndex) { UnresolvedParamCommands.push_back(PCC); continue; @@ -798,14 +781,24 @@ bool Sema::isAnyFunctionDecl() { return isFunctionDecl() && ThisDeclInfo->CurrentDecl && isa(ThisDeclInfo->CurrentDecl); } - + +bool Sema::isFunctionOrMethodVariadic() { + if (!isAnyFunctionDecl() && !isObjCMethodDecl()) + return false; + if (const FunctionDecl *FD = + dyn_cast(ThisDeclInfo->CurrentDecl)) + return FD->isVariadic(); + if (const ObjCMethodDecl *MD = + dyn_cast(ThisDeclInfo->CurrentDecl)) + return MD->isVariadic(); + return false; +} + bool Sema::isObjCMethodDecl() { return isFunctionDecl() && ThisDeclInfo->CurrentDecl && isa(ThisDeclInfo->CurrentDecl); } - -/// isFunctionPointerVarDecl - returns 'true' if declaration is a pointer to -/// function decl. + bool Sema::isFunctionPointerVarDecl() { if (!ThisDeclInfo) return false; @@ -865,6 +858,24 @@ bool Sema::isClassOrStructDecl() { isa(ThisDeclInfo->CurrentDecl) && !isUnionDecl(); } + +bool Sema::isClassTemplateDecl() { + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + return ThisDeclInfo->CurrentDecl && + (isa(ThisDeclInfo->CurrentDecl)); +} + +bool Sema::isFunctionTemplateDecl() { + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + return ThisDeclInfo->CurrentDecl && + (isa(ThisDeclInfo->CurrentDecl)); +} bool Sema::isObjCInterfaceDecl() { if (!ThisDeclInfo) @@ -901,6 +912,8 @@ unsigned Sema::resolveParmVarReference(StringRef Name, if (II && II->getName() == Name) return i; } + if (Name == "..." && isFunctionOrMethodVariadic()) + return ParamCommandComment::VarArgParamIndex; return ParamCommandComment::InvalidParamIndex; } diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index ab9d73b..6bd9858 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -34,6 +34,10 @@ using namespace clang; +Decl *clang::getPrimaryMergedDecl(Decl *D) { + return D->getASTContext().getPrimaryMergedDecl(D); +} + //===----------------------------------------------------------------------===// // NamedDecl Implementation //===----------------------------------------------------------------------===// @@ -85,6 +89,7 @@ using namespace clang; // and settings from the immediate context. const unsigned IgnoreExplicitVisibilityBit = 2; +const unsigned IgnoreAllVisibilityBit = 4; /// Kinds of LV computation. The linkage side of the computation is /// always the same, but different things can change how visibility is @@ -108,7 +113,11 @@ enum LVComputationKind { /// 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) + LVForExplicitValue = (LVForValue | IgnoreExplicitVisibilityBit), + + /// Do an LV computation when we only care about the linkage. + LVForLinkageOnly = + LVForValue | IgnoreExplicitVisibilityBit | IgnoreAllVisibilityBit }; /// Does this computation kind permit us to consider additional @@ -211,11 +220,19 @@ static Optional getVisibilityOf(const NamedDecl *D, return None; } +static LinkageInfo +getLVForType(const Type &T, LVComputationKind computation) { + if (computation == LVForLinkageOnly) + return LinkageInfo(T.getLinkage(), DefaultVisibility, true); + return T.getLinkageAndVisibility(); +} + /// \brief Get the most restrictive linkage for the types in the given /// template parameter list. For visibility purposes, template /// parameters are part of the signature of a template. static LinkageInfo -getLVForTemplateParameterList(const TemplateParameterList *params) { +getLVForTemplateParameterList(const TemplateParameterList *params, + LVComputationKind computation) { LinkageInfo LV; for (TemplateParameterList::const_iterator P = params->begin(), PEnd = params->end(); @@ -234,7 +251,7 @@ getLVForTemplateParameterList(const TemplateParameterList *params) { // Handle the non-pack case first. if (!NTTP->isExpandedParameterPack()) { if (!NTTP->getType()->isDependentType()) { - LV.merge(NTTP->getType()->getLinkageAndVisibility()); + LV.merge(getLVForType(*NTTP->getType(), computation)); } continue; } @@ -254,7 +271,8 @@ getLVForTemplateParameterList(const TemplateParameterList *params) { // Handle the non-pack case first. if (!TTP->isExpandedParameterPack()) { - LV.merge(getLVForTemplateParameterList(TTP->getTemplateParameters())); + LV.merge(getLVForTemplateParameterList(TTP->getTemplateParameters(), + computation)); continue; } @@ -262,7 +280,7 @@ getLVForTemplateParameterList(const TemplateParameterList *params) { for (unsigned i = 0, n = TTP->getNumExpansionTemplateParameters(); i != n; ++i) { LV.merge(getLVForTemplateParameterList( - TTP->getExpansionTemplateParameters(i))); + TTP->getExpansionTemplateParameters(i), computation)); } } @@ -273,13 +291,25 @@ getLVForTemplateParameterList(const TemplateParameterList *params) { static LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation); +static const Decl *getOutermostFuncOrBlockContext(const Decl *D) { + const Decl *Ret = NULL; + const DeclContext *DC = D->getDeclContext(); + while (DC->getDeclKind() != Decl::TranslationUnit) { + if (isa(DC) || isa(DC)) + Ret = cast(DC); + DC = DC->getParent(); + } + return Ret; +} + /// \brief Get the most restrictive linkage for the types and /// declarations in the given template argument list. /// /// 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 args) { +getLVForTemplateArgumentList(ArrayRef args, + LVComputationKind computation) { LinkageInfo LV; for (unsigned i = 0, e = args.size(); i != e; ++i) { @@ -291,13 +321,13 @@ getLVForTemplateArgumentList(ArrayRef args) { continue; case TemplateArgument::Type: - LV.merge(arg.getAsType()->getLinkageAndVisibility()); + LV.merge(getLVForType(*arg.getAsType(), computation)); continue; case TemplateArgument::Declaration: if (NamedDecl *ND = dyn_cast(arg.getAsDecl())) { assert(!usesTypeVisibility(ND)); - LV.merge(getLVForDecl(ND, LVForValue)); + LV.merge(getLVForDecl(ND, computation)); } continue; @@ -309,11 +339,11 @@ getLVForTemplateArgumentList(ArrayRef args) { case TemplateArgument::TemplateExpansion: if (TemplateDecl *Template = arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) - LV.merge(getLVForDecl(Template, LVForValue)); + LV.merge(getLVForDecl(Template, computation)); continue; case TemplateArgument::Pack: - LV.merge(getLVForTemplateArgumentList(arg.getPackAsArray())); + LV.merge(getLVForTemplateArgumentList(arg.getPackAsArray(), computation)); continue; } llvm_unreachable("bad template argument kind"); @@ -323,8 +353,9 @@ getLVForTemplateArgumentList(ArrayRef args) { } static LinkageInfo -getLVForTemplateArgumentList(const TemplateArgumentList &TArgs) { - return getLVForTemplateArgumentList(TArgs.asArray()); +getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, + LVComputationKind computation) { + return getLVForTemplateArgumentList(TArgs.asArray(), computation); } static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn, @@ -348,19 +379,20 @@ static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn, /// \param[out] LV the computation to use for the parent static void mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn, - const FunctionTemplateSpecializationInfo *specInfo) { + const FunctionTemplateSpecializationInfo *specInfo, + LVComputationKind computation) { bool considerVisibility = shouldConsiderTemplateVisibility(fn, specInfo); // Merge information from the template parameters. FunctionTemplateDecl *temp = specInfo->getTemplate(); LinkageInfo tempLV = - getLVForTemplateParameterList(temp->getTemplateParameters()); + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); LV.mergeMaybeWithVisibility(tempLV, considerVisibility); // Merge information from the template arguments. const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments; - LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs); + LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation); LV.mergeMaybeWithVisibility(argsLV, considerVisibility); } @@ -379,6 +411,8 @@ static bool hasDirectVisibilityAttribute(const NamedDecl *D, if (D->hasAttr()) return true; return false; + case LVForLinkageOnly: + return false; } llvm_unreachable("bad visibility computation kind"); } @@ -431,7 +465,7 @@ static void mergeTemplateLV(LinkageInfo &LV, ClassTemplateDecl *temp = spec->getSpecializedTemplate(); LinkageInfo tempLV = - getLVForTemplateParameterList(temp->getTemplateParameters()); + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); LV.mergeMaybeWithVisibility(tempLV, considerVisibility && !hasExplicitVisibilityAlready(computation)); @@ -439,8 +473,10 @@ static void mergeTemplateLV(LinkageInfo &LV, // 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); + LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation); + if (considerVisibility) + LV.mergeVisibility(argsLV); + LV.mergeExternalVisibility(argsLV); } static bool useInlineVisibilityHidden(const NamedDecl *D) { @@ -472,7 +508,7 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) { } template static bool isFirstInExternCContext(T *D) { - const T *First = D->getFirstDeclaration(); + const T *First = D->getFirstDecl(); return First->isInExternCContext(); } @@ -508,7 +544,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, !Var->getType().isVolatileQualified()) { const VarDecl *PrevVar = Var->getPreviousDecl(); if (PrevVar) - return PrevVar->getLinkageAndVisibility(); + return getLVForDecl(PrevVar, computation); if (Var->getStorageClass() != SC_Extern && Var->getStorageClass() != SC_PrivateExtern && @@ -539,11 +575,10 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // Explicitly declared static. if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) return LinkageInfo(InternalLinkage, DefaultVisibility, false); - } else if (const FieldDecl *Field = dyn_cast(D)) { - // - a data member of an anonymous union. - if (cast(Field->getDeclContext())->isAnonymousStructOrUnion()) - return LinkageInfo::internal(); } + // - a data member of an anonymous union. + assert(!isa(D) && "Didn't expect an IndirectFieldDecl!"); + assert(!isa(D) && "Didn't expect a FieldDecl!"); if (D->isInAnonymousNamespace()) { const VarDecl *Var = dyn_cast(D); @@ -627,7 +662,7 @@ 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 && !isFirstInExternCContext(Var)) { - LinkageInfo TypeLV = Var->getType()->getLinkageAndVisibility(); + LinkageInfo TypeLV = getLVForType(*Var->getType(), computation); if (TypeLV.getLinkage() != ExternalLinkage) return LinkageInfo::uniqueExternal(); if (!LV.isVisibilityExplicit()) @@ -660,16 +695,27 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // this translation unit. However, we should use the C linkage // rules instead for extern "C" declarations. if (Context.getLangOpts().CPlusPlus && - !Function->isInExternCContext() && - Function->getType()->getLinkage() == UniqueExternalLinkage) - return LinkageInfo::uniqueExternal(); + !Function->isInExternCContext()) { + // Only look at the type-as-written. If this function has an auto-deduced + // return type, we can't compute the linkage of that type because it could + // require looking at the linkage of this function, and we don't need this + // for correctness because the type is not part of the function's + // signature. + // FIXME: This is a hack. We should be able to solve this circularity and + // the one in getLVForClassMember for Functions some other way. + QualType TypeAsWritten = Function->getType(); + if (TypeSourceInfo *TSI = Function->getTypeSourceInfo()) + TypeAsWritten = TSI->getType(); + if (TypeAsWritten->getLinkage() == UniqueExternalLinkage) + return LinkageInfo::uniqueExternal(); + } // 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()) { - mergeTemplateLV(LV, Function, specInfo); + mergeTemplateLV(LV, Function, specInfo, computation); } // - a named class (Clause 9), or an unnamed class defined in a @@ -695,7 +741,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, } else if (isa(D)) { LinkageInfo EnumLV = getLVForDecl(cast(D->getDeclContext()), computation); - if (!isExternalLinkage(EnumLV.getLinkage())) + if (!isExternalFormalLinkage(EnumLV.getLinkage())) return LinkageInfo::none(); LV.merge(EnumLV); @@ -704,7 +750,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, } else if (const TemplateDecl *temp = dyn_cast(D)) { bool considerVisibility = !hasExplicitVisibilityAlready(computation); LinkageInfo tempLV = - getLVForTemplateParameterList(temp->getTemplateParameters()); + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); LV.mergeMaybeWithVisibility(tempLV, considerVisibility); // - a namespace (7.3), unless it is declared within an unnamed @@ -739,6 +785,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, if (!(isa(D) || isa(D) || isa(D) || + isa(D) || isa(D))) return LinkageInfo::none(); @@ -766,13 +813,14 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LinkageInfo classLV = getLVForDecl(cast(D->getDeclContext()), classComputation); - if (!isExternalLinkage(classLV.getLinkage())) - return LinkageInfo::none(); - // If the class already has unique-external linkage, we can't improve. if (classLV.getLinkage() == UniqueExternalLinkage) return LinkageInfo::uniqueExternal(); + if (!isExternallyVisible(classLV.getLinkage())) + return LinkageInfo::none(); + + // Otherwise, don't merge in classLV yet, because in certain cases // we need to completely ignore the visibility from it. @@ -782,14 +830,25 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, if (const CXXMethodDecl *MD = dyn_cast(D)) { // If the type of the function uses a type with unique-external // linkage, it's not legally usable from outside this translation unit. - if (MD->getType()->getLinkage() == UniqueExternalLinkage) - return LinkageInfo::uniqueExternal(); - + // But only look at the type-as-written. If this function has an auto-deduced + // return type, we can't compute the linkage of that type because it could + // require looking at the linkage of this function, and we don't need this + // for correctness because the type is not part of the function's + // signature. + // FIXME: This is a hack. We should be able to solve this circularity and the + // one in getLVForNamespaceScopeDecl for Functions some other way. + { + QualType TypeAsWritten = MD->getType(); + if (TypeSourceInfo *TSI = MD->getTypeSourceInfo()) + TypeAsWritten = TSI->getType(); + if (TypeAsWritten->getLinkage() == UniqueExternalLinkage) + return LinkageInfo::uniqueExternal(); + } // If this is a method template specialization, use the linkage for // the template parameters and arguments. if (FunctionTemplateSpecializationInfo *spec = MD->getTemplateSpecializationInfo()) { - mergeTemplateLV(LV, MD, spec); + mergeTemplateLV(LV, MD, spec, computation); if (spec->isExplicitSpecialization()) { explicitSpecSuppressor = MD; } else if (isExplicitMemberSpecialization(spec->getTemplate())) { @@ -819,9 +878,10 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, } else if (const VarDecl *VD = dyn_cast(D)) { // Modify the variable's linkage by its type, but ignore the // type's visibility unless it's a definition. - LinkageInfo typeLV = VD->getType()->getLinkageAndVisibility(); - LV.mergeMaybeWithVisibility(typeLV, - !LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit()); + LinkageInfo typeLV = getLVForType(*VD->getType(), computation); + if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit()) + LV.mergeVisibility(typeLV); + LV.mergeExternalVisibility(typeLV); if (isExplicitMemberSpecialization(VD)) { explicitSpecSuppressor = VD; @@ -834,7 +894,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, !classLV.isVisibilityExplicit() && !hasExplicitVisibilityAlready(computation)); LinkageInfo tempLV = - getLVForTemplateParameterList(temp->getTemplateParameters()); + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); LV.mergeMaybeWithVisibility(tempLV, considerVisibility); if (const RedeclarableTemplateDecl *redeclTemp = @@ -866,81 +926,42 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, void NamedDecl::anchor() { } +static LinkageInfo computeLVForDecl(const NamedDecl *D, + LVComputationKind computation); + bool NamedDecl::isLinkageValid() const { - if (!HasCachedLinkage) + if (!hasCachedLinkage()) return true; - return getLVForDecl(this, LVForExplicitValue).getLinkage() == - Linkage(CachedLinkage); + return computeLVForDecl(this, LVForLinkageOnly).getLinkage() == + getCachedLinkage(); } -Linkage NamedDecl::getLinkage() const { - if (HasCachedLinkage) - return Linkage(CachedLinkage); - +Linkage NamedDecl::getLinkageInternal() const { // 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); + return getLVForDecl(this, LVForLinkageOnly).getLinkage(); } LinkageInfo NamedDecl::getLinkageAndVisibility() const { LVComputationKind computation = (usesTypeVisibility(this) ? LVForType : LVForValue); - LinkageInfo LI = getLVForDecl(this, computation); - if (HasCachedLinkage) { - assert(Linkage(CachedLinkage) == LI.getLinkage()); - return LI; - } - HasCachedLinkage = 1; - CachedLinkage = LI.getLinkage(); - -#ifndef NDEBUG - verifyLinkage(); -#endif - - return LI; + return getLVForDecl(this, computation); } -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(*I); - if (T == this) - continue; - if (T->HasCachedLinkage != 0) { - D = T; - break; - } - } - assert(!D || D->CachedLinkage == CachedLinkage); -} +static Optional +getExplicitVisibilityAux(const NamedDecl *ND, + NamedDecl::ExplicitVisibilityKind kind, + bool IsMostRecent) { + assert(!IsMostRecent || ND == ND->getMostRecentDecl()); -Optional -NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const { // Check the declaration itself first. - if (Optional V = getVisibilityOf(this, kind)) + if (Optional V = getVisibilityOf(ND, 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(this)) { + if (const CXXRecordDecl *RD = dyn_cast(ND)) { CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass(); if (InstantiatedFrom) return getVisibilityOf(InstantiatedFrom, kind); @@ -950,16 +971,18 @@ NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const { // specialization of a class template, check for visibility // on the pattern. if (const ClassTemplateSpecializationDecl *spec - = dyn_cast(this)) + = dyn_cast(ND)) return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(), kind); // Use the most recent declaration. - const NamedDecl *MostRecent = cast(this->getMostRecentDecl()); - if (MostRecent != this) - return MostRecent->getExplicitVisibility(kind); + if (!IsMostRecent && !isa(ND)) { + const NamedDecl *MostRecent = ND->getMostRecentDecl(); + if (MostRecent != ND) + return getExplicitVisibilityAux(MostRecent, kind, true); + } - if (const VarDecl *Var = dyn_cast(this)) { + if (const VarDecl *Var = dyn_cast(ND)) { if (Var->isStaticDataMember()) { VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember(); if (InstantiatedFrom) @@ -969,7 +992,7 @@ NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const { return None; } // Also handle function template specializations. - if (const FunctionDecl *fn = dyn_cast(this)) { + if (const FunctionDecl *fn = dyn_cast(ND)) { // If the function is a specialization of a template with an // explicit visibility attribute, use that. if (FunctionTemplateSpecializationInfo *templateInfo @@ -987,12 +1010,33 @@ NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const { } // The visibility of a template is stored in the templated decl. - if (const TemplateDecl *TD = dyn_cast(this)) + if (const TemplateDecl *TD = dyn_cast(ND)) return getVisibilityOf(TD->getTemplatedDecl(), kind); return None; } +Optional +NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const { + return getExplicitVisibilityAux(this, kind, false); +} + +static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, + LVComputationKind computation) { + // This lambda has its linkage/visibility determined by its owner. + if (ContextDecl) { + if (isa(ContextDecl)) + DC = ContextDecl->getDeclContext()->getRedeclContext(); + else + return getLVForDecl(cast(ContextDecl), computation); + } + + if (const NamedDecl *ND = dyn_cast(DC)) + return getLVForDecl(ND, computation); + + return LinkageInfo::external(); +} + static LinkageInfo getLVForLocalDecl(const NamedDecl *D, LVComputationKind computation) { if (const FunctionDecl *Function = dyn_cast(D)) { @@ -1040,13 +1084,55 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, return LV; } + + if (!Var->isStaticLocal()) + return LinkageInfo::none(); } - return LinkageInfo::none(); + ASTContext &Context = D->getASTContext(); + if (!Context.getLangOpts().CPlusPlus) + return LinkageInfo::none(); + + const Decl *OuterD = getOutermostFuncOrBlockContext(D); + if (!OuterD) + return LinkageInfo::none(); + + LinkageInfo LV; + if (const BlockDecl *BD = dyn_cast(OuterD)) { + if (!BD->getBlockManglingNumber()) + return LinkageInfo::none(); + + LV = getLVForClosure(BD->getDeclContext()->getRedeclContext(), + BD->getBlockManglingContextDecl(), computation); + } else { + const FunctionDecl *FD = cast(OuterD); + if (!FD->isInlined() && + FD->getTemplateSpecializationKind() == TSK_Undeclared) + return LinkageInfo::none(); + + LV = getLVForDecl(FD, computation); + } + if (!isExternallyVisible(LV.getLinkage())) + return LinkageInfo::none(); + return LinkageInfo(VisibleNoLinkage, LV.getVisibility(), + LV.isVisibilityExplicit()); } -static LinkageInfo getLVForDecl(const NamedDecl *D, - LVComputationKind computation) { +static inline const CXXRecordDecl* +getOutermostEnclosingLambda(const CXXRecordDecl *Record) { + const CXXRecordDecl *Ret = Record; + while (Record && Record->isLambda()) { + Ret = Record; + if (!Record->getParent()) break; + // Get the Containing Class of this Lambda Class + Record = dyn_cast_or_null( + Record->getParent()->getParent()); + } + return Ret; +} + +static LinkageInfo computeLVForDecl(const NamedDecl *D, + LVComputationKind computation) { // Objective-C: treat all Objective-C declarations as having external // linkage. switch (D->getKind()) { @@ -1074,20 +1160,25 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, // This lambda has no mangling number, so it's internal. return LinkageInfo::internal(); } - - // This lambda has its linkage/visibility determined by its owner. - const DeclContext *DC = D->getDeclContext()->getRedeclContext(); - if (Decl *ContextDecl = Record->getLambdaContextDecl()) { - if (isa(ContextDecl)) - DC = ContextDecl->getDeclContext()->getRedeclContext(); - else - return getLVForDecl(cast(ContextDecl), computation); - } - if (const NamedDecl *ND = dyn_cast(DC)) - return getLVForDecl(ND, computation); + // This lambda has its linkage/visibility determined: + // - either by the outermost lambda if that lambda has no mangling + // number. + // - or by the parent of the outer most lambda + // This prevents infinite recursion in settings such as nested lambdas + // used in NSDMI's, for e.g. + // struct L { + // int t{}; + // int t2 = ([](int a) { return [](int b) { return b; };})(t)(t); + // }; + const CXXRecordDecl *OuterMostLambda = + getOutermostEnclosingLambda(Record); + if (!OuterMostLambda->getLambdaManglingNumber()) + return LinkageInfo::internal(); - return LinkageInfo::external(); + return getLVForClosure( + OuterMostLambda->getDeclContext()->getRedeclContext(), + OuterMostLambda->getLambdaContextDecl(), computation); } break; @@ -1127,6 +1218,57 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, return LinkageInfo::none(); } +namespace clang { +class LinkageComputer { +public: + static LinkageInfo getLVForDecl(const NamedDecl *D, + LVComputationKind computation) { + if (computation == LVForLinkageOnly && D->hasCachedLinkage()) + return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); + + LinkageInfo LV = computeLVForDecl(D, computation); + if (D->hasCachedLinkage()) + assert(D->getCachedLinkage() == LV.getLinkage()); + + D->setCachedLinkage(LV.getLinkage()); + +#ifndef NDEBUG + // 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 = D->getASTContext().getLangOpts(); + if (!Opts.CPlusPlus || Opts.MicrosoftExt) + return LV; + + // 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 *Old = NULL; + for (NamedDecl::redecl_iterator I = D->redecls_begin(), + E = D->redecls_end(); + I != E; ++I) { + NamedDecl *T = cast(*I); + if (T == D) + continue; + if (T->hasCachedLinkage()) { + Old = T; + break; + } + } + assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage()); +#endif + + return LV; + } +}; +} + +static LinkageInfo getLVForDecl(const NamedDecl *D, + LVComputationKind computation) { + return clang::LinkageComputer::getLVForDecl(D, computation); +} + std::string NamedDecl::getQualifiedNameAsString() const { return getQualifiedNameAsString(getASTContext().getPrintingPolicy()); } @@ -1265,6 +1407,15 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { cast(OldD)->getQualifier()); } + if (isa(this) && + isa(OldD)) { + ASTContext &Context = getASTContext(); + return Context.getCanonicalNestedNameSpecifier( + cast(this)->getQualifier()) == + Context.getCanonicalNestedNameSpecifier( + cast(OldD)->getQualifier()); + } + // A typedef of an Objective-C class type can replace an Objective-C class // declaration or definition, and vice versa. if ((isa(this) && isa(OldD)) || @@ -1278,7 +1429,7 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { } bool NamedDecl::hasLinkage() const { - return getLinkage() != NoLinkage; + return getFormalLinkage() != NoLinkage; } NamedDecl *NamedDecl::getUnderlyingDeclImpl() { @@ -1469,6 +1620,17 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { llvm_unreachable("Invalid storage class"); } +VarDecl::VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, + TypeSourceInfo *TInfo, StorageClass SC) + : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() { + assert(sizeof(VarDeclBitfields) <= sizeof(unsigned)); + assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned)); + AllBits = 0; + VarDeclBits.SClass = SC; + // Everything else is implicitly initialized to false. +} + VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartL, SourceLocation IdL, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, @@ -1502,7 +1664,7 @@ template 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())) + if (!D.hasExternalFormalLinkage()) return NoLanguageLinkage; // Language linkage is a C++ concept, but saying that everything else in C has @@ -1547,32 +1709,15 @@ bool VarDecl::isExternC() const { return isExternCTemplate(*this); } -static bool isLinkageSpecContext(const DeclContext *DC, - LinkageSpecDecl::LanguageIDs ID) { - while (DC->getDeclKind() != Decl::TranslationUnit) { - if (DC->getDeclKind() == Decl::LinkageSpec) - return cast(DC)->getLanguage() == ID; - DC = DC->getParent(); - } - return false; -} - -template -static bool isInLanguageSpecContext(T *D, LinkageSpecDecl::LanguageIDs ID) { - return isLinkageSpecContext(D->getLexicalDeclContext(), ID); -} - bool VarDecl::isInExternCContext() const { - return isInLanguageSpecContext(this, LinkageSpecDecl::lang_c); + return getLexicalDeclContext()->isExternCContext(); } bool VarDecl::isInExternCXXContext() const { - return isInLanguageSpecContext(this, LinkageSpecDecl::lang_cxx); + return getLexicalDeclContext()->isExternCXXContext(); } -VarDecl *VarDecl::getCanonicalDecl() { - return getFirstDeclaration(); -} +VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); } VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( ASTContext &C) const @@ -1581,13 +1726,24 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( // A declaration is a definition unless [...] it contains the 'extern' // specifier or a linkage-specification and neither an initializer [...], // it declares a static data member in a class declaration [...]. - // C++ [temp.expl.spec]p15: - // An explicit specialization of a static data member of a template is a - // definition if the declaration includes an initializer; otherwise, it is - // a declaration. + // C++1y [temp.expl.spec]p15: + // An explicit specialization of a static data member or an explicit + // specialization of a static data member template is a definition if the + // declaration includes an initializer; otherwise, it is a declaration. + // + // FIXME: How do you declare (but not define) a partial specialization of + // a static data member template outside the containing class? if (isStaticDataMember()) { - if (isOutOfLine() && (hasInit() || - getTemplateSpecializationKind() != TSK_ExplicitSpecialization)) + if (isOutOfLine() && + (hasInit() || + // If the first declaration is out-of-line, this may be an + // instantiation of an out-of-line partial specialization of a variable + // template for which we have not yet instantiated the initializer. + (getFirstDecl()->isOutOfLine() + ? getTemplateSpecializationKind() == TSK_Undeclared + : getTemplateSpecializationKind() != + TSK_ExplicitSpecialization) || + isa(this))) return Definition; else return DeclarationOnly; @@ -1602,6 +1758,16 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( if (hasInit()) return Definition; + if (hasAttr()) + return Definition; + + // A variable template specialization (other than a static data member + // template or an explicit specialization) is a declaration until we + // instantiate its initializer. + if (isa(this) && + getTemplateSpecializationKind() != TSK_ExplicitSpecialization) + return DeclarationOnly; + if (hasExternalStorage()) return DeclarationOnly; @@ -1631,7 +1797,7 @@ VarDecl *VarDecl::getActingDefinition() { return 0; VarDecl *LastTentative = 0; - VarDecl *First = getFirstDeclaration(); + VarDecl *First = getFirstDecl(); for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); I != E; ++I) { Kind = (*I)->isThisDeclarationADefinition(); @@ -1643,20 +1809,8 @@ VarDecl *VarDecl::getActingDefinition() { return LastTentative; } -bool VarDecl::isTentativeDefinitionNow() const { - DefinitionKind Kind = isThisDeclarationADefinition(); - if (Kind != TentativeDefinition) - return false; - - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { - if ((*I)->isThisDeclarationADefinition() == Definition) - return false; - } - return true; -} - VarDecl *VarDecl::getDefinition(ASTContext &C) { - VarDecl *First = getFirstDeclaration(); + VarDecl *First = getFirstDecl(); for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); I != E; ++I) { if ((*I)->isThisDeclarationADefinition(C) == Definition) @@ -1668,7 +1822,7 @@ VarDecl *VarDecl::getDefinition(ASTContext &C) { VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const { DefinitionKind Kind = DeclarationOnly; - const VarDecl *First = getFirstDeclaration(); + const VarDecl *First = getFirstDecl(); for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); I != E; ++I) { Kind = std::max(Kind, (*I)->isThisDeclarationADefinition(C)); @@ -1763,6 +1917,10 @@ EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const { EvaluatedStmt *Eval = Init.dyn_cast(); if (!Eval) { Stmt *S = Init.get(); + // Note: EvaluatedStmt contains an APValue, which usually holds + // resources not allocated from the ASTContext. We need to do some + // work to avoid leaking those, but we do so in VarDecl::evaluateValue + // where we can detect whether there's anything to clean up or not. Eval = new (getASTContext()) EvaluatedStmt; Eval->Value = S; Init = Eval; @@ -1775,6 +1933,13 @@ APValue *VarDecl::evaluateValue() const { return evaluateValue(Notes); } +namespace { +// Destroy an APValue that was allocated in an ASTContext. +void DestroyAPValue(void* UntypedValue) { + static_cast(UntypedValue)->~APValue(); +} +} // namespace + APValue *VarDecl::evaluateValue( SmallVectorImpl &Notes) const { EvaluatedStmt *Eval = ensureEvaluatedStmt(); @@ -1800,9 +1965,13 @@ APValue *VarDecl::evaluateValue( bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, getASTContext(), this, Notes); - // Ensure the result is an uninitialized APValue if evaluation fails. + // Ensure the computed APValue is cleaned up later if evaluation succeeded, + // or that it's empty (so that there's nothing to clean up) if evaluation + // failed. if (!Result) Eval->Evaluated = APValue(); + else if (Eval->Evaluated.needsCleanup()) + getASTContext().AddDeallocation(DestroyAPValue, &Eval->Evaluated); Eval->IsEvaluating = false; Eval->WasEvaluated = true; @@ -1853,19 +2022,6 @@ bool VarDecl::checkInitIsICE() const { return Eval->IsICE; } -bool VarDecl::extendsLifetimeOfTemporary() const { - assert(getType()->isReferenceType() &&"Non-references never extend lifetime"); - - const Expr *E = getInit(); - if (!E) - return false; - - if (const ExprWithCleanups *Cleanups = dyn_cast(E)) - E = Cleanups->getSubExpr(); - - return isa(E); -} - VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const { if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) return cast(MSI->getInstantiatedFrom()); @@ -1874,25 +2030,73 @@ VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const { } TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const { + if (const VarTemplateSpecializationDecl *Spec = + dyn_cast(this)) + return Spec->getSpecializationKind(); + if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) return MSI->getTemplateSpecializationKind(); - + return TSK_Undeclared; } +SourceLocation VarDecl::getPointOfInstantiation() const { + if (const VarTemplateSpecializationDecl *Spec = + dyn_cast(this)) + return Spec->getPointOfInstantiation(); + + if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) + return MSI->getPointOfInstantiation(); + + return SourceLocation(); +} + +VarTemplateDecl *VarDecl::getDescribedVarTemplate() const { + return getASTContext().getTemplateOrSpecializationInfo(this) + .dyn_cast(); +} + +void VarDecl::setDescribedVarTemplate(VarTemplateDecl *Template) { + getASTContext().setTemplateOrSpecializationInfo(this, Template); +} + MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const { - return getASTContext().getInstantiatedFromStaticDataMember(this); + if (isStaticDataMember()) + // FIXME: Remove ? + // return getASTContext().getInstantiatedFromStaticDataMember(this); + return getASTContext().getTemplateOrSpecializationInfo(this) + .dyn_cast(); + return 0; } void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, SourceLocation PointOfInstantiation) { - MemberSpecializationInfo *MSI = getMemberSpecializationInfo(); - assert(MSI && "Not an instantiated static data member?"); - MSI->setTemplateSpecializationKind(TSK); - if (TSK != TSK_ExplicitSpecialization && - PointOfInstantiation.isValid() && - MSI->getPointOfInstantiation().isInvalid()) - MSI->setPointOfInstantiation(PointOfInstantiation); + assert((isa(this) || + getMemberSpecializationInfo()) && + "not a variable or static data member template specialization"); + + if (VarTemplateSpecializationDecl *Spec = + dyn_cast(this)) { + Spec->setSpecializationKind(TSK); + if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && + Spec->getPointOfInstantiation().isInvalid()) + Spec->setPointOfInstantiation(PointOfInstantiation); + } + + if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) { + MSI->setTemplateSpecializationKind(TSK); + if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && + MSI->getPointOfInstantiation().isInvalid()) + MSI->setPointOfInstantiation(PointOfInstantiation); + } +} + +void +VarDecl::setInstantiationOfStaticDataMember(VarDecl *VD, + TemplateSpecializationKind TSK) { + assert(getASTContext().getTemplateOrSpecializationInfo(this).isNull() && + "Previous template or instantiation?"); + getASTContext().setInstantiatedFromStaticDataMember(this, VD, TSK); } //===----------------------------------------------------------------------===// @@ -1908,6 +2112,14 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, S, DefArg); } +QualType ParmVarDecl::getOriginalType() const { + TypeSourceInfo *TSI = getTypeSourceInfo(); + QualType T = TSI ? TSI->getType() : getType(); + if (const DecayedType *DT = dyn_cast(T)) + return DT->getOriginalType(); + return T; +} + ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ParmVarDecl)); return new (Mem) ParmVarDecl(ParmVar, 0, SourceLocation(), SourceLocation(), @@ -2010,7 +2222,8 @@ bool FunctionDecl::hasTrivialBody() const bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const { for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { - if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed) { + if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed || + I->hasAttr()) { Definition = I->IsDeleted ? I->getCanonicalDecl() : *I; return true; } @@ -2020,15 +2233,11 @@ bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const { } Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { - if (I->Body) { - Definition = *I; - return I->Body.get(getASTContext().getExternalSource()); - } else if (I->IsLateTemplateParsed) { - Definition = *I; - return 0; - } - } + if (!hasBody(Definition)) + return 0; + + if (Definition->Body) + return Definition->Body.get(getASTContext().getExternalSource()); return 0; } @@ -2046,13 +2255,45 @@ void FunctionDecl::setPure(bool P) { Parent->markedVirtualFunctionPure(); } +template +static bool isNamed(const NamedDecl *ND, const char (&Str)[Len]) { + IdentifierInfo *II = ND->getIdentifier(); + return II && II->isStr(Str); +} + bool FunctionDecl::isMain() const { const TranslationUnitDecl *tunit = dyn_cast(getDeclContext()->getRedeclContext()); return tunit && !tunit->getASTContext().getLangOpts().Freestanding && - getIdentifier() && - getIdentifier()->isStr("main"); + isNamed(this, "main"); +} + +bool FunctionDecl::isMSVCRTEntryPoint() const { + const TranslationUnitDecl *TUnit = + dyn_cast(getDeclContext()->getRedeclContext()); + if (!TUnit) + return false; + + // Even though we aren't really targeting MSVCRT if we are freestanding, + // semantic analysis for these functions remains the same. + + // MSVCRT entry points only exist on MSVCRT targets. + if (!TUnit->getASTContext().getTargetInfo().getTriple().isOSMSVCRT()) + return false; + + // Nameless functions like constructors cannot be entry points. + if (!getIdentifier()) + return false; + + return llvm::StringSwitch(getName()) + .Cases("main", // an ANSI console app + "wmain", // a Unicode console App + "WinMain", // an ANSI GUI app + "wWinMain", // a Unicode GUI app + "DllMain", // a DLL + true) + .Default(false); } bool FunctionDecl::isReservedGlobalPlacementOperator() const { @@ -2077,13 +2318,83 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { return (proto->getArgType(1).getCanonicalType() == Context.VoidPtrTy); } -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; +static bool isNamespaceStd(const DeclContext *DC) { + const NamespaceDecl *ND = dyn_cast(DC->getRedeclContext()); + return ND && isNamed(ND, "std") && + ND->getParent()->getRedeclContext()->isTranslationUnit(); +} +bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { + if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName) + return false; + if (getDeclName().getCXXOverloadedOperator() != OO_New && + getDeclName().getCXXOverloadedOperator() != OO_Delete && + getDeclName().getCXXOverloadedOperator() != OO_Array_New && + getDeclName().getCXXOverloadedOperator() != OO_Array_Delete) + return false; + + if (isa(getDeclContext())) + return false; + assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + + const FunctionProtoType *FPT = getType()->castAs(); + if (FPT->getNumArgs() > 2 || FPT->isVariadic()) + return false; + + // If this is a single-parameter function, it must be a replaceable global + // allocation or deallocation function. + if (FPT->getNumArgs() == 1) + return true; + + // Otherwise, we're looking for a second parameter whose type is + // 'const std::nothrow_t &', or, in C++1y, 'std::size_t'. + QualType Ty = FPT->getArgType(1); + ASTContext &Ctx = getASTContext(); + if (Ctx.getLangOpts().SizedDeallocation && + Ctx.hasSameType(Ty, Ctx.getSizeType())) + return true; + if (!Ty->isReferenceType()) + return false; + Ty = Ty->getPointeeType(); + if (Ty.getCVRQualifiers() != Qualifiers::Const) + return false; + // FIXME: Recognise nothrow_t in an inline namespace inside std? + const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + return RD && isNamed(RD, "nothrow_t") && isNamespaceStd(RD->getDeclContext()); +} + +FunctionDecl * +FunctionDecl::getCorrespondingUnsizedGlobalDeallocationFunction() const { + ASTContext &Ctx = getASTContext(); + if (!Ctx.getLangOpts().SizedDeallocation) + return 0; + + if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName) + return 0; + if (getDeclName().getCXXOverloadedOperator() != OO_Delete && + getDeclName().getCXXOverloadedOperator() != OO_Array_Delete) + return 0; + if (isa(getDeclContext())) + return 0; + assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + + if (getNumParams() != 2 || isVariadic() || + !Ctx.hasSameType(getType()->castAs()->getArgType(1), + Ctx.getSizeType())) + return 0; + + // This is a sized deallocation function. Find the corresponding unsized + // deallocation function. + lookup_const_result R = getDeclContext()->lookup(getDeclName()); + for (lookup_const_result::iterator RI = R.begin(), RE = R.end(); RI != RE; + ++RI) + if (FunctionDecl *FD = dyn_cast(*RI)) + if (FD->getNumParams() == 1 && !FD->isVariadic()) + return FD; + return 0; +} + +LanguageLinkage FunctionDecl::getLanguageLinkage() const { return getLanguageLinkageTemplate(*this); } @@ -2092,11 +2403,11 @@ bool FunctionDecl::isExternC() const { } bool FunctionDecl::isInExternCContext() const { - return isInLanguageSpecContext(this, LinkageSpecDecl::lang_c); + return getLexicalDeclContext()->isExternCContext(); } bool FunctionDecl::isInExternCXXContext() const { - return isInLanguageSpecContext(this, LinkageSpecDecl::lang_cxx); + return getLexicalDeclContext()->isExternCXXContext(); } bool FunctionDecl::isGlobal() const { @@ -2127,13 +2438,13 @@ bool FunctionDecl::isNoReturn() const { void FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { - redeclarable_base::setPreviousDeclaration(PrevDecl); + redeclarable_base::setPreviousDecl(PrevDecl); if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) { FunctionTemplateDecl *PrevFunTmpl = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0; assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch"); - FunTmpl->setPreviousDeclaration(PrevFunTmpl); + FunTmpl->setPreviousDecl(PrevFunTmpl); } if (PrevDecl && PrevDecl->IsInline) @@ -2141,12 +2452,10 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { } const FunctionDecl *FunctionDecl::getCanonicalDecl() const { - return getFirstDeclaration(); + return getFirstDecl(); } -FunctionDecl *FunctionDecl::getCanonicalDecl() { - return getFirstDeclaration(); -} +FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); } /// \brief Returns a value indicating whether this function /// corresponds to a builtin function. @@ -2166,6 +2475,22 @@ unsigned FunctionDecl::getBuiltinID() const { return 0; ASTContext &Context = getASTContext(); + if (Context.getLangOpts().CPlusPlus) { + const LinkageSpecDecl *LinkageDecl = dyn_cast( + getFirstDecl()->getDeclContext()); + // In C++, the first declaration of a builtin is always inside an implicit + // extern "C". + // FIXME: A recognised library function may not be directly in an extern "C" + // declaration, for instance "extern "C" { namespace std { decl } }". + if (!LinkageDecl || LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c) + return 0; + } + + // If the function is marked "overloadable", it has a different mangled name + // and is not the C library function. + if (getAttr()) + return 0; + if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) return BuiltinID; @@ -2177,22 +2502,7 @@ unsigned FunctionDecl::getBuiltinID() const { if (getStorageClass() == SC_Static) return 0; - // If this function is at translation-unit scope and we're not in - // C++, it refers to the C library function. - if (!Context.getLangOpts().CPlusPlus && - getDeclContext()->isTranslationUnit()) - return BuiltinID; - - // If the function is in an extern "C" linkage specification and is - // not marked "overloadable", it's the real function. - if (isa(getDeclContext()) && - cast(getDeclContext())->getLanguage() - == LinkageSpecDecl::lang_c && - !getAttr()) - return BuiltinID; - - // Not a builtin - return 0; + return BuiltinID; } @@ -2304,7 +2614,7 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { const FunctionDecl *Prev = this; bool FoundBody = false; while ((Prev = Prev->getPreviousDecl())) { - FoundBody |= Prev->Body; + FoundBody |= Prev->Body.isValid(); if (Prev->Body) { // If it's not the case that both 'inline' and 'extern' are @@ -2332,7 +2642,7 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { const FunctionDecl *Prev = this; bool FoundBody = false; while ((Prev = Prev->getPreviousDecl())) { - FoundBody |= Prev->Body; + FoundBody |= Prev->Body.isValid(); if (RedeclForcesDefC99(Prev)) return false; } @@ -2818,26 +3128,18 @@ unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { } unsigned FieldDecl::getFieldIndex() const { + const FieldDecl *Canonical = getCanonicalDecl(); + if (Canonical != this) + return Canonical->getFieldIndex(); + if (CachedFieldIndex) return CachedFieldIndex - 1; unsigned Index = 0; const RecordDecl *RD = getParent(); - const FieldDecl *LastFD = 0; - bool IsMsStruct = RD->isMsStruct(getASTContext()); for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); - I != E; ++I, ++Index) { - I->CachedFieldIndex = Index + 1; - - if (IsMsStruct) { - // Zero-length bitfields following non-bitfield members are ignored. - if (getASTContext().ZeroBitfieldFollowsNonBitfield(*I, LastFD)) { - --Index; - continue; - } - LastFD = *I; - } - } + I != E; ++I, ++Index) + I->getCanonicalDecl()->CachedFieldIndex = Index + 1; assert(CachedFieldIndex && "failed to find field in parent"); return CachedFieldIndex - 1; @@ -2874,12 +3176,10 @@ SourceRange TagDecl::getSourceRange() const { return SourceRange(getOuterLocStart(), E); } -TagDecl* TagDecl::getCanonicalDecl() { - return getFirstDeclaration(); -} +TagDecl *TagDecl::getCanonicalDecl() { return getFirstDecl(); } void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { - TypedefNameDeclOrQualifier = TDD; + NamedDeclOrQualifier = TDD; if (TypeForDecl) assert(TypeForDecl->isLinkageValid()); assert(isLinkageValid()); @@ -2936,7 +3236,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { if (QualifierLoc) { // Make sure the extended qualifier info is allocated. if (!hasExtInfo()) - TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; + NamedDeclOrQualifier = new (getASTContext()) ExtInfo; // Set qualifier info. getExtInfo()->QualifierLoc = QualifierLoc; } else { @@ -2944,7 +3244,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { if (hasExtInfo()) { if (getExtInfo()->NumTemplParamLists == 0) { getASTContext().Deallocate(getExtInfo()); - TypedefNameDeclOrQualifier = (TypedefNameDecl*) 0; + NamedDeclOrQualifier = (TypedefNameDecl*) 0; } else getExtInfo()->QualifierLoc = QualifierLoc; @@ -2959,7 +3259,7 @@ void TagDecl::setTemplateParameterListsInfo(ASTContext &Context, // Make sure the extended decl info is allocated. if (!hasExtInfo()) // Allocate external info struct. - TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; + NamedDeclOrQualifier = new (getASTContext()) ExtInfo; // Set the template parameter lists info. getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index 084a432..121c5a6 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -291,6 +291,16 @@ bool Decl::isUsed(bool CheckUsedAttr) const { return false; } +void Decl::markUsed(ASTContext &C) { + if (Used) + return; + + if (C.getASTMutationListener()) + C.getASTMutationListener()->DeclarationMarkedUsed(this); + + Used = true; +} + bool Decl::isReferenced() const { if (Referenced) return true; @@ -538,6 +548,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { return IDNS_Namespace; case FunctionTemplate: + case VarTemplate: return IDNS_Ordinary; case ClassTemplate: @@ -560,6 +571,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ClassTemplateSpecialization: case ClassTemplatePartialSpecialization: case ClassScopeFunctionSpecialization: + case VarTemplateSpecialization: + case VarTemplatePartialSpecialization: case ObjCImplementation: case ObjCCategory: case ObjCCategoryImpl: @@ -595,32 +608,6 @@ const AttrVec &Decl::getAttrs() const { return getASTContext().getDeclAttrs(this); } -void Decl::swapAttrs(Decl *RHS) { - bool HasLHSAttr = this->HasAttrs; - bool HasRHSAttr = RHS->HasAttrs; - - // Usually, neither decl has attrs, nothing to do. - if (!HasLHSAttr && !HasRHSAttr) return; - - // If 'this' has no attrs, swap the other way. - if (!HasLHSAttr) - return RHS->swapAttrs(this); - - ASTContext &Context = getASTContext(); - - // Handle the case when both decls have attrs. - if (HasRHSAttr) { - std::swap(Context.getDeclAttrs(this), Context.getDeclAttrs(RHS)); - return; - } - - // Otherwise, LHS has an attr and RHS doesn't. - Context.getDeclAttrs(RHS) = Context.getDeclAttrs(this); - Context.eraseDeclAttrs(this); - this->HasAttrs = false; - RHS->HasAttrs = true; -} - Decl *Decl::castFromDeclContext (const DeclContext *D) { Decl::Kind DK = D->getDeclKind(); switch(DK) { @@ -819,6 +806,24 @@ bool DeclContext::isTransparentContext() const { return false; } +static bool isLinkageSpecContext(const DeclContext *DC, + LinkageSpecDecl::LanguageIDs ID) { + while (DC->getDeclKind() != Decl::TranslationUnit) { + if (DC->getDeclKind() == Decl::LinkageSpec) + return cast(DC)->getLanguage() == ID; + DC = DC->getParent(); + } + return false; +} + +bool DeclContext::isExternCContext() const { + return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_c); +} + +bool DeclContext::isExternCXXContext() const { + return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_cxx); +} + bool DeclContext::Encloses(const DeclContext *DC) const { if (getPrimaryContext() != this) return getPrimaryContext()->Encloses(DC); @@ -939,11 +944,8 @@ void DeclContext::reconcileExternalVisibleStorage() { 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); - } + for (StoredDeclsMap::iterator I = Map.begin(); I != Map.end(); ++I) + I->second.setHasExternalDecls(); } /// \brief Load the declarations within this lexical storage from an @@ -996,8 +998,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC, if (!(Map = DC->LookupPtr.getPointer())) Map = DC->CreateStoredDeclsMap(Context); - // Add an entry to the map for this name, if it's not already present. - (*Map)[Name]; + (*Map)[Name].removeExternalDecls(); return DeclContext::lookup_result(); } @@ -1012,13 +1013,38 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, Map = DC->CreateStoredDeclsMap(Context); StoredDeclsList &List = (*Map)[Name]; - for (ArrayRef::iterator - I = Decls.begin(), E = Decls.end(); I != E; ++I) { - if (List.isNull()) - List.setOnlyValue(*I); - else - // FIXME: Need declarationReplaces handling for redeclarations in modules. - List.AddSubsequentDecl(*I); + + // Clear out any old external visible declarations, to avoid quadratic + // performance in the redeclaration checks below. + List.removeExternalDecls(); + + if (!List.isNull()) { + // We have both existing declarations and new declarations for this name. + // Some of the declarations may simply replace existing ones. Handle those + // first. + llvm::SmallVector Skip; + for (unsigned I = 0, N = Decls.size(); I != N; ++I) + if (List.HandleRedeclaration(Decls[I])) + Skip.push_back(I); + Skip.push_back(Decls.size()); + + // Add in any new declarations. + unsigned SkipPos = 0; + for (unsigned I = 0, N = Decls.size(); I != N; ++I) { + if (I == Skip[SkipPos]) + ++SkipPos; + else + List.AddSubsequentDecl(Decls[I]); + } + } else { + // Convert the array to a StoredDeclsList. + for (ArrayRef::iterator + I = Decls.begin(), E = Decls.end(); I != E; ++I) { + if (List.isNull()) + List.setOnlyValue(*I); + else + List.AddSubsequentDecl(*I); + } } return List.getLookupResult(); @@ -1171,7 +1197,8 @@ StoredDeclsMap *DeclContext::buildLookup() { SmallVector Contexts; collectAllContexts(Contexts); for (unsigned I = 0, N = Contexts.size(); I != N; ++I) - buildLookupImpl(Contexts[I]); + buildLookupImpl<&DeclContext::decls_begin, + &DeclContext::decls_end>(Contexts[I]); // We no longer have any lazy decls. LookupPtr.setInt(false); @@ -1183,16 +1210,26 @@ StoredDeclsMap *DeclContext::buildLookup() { /// declarations contained within DCtx, which will either be this /// DeclContext, a DeclContext linked to it, or a transparent context /// nested within it. +template void DeclContext::buildLookupImpl(DeclContext *DCtx) { - for (decl_iterator I = DCtx->decls_begin(), E = DCtx->decls_end(); + for (decl_iterator I = (DCtx->*Begin)(), E = (DCtx->*End)(); I != E; ++I) { Decl *D = *I; // Insert this declaration into the lookup structure, but only if // it's semantically within its decl context. Any other decls which // should be found in this context are added eagerly. + // + // If it's from an AST file, don't add it now. It'll get handled by + // FindExternalVisibleDeclsByName if needed. Exception: if we're not + // in C++, we do not track external visible decls for the TU, so in + // that case we need to collect them all here. if (NamedDecl *ND = dyn_cast(D)) - if (ND->getDeclContext() == DCtx && !shouldBeHidden(ND)) + if (ND->getDeclContext() == DCtx && !shouldBeHidden(ND) && + (!ND->isFromASTFile() || + (isTranslationUnit() && + !getParentASTContext().getLangOpts().CPlusPlus))) makeDeclVisibleInContextImpl(ND, false); // If this declaration is itself a transparent declaration context @@ -1200,7 +1237,7 @@ void DeclContext::buildLookupImpl(DeclContext *DCtx) { // context (recursively). if (DeclContext *InnerCtx = dyn_cast(D)) if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace()) - buildLookupImpl(InnerCtx); + buildLookupImpl(InnerCtx); } } @@ -1223,16 +1260,14 @@ DeclContext::lookup(DeclarationName Name) { 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. + // If we have a lookup result with no external decls, we are done. std::pair R = Map->insert(std::make_pair(Name, StoredDeclsList())); - if (!R.second) + if (!R.second && !R.first->second.hasExternalDecls()) return R.first->second.getLookupResult(); ExternalASTSource *Source = getParentASTContext().getExternalSource(); - if (Source->FindExternalVisibleDeclsByName(this, Name)) { + if (Source->FindExternalVisibleDeclsByName(this, Name) || R.second) { if (StoredDeclsMap *Map = LookupPtr.getPointer()) { StoredDeclsMap::iterator I = Map->find(Name); if (I != Map->end()) @@ -1257,6 +1292,46 @@ DeclContext::lookup(DeclarationName Name) { return I->second.getLookupResult(); } +DeclContext::lookup_result +DeclContext::noload_lookup(DeclarationName Name) { + assert(DeclKind != Decl::LinkageSpec && + "Should not perform lookups into linkage specs!"); + if (!hasExternalVisibleStorage()) + return lookup(Name); + + DeclContext *PrimaryContext = getPrimaryContext(); + if (PrimaryContext != this) + return PrimaryContext->noload_lookup(Name); + + StoredDeclsMap *Map = LookupPtr.getPointer(); + if (LookupPtr.getInt()) { + // Carefully build the lookup map, without deserializing anything. + SmallVector Contexts; + collectAllContexts(Contexts); + for (unsigned I = 0, N = Contexts.size(); I != N; ++I) + buildLookupImpl<&DeclContext::noload_decls_begin, + &DeclContext::noload_decls_end>(Contexts[I]); + + // We no longer have any lazy decls. + LookupPtr.setInt(false); + + // There may now be names for which we have local decls but are + // missing the external decls. FIXME: Just set the hasExternalDecls + // flag on those names that have external decls. + NeedToReconcileExternalVisibleStorage = true; + + Map = LookupPtr.getPointer(); + } + + if (!Map) + return lookup_result(lookup_iterator(0), lookup_iterator(0)); + + StoredDeclsMap::iterator I = Map->find(Name); + return I != Map->end() + ? I->second.getLookupResult() + : lookup_result(lookup_iterator(0), lookup_iterator(0)); +} + void DeclContext::localUncachedLookup(DeclarationName Name, SmallVectorImpl &Results) { Results.clear(); @@ -1338,14 +1413,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, assert(this == getPrimaryContext() && "expected a primary DC"); // Skip declarations within functions. - // FIXME: We shouldn't need to build lookup tables for function declarations - // ever, and we can't do so correctly because we can't model the nesting of - // scopes which occurs within functions. We use "qualified" lookup into - // function declarations when handling friend declarations inside nested - // classes, and consequently accept the following invalid code: - // - // void f() { void g(); { int g; struct S { friend void g(); }; } } - if (isFunctionOrMethod() && !isa(D)) + if (isFunctionOrMethod()) return; // Skip declarations which should be invisible to name lookup. @@ -1406,7 +1474,18 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) { // Insert this declaration into the map. StoredDeclsList &DeclNameEntries = (*Map)[D->getDeclName()]; - if (DeclNameEntries.isNull()) { + + if (Internal) { + // If this is being added as part of loading an external declaration, + // this may not be the only external declaration with this name. + // In this case, we never try to replace an existing declaration; we'll + // handle that when we finalize the list of declarations for this name. + DeclNameEntries.setHasExternalDecls(); + DeclNameEntries.AddSubsequentDecl(D); + return; + } + + else if (DeclNameEntries.isNull()) { DeclNameEntries.setOnlyValue(D); return; } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index 0646499..a17abdd 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -10,9 +10,9 @@ // This file implements the C++ related Decl classes. // //===----------------------------------------------------------------------===// - #include "clang/AST/DeclCXX.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclTemplate.h" @@ -35,6 +35,17 @@ AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (Mem) AccessSpecDecl(EmptyShell()); } +void LazyASTUnresolvedSet::getFromExternalSource(ASTContext &C) const { + ExternalASTSource *Source = C.getExternalSource(); + assert(Impl.Decls.isLazy() && "getFromExternalSource for non-lazy set"); + assert(Source && "getFromExternalSource with no external source"); + + for (ASTUnresolvedSet::iterator I = Impl.begin(); I != Impl.end(); ++I) + I.setDecl(cast(Source->GetExternalDecl( + reinterpret_cast(I.getDecl()) >> 2))); + Impl.Decls.setLazy(false); +} + CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) : UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0), Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), @@ -60,9 +71,8 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) ImplicitCopyAssignmentHasConstParam(true), HasDeclaredCopyConstructorWithConstParam(false), HasDeclaredCopyAssignmentWithConstParam(false), - FailedImplicitMoveConstructor(false), FailedImplicitMoveAssignment(false), IsLambda(false), NumBases(0), NumVBases(0), Bases(), VBases(), - Definition(D), FirstFriend(0) { + Definition(D), FirstFriend() { } CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const { @@ -97,12 +107,17 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, - bool Dependent) { + bool Dependent, bool IsGeneric, + LambdaCaptureDefault CaptureDefault) { CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc, 0, 0); R->IsBeingDefined = true; - R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, Dependent); + R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, + Dependent, + IsGeneric, + CaptureDefault); R->MayHaveOutOfDateDef = false; + R->setImplicit(true); C.getTypeDeclType(R, /*PrevDecl=*/0); return R; } @@ -552,18 +567,16 @@ void CXXRecordDecl::addedMember(Decl *D) { if (Conversion->getPrimaryTemplate()) { // We don't record specializations. - } else if (FunTmpl) { - if (FunTmpl->getPreviousDecl()) - data().Conversions.replace(FunTmpl->getPreviousDecl(), - FunTmpl, AS); - else - data().Conversions.addDecl(getASTContext(), FunTmpl, AS); } else { - if (Conversion->getPreviousDecl()) - data().Conversions.replace(Conversion->getPreviousDecl(), - Conversion, AS); + ASTContext &Ctx = getASTContext(); + ASTUnresolvedSet &Conversions = data().Conversions.get(Ctx); + NamedDecl *Primary = + FunTmpl ? cast(FunTmpl) : cast(Conversion); + if (Primary->getPreviousDecl()) + Conversions.replace(cast(Primary->getPreviousDecl()), + Primary, AS); else - data().Conversions.addDecl(getASTContext(), Conversion, AS); + Conversions.addDecl(Ctx, Primary, AS); } } @@ -662,7 +675,7 @@ void CXXRecordDecl::addedMember(Decl *D) { if (!Context.getLangOpts().ObjCAutoRefCount || T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) setHasObjectMember(true); - } else if (!T.isPODType(Context)) + } else if (!T.isCXX98PODType(Context)) data().PlainOldData = false; if (T->isReferenceType()) { @@ -712,6 +725,13 @@ void CXXRecordDecl::addedMember(Decl *D) { if (FieldRec->getDefinition()) { addedClassSubobject(FieldRec); + // We may need to perform overload resolution to determine whether a + // field can be moved if it's const or volatile qualified. + if (T.getCVRQualifiers() & (Qualifiers::Const | Qualifiers::Volatile)) { + data().NeedOverloadResolutionForMoveConstructor = true; + data().NeedOverloadResolutionForMoveAssignment = true; + } + // C++11 [class.ctor]p5, C++11 [class.copy]p11: // A defaulted [special member] for a class X is defined as // deleted if: @@ -880,10 +900,13 @@ void CXXRecordDecl::addedMember(Decl *D) { } // Handle using declarations of conversion functions. - if (UsingShadowDecl *Shadow = dyn_cast(D)) + if (UsingShadowDecl *Shadow = dyn_cast(D)) { if (Shadow->getDeclName().getNameKind() - == DeclarationName::CXXConversionFunctionName) - data().Conversions.addDecl(getASTContext(), Shadow, Shadow->getAccess()); + == DeclarationName::CXXConversionFunctionName) { + ASTContext &Ctx = getASTContext(); + data().Conversions.get(Ctx).addDecl(Ctx, Shadow, Shadow->getAccess()); + } + } } void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) { @@ -929,6 +952,43 @@ bool CXXRecordDecl::isCLike() const { return isPOD() && data().HasOnlyCMembers; } + +bool CXXRecordDecl::isGenericLambda() const { + if (!isLambda()) return false; + return getLambdaData().IsGenericLambda; +} + +CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const { + if (!isLambda()) return 0; + DeclarationName Name = + getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); + DeclContext::lookup_const_result Calls = lookup(Name); + + assert(!Calls.empty() && "Missing lambda call operator!"); + assert(Calls.size() == 1 && "More than one lambda call operator!"); + + NamedDecl *CallOp = Calls.front(); + if (FunctionTemplateDecl *CallOpTmpl = + dyn_cast(CallOp)) + return cast(CallOpTmpl->getTemplatedDecl()); + + return cast(CallOp); +} + +CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const { + if (!isLambda()) return 0; + DeclarationName Name = + &getASTContext().Idents.get(getLambdaStaticInvokerName()); + DeclContext::lookup_const_result Invoker = lookup(Name); + if (Invoker.empty()) return 0; + assert(Invoker.size() == 1 && "More than one static invoker operator!"); + NamedDecl *InvokerFun = Invoker.front(); + if (FunctionTemplateDecl *InvokerTemplate = + dyn_cast(InvokerFun)) + return cast(InvokerTemplate->getTemplatedDecl()); + + return cast(InvokerFun); +} void CXXRecordDecl::getCaptureFields( llvm::DenseMap &Captures, @@ -940,15 +1000,22 @@ void CXXRecordDecl::getCaptureFields( RecordDecl::field_iterator Field = field_begin(); for (LambdaExpr::Capture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures; C != CEnd; ++C, ++Field) { - if (C->capturesThis()) { + if (C->capturesThis()) ThisCapture = *Field; - continue; - } - - Captures[C->getCapturedVar()] = *Field; + else if (C->capturesVariable()) + Captures[C->getCapturedVar()] = *Field; } + assert(Field == field_end()); } +TemplateParameterList * +CXXRecordDecl::getGenericLambdaTemplateParameterList() const { + if (!isLambda()) return 0; + CXXMethodDecl *CallOp = getLambdaCallOperator(); + if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate()) + return Tmpl->getTemplateParameters(); + return 0; +} static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { QualType T; @@ -1085,16 +1152,21 @@ static void CollectVisibleConversions(ASTContext &Context, /// in current class; including conversion function templates. std::pair CXXRecordDecl::getVisibleConversionFunctions() { - // If root class, all conversions are visible. - if (bases_begin() == bases_end()) - return std::make_pair(data().Conversions.begin(), data().Conversions.end()); - // If visible conversion list is already evaluated, return it. - if (!data().ComputedVisibleConversions) { - CollectVisibleConversions(getASTContext(), this, data().VisibleConversions); - data().ComputedVisibleConversions = true; + ASTContext &Ctx = getASTContext(); + + ASTUnresolvedSet *Set; + if (bases_begin() == bases_end()) { + // If root class, all conversions are visible. + Set = &data().Conversions.get(Ctx); + } else { + Set = &data().VisibleConversions.get(Ctx); + // If visible conversion list is not evaluated, evaluate it. + if (!data().ComputedVisibleConversions) { + CollectVisibleConversions(Ctx, this, *Set); + data().ComputedVisibleConversions = true; + } } - return std::make_pair(data().VisibleConversions.begin(), - data().VisibleConversions.end()); + return std::make_pair(Set->begin(), Set->end()); } void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { @@ -1109,7 +1181,7 @@ void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { // with sufficiently large numbers of directly-declared conversions // that asymptotic behavior matters. - ASTUnresolvedSet &Convs = data().Conversions; + ASTUnresolvedSet &Convs = data().Conversions.get(getASTContext()); for (unsigned I = 0, E = Convs.size(); I != E; ++I) { if (Convs[I].getDecl() == ConvDecl) { Convs.erase(I); @@ -1134,7 +1206,7 @@ CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD, TemplateSpecializationKind TSK) { assert(TemplateOrInstantiation.isNull() && "Previous template or instantiation?"); - assert(!isa(this)); + assert(!isa(this)); TemplateOrInstantiation = new (getASTContext()) MemberSpecializationInfo(RD, TSK); } @@ -1235,8 +1307,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { } // Set access bits correctly on the directly-declared conversions. - for (UnresolvedSetIterator I = data().Conversions.begin(), - E = data().Conversions.end(); + for (conversion_iterator I = conversion_begin(), E = conversion_end(); I != E; ++I) I.setAccess((*I)->getAccess()); } @@ -1266,21 +1337,8 @@ bool CXXMethodDecl::isStatic() const { 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; + OverloadedOperatorKind OOK = getDeclName().getCXXOverloadedOperator(); + return isStaticOverloadedOperator(OOK); } static bool recursivelyOverrides(const CXXMethodDecl *DerivedMD, @@ -1408,7 +1466,8 @@ bool CXXMethodDecl::isCopyAssignmentOperator() const { // type X, X&, const X&, volatile X& or const volatile X&. if (/*operator=*/getOverloadedOperator() != OO_Equal || /*non-static*/ isStatic() || - /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate()) + /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate() || + getNumParams() != 1) return false; QualType ParamType = getParamDecl(0)->getType(); @@ -1427,7 +1486,8 @@ bool CXXMethodDecl::isMoveAssignmentOperator() const { // non-template member function of class X with exactly one parameter of type // X&&, const X&&, volatile X&&, or const volatile X&&. if (getOverloadedOperator() != OO_Equal || isStatic() || - getPrimaryTemplate() || getDescribedFunctionTemplate()) + getPrimaryTemplate() || getDescribedFunctionTemplate() || + getNumParams() != 1) return false; QualType ParamType = getParamDecl(0)->getType(); @@ -1492,11 +1552,17 @@ bool CXXMethodDecl::hasInlineBody() const { } bool CXXMethodDecl::isLambdaStaticInvoker() const { - return getParent()->isLambda() && - getIdentifier() && getIdentifier()->getName() == "__invoke"; + const CXXRecordDecl *P = getParent(); + if (P->isLambda()) { + if (const CXXMethodDecl *StaticInvoker = P->getLambdaStaticInvoker()) { + if (StaticInvoker == this) return true; + if (P->isGenericLambda() && this->isFunctionTemplateSpecialization()) + return StaticInvoker == this->getPrimaryTemplate()->getTemplatedDecl(); + } + } + return false; } - CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual, SourceLocation L, Expr *Init, @@ -1865,7 +1931,7 @@ NamespaceDecl::NamespaceDecl(DeclContext *DC, bool Inline, : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), LocStart(StartLoc), RBraceLoc(), AnonOrFirstNamespaceAndInline(0, Inline) { - setPreviousDeclaration(PrevDecl); + setPreviousDecl(PrevDecl); if (PrevDecl) AnonOrFirstNamespaceAndInline.setPointer(PrevDecl->getOriginalNamespace()); @@ -1959,8 +2025,8 @@ void UsingDecl::removeShadowDecl(UsingShadowDecl *S) { UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, - bool IsTypeNameArg) { - return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, IsTypeNameArg); + bool HasTypename) { + return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, HasTypename); } UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, unsigned ID) { @@ -1969,6 +2035,12 @@ UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, unsigned ID) { DeclarationNameInfo(), false); } +SourceRange UsingDecl::getSourceRange() const { + SourceLocation Begin = isAccessDeclaration() + ? getQualifierLoc().getBeginLoc() : UsingLocation; + return SourceRange(Begin, getNameInfo().getEndLoc()); +} + void UnresolvedUsingValueDecl::anchor() { } UnresolvedUsingValueDecl * @@ -1988,6 +2060,12 @@ UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) { DeclarationNameInfo()); } +SourceRange UnresolvedUsingValueDecl::getSourceRange() const { + SourceLocation Begin = isAccessDeclaration() + ? getQualifierLoc().getBeginLoc() : UsingLocation; + return SourceRange(Begin, getNameInfo().getEndLoc()); +} + void UnresolvedUsingTypenameDecl::anchor() { } UnresolvedUsingTypenameDecl * diff --git a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp index 37a812e..1c639d6 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp @@ -63,3 +63,8 @@ FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, unsigned ID, return new (Mem) FriendDecl(EmptyShell(), FriendTypeNumTPLists); } +FriendDecl *CXXRecordDecl::getFirstFriend() const { + ExternalASTSource *Source = getParentASTContext().getExternalSource(); + Decl *First = data().FirstFriend.get(Source); + return First ? cast(First) : 0; +} diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp index 4ddbb22..b2b5b70 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp @@ -441,6 +441,17 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass( return NULL; } +ObjCProtocolDecl * +ObjCInterfaceDecl::lookupNestedProtocol(IdentifierInfo *Name) { + for (ObjCInterfaceDecl::all_protocol_iterator P = + all_referenced_protocol_begin(), PE = all_referenced_protocol_end(); + P != PE; ++P) + if ((*P)->lookupProtocolNamed(Name)) + return (*P); + ObjCInterfaceDecl *SuperClass = getSuperClass(); + return SuperClass ? SuperClass->lookupNestedProtocol(Name) : NULL; +} + /// lookupMethod - This method returns an instance/class method by looking in /// the class, its categories, and its super classes (using a linear search). /// When argument category "C" is specified, any implicit method found @@ -627,23 +638,29 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() { Decl *CtxD = cast(getDeclContext()); - if (ObjCInterfaceDecl *IFD = dyn_cast(CtxD)) { - if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD)) - Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); - - } else if (ObjCCategoryDecl *CD = dyn_cast(CtxD)) { - if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD)) - Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); - - } else if (ObjCImplementationDecl *ImplD = - dyn_cast(CtxD)) { - if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) - Redecl = IFD->getMethod(getSelector(), isInstanceMethod()); - - } else if (ObjCCategoryImplDecl *CImplD = - dyn_cast(CtxD)) { - if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) - Redecl = CatD->getMethod(getSelector(), isInstanceMethod()); + if (!CtxD->isInvalidDecl()) { + if (ObjCInterfaceDecl *IFD = dyn_cast(CtxD)) { + if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD)) + if (!ImplD->isInvalidDecl()) + Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); + + } else if (ObjCCategoryDecl *CD = dyn_cast(CtxD)) { + if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD)) + if (!ImplD->isInvalidDecl()) + Redecl = ImplD->getMethod(getSelector(), isInstanceMethod()); + + } else if (ObjCImplementationDecl *ImplD = + dyn_cast(CtxD)) { + if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) + if (!IFD->isInvalidDecl()) + Redecl = IFD->getMethod(getSelector(), isInstanceMethod()); + + } else if (ObjCCategoryImplDecl *CImplD = + dyn_cast(CtxD)) { + if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) + if (!CatD->isInvalidDecl()) + Redecl = CatD->getMethod(getSelector(), isInstanceMethod()); + } } if (!Redecl && isRedeclaration()) { @@ -1062,7 +1079,7 @@ ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc), TypeForDecl(0), Data() { - setPreviousDeclaration(PrevDecl); + setPreviousDecl(PrevDecl); // Copy the 'data' pointer over. if (PrevDecl) @@ -1308,7 +1325,8 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, - bool synthesized) { + bool synthesized, + bool backingIvarReferencedInAccessor) { if (DC) { // Ivar's can only appear in interfaces, implementations (via synthesized // properties), and class extensions (via direct declaration, or synthesized @@ -1336,13 +1354,13 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, } return new (C) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, - ac, BW, synthesized); + ac, BW, synthesized, backingIvarReferencedInAccessor); } ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCIvarDecl)); return new (Mem) ObjCIvarDecl(0, SourceLocation(), SourceLocation(), 0, - QualType(), 0, ObjCIvarDecl::None, 0, false); + QualType(), 0, ObjCIvarDecl::None, 0, false, false); } const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const { @@ -1401,7 +1419,7 @@ ObjCProtocolDecl::ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id, ObjCProtocolDecl *PrevDecl) : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc), Data() { - setPreviousDeclaration(PrevDecl); + setPreviousDecl(PrevDecl); if (PrevDecl) Data = PrevDecl->Data; } @@ -1493,6 +1511,30 @@ void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM, } } + +void ObjCProtocolDecl::collectInheritedProtocolProperties( + const ObjCPropertyDecl *Property, + ProtocolPropertyMap &PM) const { + if (const ObjCProtocolDecl *PDecl = getDefinition()) { + bool MatchFound = false; + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = *P; + if (Prop == Property) + continue; + if (Prop->getIdentifier() == Property->getIdentifier()) { + PM[PDecl] = Prop; + MatchFound = true; + break; + } + } + // Scan through protocol's protocols which did not have a matching property. + if (!MatchFound) + for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), + E = PDecl->protocol_end(); PI != E; ++PI) + (*PI)->collectInheritedProtocolProperties(Property, PM); + } +} //===----------------------------------------------------------------------===// // ObjCCategoryDecl diff --git a/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp index c0d10a0..0d195f7 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp @@ -28,9 +28,9 @@ void OMPThreadPrivateDecl::anchor() { } OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, - ArrayRef VL) { + ArrayRef VL) { unsigned Size = sizeof(OMPThreadPrivateDecl) + - (VL.size() * sizeof(DeclRefExpr *)); + (VL.size() * sizeof(Expr *)); void *Mem = C.Allocate(Size, llvm::alignOf()); OMPThreadPrivateDecl *D = new (Mem) OMPThreadPrivateDecl(OMPThreadPrivate, @@ -43,7 +43,7 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C, OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned N) { - unsigned Size = sizeof(OMPThreadPrivateDecl) + (N * sizeof(DeclRefExpr *)); + unsigned Size = sizeof(OMPThreadPrivateDecl) + (N * sizeof(Expr *)); void *Mem = AllocateDeserializedDecl(C, ID, Size); OMPThreadPrivateDecl *D = new (Mem) OMPThreadPrivateDecl(OMPThreadPrivate, @@ -52,9 +52,10 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C, return D; } -void OMPThreadPrivateDecl::setVars(ArrayRef VL) { +void OMPThreadPrivateDecl::setVars(ArrayRef VL) { assert(VL.size() == NumVars && "Number of variables is not the same as the preallocated buffer"); - DeclRefExpr **Vars = reinterpret_cast(this + 1); + Expr **Vars = reinterpret_cast(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 d47972b..767f662 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -260,6 +260,8 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { QualType CurDeclType = getDeclType(*D); if (!Decls.empty() && !CurDeclType.isNull()) { QualType BaseType = GetBaseType(CurDeclType); + if (!BaseType.isNull() && isa(BaseType)) + BaseType = cast(BaseType)->getNamedType(); if (!BaseType.isNull() && isa(BaseType) && cast(BaseType)->getDecl() == Decls[0]) { Decls.push_back(*D); @@ -337,12 +339,14 @@ void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { if (D->isModulePrivate()) Out << "__module_private__ "; } - D->getUnderlyingType().print(Out, Policy, D->getName()); + D->getTypeSourceInfo()->getType().print(Out, Policy, D->getName()); prettyPrintAttributes(D); } void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) { - Out << "using " << *D << " = " << D->getUnderlyingType().getAsString(Policy); + Out << "using " << *D; + prettyPrintAttributes(D); + Out << " = " << D->getTypeSourceInfo()->getType().getAsString(Policy); } void DeclPrinter::VisitEnumDecl(EnumDecl *D) { @@ -665,9 +669,9 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { Out << "__module_private__ "; } - QualType T = D->getASTContext().getUnqualifiedObjCPointerType(D->getType()); - if (ParmVarDecl *Parm = dyn_cast(D)) - T = Parm->getOriginalType(); + QualType T = D->getTypeSourceInfo() + ? D->getTypeSourceInfo()->getType() + : D->getASTContext().getUnqualifiedObjCPointerType(D->getType()); T.print(Out, Policy, D->getName()); Expr *Init = D->getInit(); if (!Policy.SuppressInitializers && Init) { @@ -1153,7 +1157,10 @@ void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { } void DeclPrinter::VisitUsingDecl(UsingDecl *D) { - Out << "using "; + if (!D->isAccessDeclaration()) + Out << "using "; + if (D->hasTypename()) + Out << "typename "; D->getQualifier()->print(Out, Policy); Out << *D; } @@ -1166,7 +1173,8 @@ DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { } void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { - Out << "using "; + if (!D->isAccessDeclaration()) + Out << "using "; D->getQualifier()->print(Out, Policy); Out << D->getName(); } @@ -1180,9 +1188,10 @@ void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { 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((*I)->getDecl()); + I != E; ++I) { + Out << (I == D->varlist_begin() ? '(' : ','); + NamedDecl *ND = cast(cast(*I)->getDecl()); + ND->printQualifiedName(Out); } Out << ")"; } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp index 0b94f7d..7172fb7 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp @@ -129,33 +129,34 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params, //===----------------------------------------------------------------------===// 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. - SmallVector PrevDecls; - for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev; - Prev = Prev->getPreviousDecl()) { - if (Prev->Common) { - Common = Prev->Common; - break; - } - - PrevDecls.push_back(Prev); + if (Common) + return Common; + + // Walk the previous-declaration chain until we either find a declaration + // with a common pointer or we run out of previous declarations. + SmallVector PrevDecls; + for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev; + Prev = Prev->getPreviousDecl()) { + if (Prev->Common) { + Common = Prev->Common; + break; } - // If we never found a common pointer, allocate one now. - if (!Common) { - // FIXME: If any of the declarations is from an AST file, we probably - // need an update record to add the common data. - - Common = newCommon(getASTContext()); - } - - // Update any previous declarations we saw with the common pointer. - for (unsigned I = 0, N = PrevDecls.size(); I != N; ++I) - PrevDecls[I]->Common = Common; + PrevDecls.push_back(Prev); + } + + // If we never found a common pointer, allocate one now. + if (!Common) { + // FIXME: If any of the declarations is from an AST file, we probably + // need an update record to add the common data. + + Common = newCommon(getASTContext()); } + // Update any previous declarations we saw with the common pointer. + for (unsigned I = 0, N = PrevDecls.size(); I != N; ++I) + PrevDecls[I]->Common = Common; + return Common; } @@ -245,6 +246,23 @@ FunctionTemplateDecl::newCommon(ASTContext &C) const { return CommonPtr; } +void FunctionTemplateDecl::LoadLazySpecializations() const { + Common *CommonPtr = getCommonPtr(); + if (CommonPtr->LazySpecializations) { + ASTContext &Context = getASTContext(); + uint32_t *Specs = CommonPtr->LazySpecializations; + CommonPtr->LazySpecializations = 0; + for (uint32_t I = 0, N = *Specs++; I != N; ++I) + (void)Context.getExternalSource()->GetExternalDecl(Specs[I]); + } +} + +llvm::FoldingSetVector & +FunctionTemplateDecl::getSpecializations() const { + LoadLazySpecializations(); + return getCommonPtr()->Specializations; +} + FunctionDecl * FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args, unsigned NumArgs, void *&InsertPos) { @@ -261,18 +279,17 @@ void FunctionTemplateDecl::addSpecialization( L->AddedCXXTemplateSpecialization(this, Info->Function); } -std::pair -FunctionTemplateDecl::getInjectedTemplateArgs() { +ArrayRef FunctionTemplateDecl::getInjectedTemplateArgs() { TemplateParameterList *Params = getTemplateParameters(); Common *CommonPtr = getCommonPtr(); if (!CommonPtr->InjectedArgs) { CommonPtr->InjectedArgs - = new (getASTContext()) TemplateArgument [Params->size()]; - GenerateInjectedTemplateArgs(getASTContext(), Params, + = new (getASTContext()) TemplateArgument[Params->size()]; + GenerateInjectedTemplateArgs(getASTContext(), Params, CommonPtr->InjectedArgs); } - - return std::make_pair(CommonPtr->InjectedArgs, Params->size()); + + return llvm::makeArrayRef(CommonPtr->InjectedArgs, Params->size()); } //===----------------------------------------------------------------------===// @@ -292,7 +309,7 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, ClassTemplateDecl *PrevDecl) { AdoptTemplateParameterList(Params, cast(Decl)); ClassTemplateDecl *New = new (C) ClassTemplateDecl(DC, L, Name, Params, Decl); - New->setPreviousDeclaration(PrevDecl); + New->setPreviousDecl(PrevDecl); return New; } @@ -381,13 +398,11 @@ void ClassTemplateDecl::getPartialSpecializations( llvm::FoldingSetVector &PartialSpecs = getPartialSpecializations(); PS.clear(); - PS.resize(PartialSpecs.size()); + PS.reserve(PartialSpecs.size()); for (llvm::FoldingSetVector::iterator P = PartialSpecs.begin(), PEnd = PartialSpecs.end(); - P != PEnd; ++P) { - assert(!PS[P->getSequenceNumber()]); - PS[P->getSequenceNumber()] = P->getMostRecentDecl(); - } + P != PEnd; ++P) + PS.push_back(P->getMostRecentDecl()); } ClassTemplatePartialSpecializationDecl * @@ -813,19 +828,16 @@ ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, unsigned NumArgs, - TemplateArgumentLoc *ArgInfos, - unsigned NumArgInfos, - ClassTemplatePartialSpecializationDecl *PrevDecl, - unsigned SequenceNumber) + const ASTTemplateArgumentListInfo *ArgInfos, + ClassTemplatePartialSpecializationDecl *PrevDecl) : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc, SpecializedTemplate, Args, NumArgs, PrevDecl), TemplateParams(Params), ArgsAsWritten(ArgInfos), - NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber), InstantiatedFromMember(0, false) -{ +{ AdoptTemplateParameterList(Params, this); } @@ -839,12 +851,9 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, unsigned NumArgs, const TemplateArgumentListInfo &ArgInfos, QualType CanonInjectedType, - ClassTemplatePartialSpecializationDecl *PrevDecl, - unsigned SequenceNumber) { - unsigned N = ArgInfos.size(); - TemplateArgumentLoc *ClonedArgs = new (Context) TemplateArgumentLoc[N]; - for (unsigned I = 0; I != N; ++I) - ClonedArgs[I] = ArgInfos[I]; + ClassTemplatePartialSpecializationDecl *PrevDecl) { + const ASTTemplateArgumentListInfo *ASTArgInfos = + ASTTemplateArgumentListInfo::Create(Context, ArgInfos); ClassTemplatePartialSpecializationDecl *Result = new (Context)ClassTemplatePartialSpecializationDecl(Context, TK, DC, @@ -852,9 +861,8 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, Params, SpecializedTemplate, Args, NumArgs, - ClonedArgs, N, - PrevDecl, - SequenceNumber); + ASTArgInfos, + PrevDecl); Result->setSpecializationKind(TSK_ExplicitSpecialization); Result->MayHaveOutOfDateDef = false; @@ -942,3 +950,252 @@ ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C, return new (Mem) ClassScopeFunctionSpecializationDecl(0, SourceLocation(), 0, false, TemplateArgumentListInfo()); } + +//===----------------------------------------------------------------------===// +// VarTemplateDecl Implementation +//===----------------------------------------------------------------------===// + +void VarTemplateDecl::DeallocateCommon(void *Ptr) { + static_cast(Ptr)->~Common(); +} + +VarTemplateDecl *VarTemplateDecl::getDefinition() { + VarTemplateDecl *CurD = this; + while (CurD) { + if (CurD->isThisDeclarationADefinition()) + return CurD; + CurD = CurD->getPreviousDecl(); + } + return 0; +} + +VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl, + VarTemplateDecl *PrevDecl) { + VarTemplateDecl *New = new (C) VarTemplateDecl(DC, L, Name, Params, Decl); + New->setPreviousDecl(PrevDecl); + return New; +} + +VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(VarTemplateDecl)); + return new (Mem) VarTemplateDecl(EmptyShell()); +} + +// TODO: Unify accross class, function and variable templates? +// May require moving this and Common to RedeclarableTemplateDecl. +void VarTemplateDecl::LoadLazySpecializations() const { + Common *CommonPtr = getCommonPtr(); + if (CommonPtr->LazySpecializations) { + ASTContext &Context = getASTContext(); + uint32_t *Specs = CommonPtr->LazySpecializations; + CommonPtr->LazySpecializations = 0; + for (uint32_t I = 0, N = *Specs++; I != N; ++I) + (void)Context.getExternalSource()->GetExternalDecl(Specs[I]); + } +} + +llvm::FoldingSetVector & +VarTemplateDecl::getSpecializations() const { + LoadLazySpecializations(); + return getCommonPtr()->Specializations; +} + +llvm::FoldingSetVector & +VarTemplateDecl::getPartialSpecializations() { + LoadLazySpecializations(); + return getCommonPtr()->PartialSpecializations; +} + +RedeclarableTemplateDecl::CommonBase * +VarTemplateDecl::newCommon(ASTContext &C) const { + Common *CommonPtr = new (C) Common; + C.AddDeallocation(DeallocateCommon, CommonPtr); + return CommonPtr; +} + +VarTemplateSpecializationDecl * +VarTemplateDecl::findSpecialization(const TemplateArgument *Args, + unsigned NumArgs, void *&InsertPos) { + return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos); +} + +void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D, + void *InsertPos) { + if (InsertPos) + getSpecializations().InsertNode(D, InsertPos); + else { + VarTemplateSpecializationDecl *Existing = + getSpecializations().GetOrInsertNode(D); + (void)Existing; + assert(Existing->isCanonicalDecl() && "Non-canonical specialization?"); + } + if (ASTMutationListener *L = getASTMutationListener()) + L->AddedCXXTemplateSpecialization(this, D); +} + +VarTemplatePartialSpecializationDecl * +VarTemplateDecl::findPartialSpecialization(const TemplateArgument *Args, + unsigned NumArgs, void *&InsertPos) { + return findSpecializationImpl(getPartialSpecializations(), Args, NumArgs, + InsertPos); +} + +void VarTemplateDecl::AddPartialSpecialization( + VarTemplatePartialSpecializationDecl *D, void *InsertPos) { + if (InsertPos) + getPartialSpecializations().InsertNode(D, InsertPos); + else { + VarTemplatePartialSpecializationDecl *Existing = + getPartialSpecializations().GetOrInsertNode(D); + (void)Existing; + assert(Existing->isCanonicalDecl() && "Non-canonical specialization?"); + } + + if (ASTMutationListener *L = getASTMutationListener()) + L->AddedCXXTemplateSpecialization(this, D); +} + +void VarTemplateDecl::getPartialSpecializations( + SmallVectorImpl &PS) { + llvm::FoldingSetVector &PartialSpecs = + getPartialSpecializations(); + PS.clear(); + PS.reserve(PartialSpecs.size()); + for (llvm::FoldingSetVector::iterator + P = PartialSpecs.begin(), + PEnd = PartialSpecs.end(); + P != PEnd; ++P) + PS.push_back(P->getMostRecentDecl()); +} + +VarTemplatePartialSpecializationDecl * +VarTemplateDecl::findPartialSpecInstantiatedFromMember( + VarTemplatePartialSpecializationDecl *D) { + Decl *DCanon = D->getCanonicalDecl(); + for (llvm::FoldingSetVector::iterator + P = getPartialSpecializations().begin(), + PEnd = getPartialSpecializations().end(); + P != PEnd; ++P) { + if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon) + return P->getMostRecentDecl(); + } + + return 0; +} + +//===----------------------------------------------------------------------===// +// VarTemplateSpecializationDecl Implementation +//===----------------------------------------------------------------------===// +VarTemplateSpecializationDecl::VarTemplateSpecializationDecl( + ASTContext &Context, Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T, + TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args, + unsigned NumArgs) + : VarDecl(DK, DC, StartLoc, IdLoc, SpecializedTemplate->getIdentifier(), T, + TInfo, S), + SpecializedTemplate(SpecializedTemplate), ExplicitInfo(0), + TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args, NumArgs)), + SpecializationKind(TSK_Undeclared) {} + +VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK) + : VarDecl(DK, 0, SourceLocation(), SourceLocation(), 0, QualType(), 0, + SC_None), + ExplicitInfo(0), SpecializationKind(TSK_Undeclared) {} + +VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create( + ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T, + TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args, + unsigned NumArgs) { + VarTemplateSpecializationDecl *Result = new (Context) + VarTemplateSpecializationDecl(Context, VarTemplateSpecialization, DC, + StartLoc, IdLoc, SpecializedTemplate, T, + TInfo, S, Args, NumArgs); + return Result; +} + +VarTemplateSpecializationDecl * +VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = + AllocateDeserializedDecl(C, ID, sizeof(VarTemplateSpecializationDecl)); + VarTemplateSpecializationDecl *Result = + new (Mem) VarTemplateSpecializationDecl(VarTemplateSpecialization); + return Result; +} + +void VarTemplateSpecializationDecl::getNameForDiagnostic( + raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const { + NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); + + const TemplateArgumentList &TemplateArgs = getTemplateArgs(); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, TemplateArgs.data(), TemplateArgs.size(), Policy); +} + +VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const { + if (SpecializedPartialSpecialization *PartialSpec = + SpecializedTemplate.dyn_cast()) + return PartialSpec->PartialSpecialization->getSpecializedTemplate(); + return SpecializedTemplate.get(); +} + +void VarTemplateSpecializationDecl::setTemplateArgsInfo( + const TemplateArgumentListInfo &ArgsInfo) { + unsigned N = ArgsInfo.size(); + TemplateArgsInfo.setLAngleLoc(ArgsInfo.getLAngleLoc()); + TemplateArgsInfo.setRAngleLoc(ArgsInfo.getRAngleLoc()); + for (unsigned I = 0; I != N; ++I) + TemplateArgsInfo.addArgument(ArgsInfo[I]); +} + +//===----------------------------------------------------------------------===// +// VarTemplatePartialSpecializationDecl Implementation +//===----------------------------------------------------------------------===// +void VarTemplatePartialSpecializationDecl::anchor() {} + +VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl( + ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, TemplateParameterList *Params, + VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, + StorageClass S, const TemplateArgument *Args, unsigned NumArgs, + const ASTTemplateArgumentListInfo *ArgInfos) + : VarTemplateSpecializationDecl(Context, VarTemplatePartialSpecialization, + DC, StartLoc, IdLoc, SpecializedTemplate, T, + TInfo, S, Args, NumArgs), + TemplateParams(Params), ArgsAsWritten(ArgInfos), + InstantiatedFromMember(0, false) { + // TODO: The template parameters should be in DC by now. Verify. + // AdoptTemplateParameterList(Params, DC); +} + +VarTemplatePartialSpecializationDecl * +VarTemplatePartialSpecializationDecl::Create( + ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, TemplateParameterList *Params, + VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, + StorageClass S, const TemplateArgument *Args, unsigned NumArgs, + const TemplateArgumentListInfo &ArgInfos) { + const ASTTemplateArgumentListInfo *ASTArgInfos + = ASTTemplateArgumentListInfo::Create(Context, ArgInfos); + + VarTemplatePartialSpecializationDecl *Result = + new (Context) VarTemplatePartialSpecializationDecl( + Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo, + S, Args, NumArgs, ASTArgInfos); + Result->setSpecializationKind(TSK_ExplicitSpecialization); + return Result; +} + +VarTemplatePartialSpecializationDecl * +VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl( + C, ID, sizeof(VarTemplatePartialSpecializationDecl)); + VarTemplatePartialSpecializationDecl *Result = + new (Mem) VarTemplatePartialSpecializationDecl(); + return Result; +} diff --git a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp index e4a41b6..e064e23 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp @@ -133,6 +133,66 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { llvm_unreachable("Invalid DeclarationName Kind!"); } +raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) { + switch (N.getNameKind()) { + case DeclarationName::Identifier: + if (const IdentifierInfo *II = N.getAsIdentifierInfo()) + OS << II->getName(); + return OS; + + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + return OS << N.getObjCSelector().getAsString(); + + case DeclarationName::CXXConstructorName: { + QualType ClassType = N.getCXXNameType(); + if (const RecordType *ClassRec = ClassType->getAs()) + return OS << *ClassRec->getDecl(); + return OS << ClassType.getAsString(); + } + + case DeclarationName::CXXDestructorName: { + OS << '~'; + QualType Type = N.getCXXNameType(); + if (const RecordType *Rec = Type->getAs()) + return OS << *Rec->getDecl(); + return OS << Type.getAsString(); + } + + case DeclarationName::CXXOperatorName: { + static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = { + 0, +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + Spelling, +#include "clang/Basic/OperatorKinds.def" + }; + const char *OpName = OperatorNames[N.getCXXOverloadedOperator()]; + assert(OpName && "not an overloaded operator"); + + OS << "operator"; + if (OpName[0] >= 'a' && OpName[0] <= 'z') + OS << ' '; + return OS << OpName; + } + + case DeclarationName::CXXLiteralOperatorName: + return OS << "operator \"\" " << N.getCXXLiteralIdentifier()->getName(); + + case DeclarationName::CXXConversionFunctionName: { + OS << "operator "; + QualType Type = N.getCXXNameType(); + if (const RecordType *Rec = Type->getAs()) + return OS << *Rec->getDecl(); + return OS << Type.getAsString(); + } + case DeclarationName::CXXUsingDirective: + return OS << ""; + } + + llvm_unreachable("Unexpected declaration name kind"); +} + } // end namespace clang DeclarationName::NameKind DeclarationName::getNameKind() const { @@ -180,80 +240,10 @@ bool DeclarationName::isDependentName() const { std::string DeclarationName::getAsString() const { std::string Result; llvm::raw_string_ostream OS(Result); - printName(OS); + OS << *this; return OS.str(); } -void DeclarationName::printName(raw_ostream &OS) const { - switch (getNameKind()) { - case Identifier: - if (const IdentifierInfo *II = getAsIdentifierInfo()) - OS << II->getName(); - return; - - case ObjCZeroArgSelector: - case ObjCOneArgSelector: - case ObjCMultiArgSelector: - OS << getObjCSelector().getAsString(); - return; - - case CXXConstructorName: { - QualType ClassType = getCXXNameType(); - if (const RecordType *ClassRec = ClassType->getAs()) - OS << *ClassRec->getDecl(); - else - OS << ClassType.getAsString(); - return; - } - - case CXXDestructorName: { - OS << '~'; - QualType Type = getCXXNameType(); - if (const RecordType *Rec = Type->getAs()) - OS << *Rec->getDecl(); - else - OS << Type.getAsString(); - return; - } - - case CXXOperatorName: { - static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = { - 0, -#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ - Spelling, -#include "clang/Basic/OperatorKinds.def" - }; - const char *OpName = OperatorNames[getCXXOverloadedOperator()]; - assert(OpName && "not an overloaded operator"); - - OS << "operator"; - if (OpName[0] >= 'a' && OpName[0] <= 'z') - OS << ' '; - OS << OpName; - return; - } - - case CXXLiteralOperatorName: - OS << "operator \"\" " << getCXXLiteralIdentifier()->getName(); - return; - - case CXXConversionFunctionName: { - OS << "operator "; - QualType Type = getCXXNameType(); - if (const RecordType *Rec = Type->getAs()) - OS << *Rec->getDecl(); - else - OS << Type.getAsString(); - return; - } - case CXXUsingDirective: - OS << ""; - return; - } - - llvm_unreachable("Unexpected declaration name kind"); -} - QualType DeclarationName::getCXXNameType() const { if (CXXSpecialName *CXXName = getAsCXXSpecialName()) return CXXName->Type; @@ -336,8 +326,7 @@ DeclarationName DeclarationName::getUsingDirectiveName() { } void DeclarationName::dump() const { - printName(llvm::errs()); - llvm::errs() << '\n'; + llvm::errs() << *this << '\n'; } DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) { @@ -537,7 +526,7 @@ void DeclarationNameInfo::printName(raw_ostream &OS) const { case DeclarationName::CXXOperatorName: case DeclarationName::CXXLiteralOperatorName: case DeclarationName::CXXUsingDirective: - Name.printName(OS); + OS << Name; return; case DeclarationName::CXXConstructorName: @@ -549,9 +538,8 @@ void DeclarationNameInfo::printName(raw_ostream &OS) const { else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) OS << "operator "; OS << TInfo->getType().getAsString(); - } - else - Name.printName(OS); + } else + OS << Name; return; } llvm_unreachable("Unexpected declaration name kind"); diff --git a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp deleted file mode 100644 index dc47c1c..0000000 --- a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp +++ /dev/null @@ -1,1055 +0,0 @@ -//===--- DumpXML.cpp - Detailed XML dumping -------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the Decl::dumpXML() method, a debugging tool to -// print a detailed graph of an AST in an unspecified XML format. -// -// There is no guarantee of stability for this format. -// -//===----------------------------------------------------------------------===// - -// 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" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" -#include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/Stmt.h" -#include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtObjC.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/TemplateName.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeLoc.h" -#include "clang/AST/TypeLocVisitor.h" -#include "clang/AST/TypeVisitor.h" -#include "llvm/ADT/SmallString.h" - -using namespace clang; - -#ifndef NDEBUG - -namespace { - -enum NodeState { - NS_Attrs, NS_LazyChildren, NS_Children -}; - -struct Node { - StringRef Name; - NodeState State; - Node(StringRef name) : Name(name), State(NS_Attrs) {} - - bool isDoneWithAttrs() const { return State != NS_Attrs; } -}; - -template struct XMLDeclVisitor { -#define DISPATCH(NAME, CLASS) \ - static_cast(this)->NAME(static_cast(D)) - - void dispatch(Decl *D) { - if (D->isUsed()) - static_cast(this)->set("used", "1"); - switch (D->getKind()) { -#define DECL(DERIVED, BASE) \ - case Decl::DERIVED: \ - DISPATCH(dispatch##DERIVED##DeclAttrs, DERIVED##Decl); \ - static_cast(this)->completeAttrs(); \ - DISPATCH(dispatch##DERIVED##DeclChildren, DERIVED##Decl); \ - DISPATCH(dispatch##DERIVED##DeclAsContext, DERIVED##Decl); \ - break; -#define ABSTRACT_DECL(DECL) -#include "clang/AST/DeclNodes.inc" - } - } - -#define DECL(DERIVED, BASE) \ - void dispatch##DERIVED##DeclAttrs(DERIVED##Decl *D) { \ - DISPATCH(dispatch##BASE##Attrs, BASE); \ - DISPATCH(visit##DERIVED##DeclAttrs, DERIVED##Decl); \ - } \ - void visit##DERIVED##DeclAttrs(DERIVED##Decl *D) {} \ - void dispatch##DERIVED##DeclChildren(DERIVED##Decl *D) { \ - DISPATCH(dispatch##BASE##Children, BASE); \ - DISPATCH(visit##DERIVED##DeclChildren, DERIVED##Decl); \ - } \ - void visit##DERIVED##DeclChildren(DERIVED##Decl *D) {} \ - void dispatch##DERIVED##DeclAsContext(DERIVED##Decl *D) { \ - DISPATCH(dispatch##BASE##AsContext, BASE); \ - DISPATCH(visit##DERIVED##DeclAsContext, DERIVED##Decl); \ - } \ - void visit##DERIVED##DeclAsContext(DERIVED##Decl *D) {} -#include "clang/AST/DeclNodes.inc" - - void dispatchDeclAttrs(Decl *D) { - DISPATCH(visitDeclAttrs, Decl); - } - void visitDeclAttrs(Decl *D) {} - - void dispatchDeclChildren(Decl *D) { - DISPATCH(visitDeclChildren, Decl); - } - void visitDeclChildren(Decl *D) {} - - void dispatchDeclAsContext(Decl *D) { - DISPATCH(visitDeclAsContext, Decl); - } - void visitDeclAsContext(Decl *D) {} - -#undef DISPATCH -}; - -template struct XMLTypeVisitor { -#define DISPATCH(NAME, CLASS) \ - static_cast(this)->NAME(static_cast(T)) - - void dispatch(Type *T) { - switch (T->getTypeClass()) { -#define TYPE(DERIVED, BASE) \ - case Type::DERIVED: \ - DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \ - static_cast(this)->completeAttrs(); \ - DISPATCH(dispatch##DERIVED##TypeChildren, DERIVED##Type); \ - break; -#define ABSTRACT_TYPE(DERIVED, BASE) -#include "clang/AST/TypeNodes.def" - } - } - -#define TYPE(DERIVED, BASE) \ - void dispatch##DERIVED##TypeAttrs(DERIVED##Type *T) { \ - DISPATCH(dispatch##BASE##Attrs, BASE); \ - DISPATCH(visit##DERIVED##TypeAttrs, DERIVED##Type); \ - } \ - void visit##DERIVED##TypeAttrs(DERIVED##Type *T) {} \ - void dispatch##DERIVED##TypeChildren(DERIVED##Type *T) { \ - DISPATCH(dispatch##BASE##Children, BASE); \ - DISPATCH(visit##DERIVED##TypeChildren, DERIVED##Type); \ - } \ - void visit##DERIVED##TypeChildren(DERIVED##Type *T) {} -#include "clang/AST/TypeNodes.def" - - void dispatchTypeAttrs(Type *T) { - DISPATCH(visitTypeAttrs, Type); - } - void visitTypeAttrs(Type *T) {} - - void dispatchTypeChildren(Type *T) { - DISPATCH(visitTypeChildren, Type); - } - void visitTypeChildren(Type *T) {} - -#undef DISPATCH -}; - -static StringRef getTypeKindName(Type *T) { - switch (T->getTypeClass()) { -#define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type"; -#define ABSTRACT_TYPE(DERIVED, BASE) -#include "clang/AST/TypeNodes.def" - } - - llvm_unreachable("unknown type kind!"); -} - -struct XMLDumper : public XMLDeclVisitor, - public XMLTypeVisitor { - raw_ostream &out; - ASTContext &Context; - SmallVector Stack; - unsigned Indent; - explicit XMLDumper(raw_ostream &OS, ASTContext &context) - : out(OS), Context(context), Indent(0) {} - - void indent() { - for (unsigned I = Indent; I; --I) - out << ' '; - } - - /// Push a new node on the stack. - void push(StringRef name) { - if (!Stack.empty()) { - assert(Stack.back().isDoneWithAttrs()); - if (Stack.back().State == NS_LazyChildren) { - Stack.back().State = NS_Children; - out << ">\n"; - } - Indent++; - indent(); - } - Stack.push_back(Node(name)); - out << '<' << name; - } - - /// Set the given attribute to the given value. - void set(StringRef attr, StringRef value) { - assert(!Stack.empty() && !Stack.back().isDoneWithAttrs()); - out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation - } - - /// Finish attributes. - void completeAttrs() { - assert(!Stack.empty() && !Stack.back().isDoneWithAttrs()); - Stack.back().State = NS_LazyChildren; - } - - /// Pop a node. - void pop() { - assert(!Stack.empty() && Stack.back().isDoneWithAttrs()); - if (Stack.back().State == NS_LazyChildren) { - out << "/>\n"; - } else { - indent(); - out << "\n"; - } - if (Stack.size() > 1) Indent--; - Stack.pop_back(); - } - - //---- General utilities -------------------------------------------// - - void setPointer(StringRef prop, const void *p) { - SmallString<10> buffer; - llvm::raw_svector_ostream os(buffer); - os << p; - os.flush(); - set(prop, buffer); - } - - void setPointer(void *p) { - setPointer("ptr", p); - } - - void setInteger(StringRef prop, const llvm::APSInt &v) { - set(prop, v.toString(10)); - } - - void setInteger(StringRef prop, unsigned n) { - SmallString<10> buffer; - llvm::raw_svector_ostream os(buffer); - os << n; - os.flush(); - set(prop, buffer); - } - - void setFlag(StringRef prop, bool flag) { - if (flag) set(prop, "true"); - } - - void setName(DeclarationName Name) { - if (!Name) - return set("name", ""); - - // Common case. - if (Name.isIdentifier()) - return set("name", Name.getAsIdentifierInfo()->getName()); - - set("name", Name.getAsString()); - } - - class TemporaryContainer { - XMLDumper &Dumper; - public: - TemporaryContainer(XMLDumper &dumper, StringRef name) - : Dumper(dumper) { - Dumper.push(name); - Dumper.completeAttrs(); - } - - ~TemporaryContainer() { - Dumper.pop(); - } - }; - - void visitTemplateParameters(TemplateParameterList *L) { - push("template_parameters"); - completeAttrs(); - for (TemplateParameterList::iterator - I = L->begin(), E = L->end(); I != E; ++I) - dispatch(*I); - pop(); - } - - void visitTemplateArguments(const TemplateArgumentList &L) { - push("template_arguments"); - completeAttrs(); - for (unsigned I = 0, E = L.size(); I != E; ++I) - dispatch(L[I]); - pop(); - } - - /// Visits a reference to the given declaration. - void visitDeclRef(Decl *D) { - push(D->getDeclKindName()); - setPointer("ref", D); - completeAttrs(); - pop(); - } - void visitDeclRef(StringRef Name, Decl *D) { - TemporaryContainer C(*this, Name); - if (D) visitDeclRef(D); - } - - void dispatch(const TemplateArgument &A) { - switch (A.getKind()) { - case TemplateArgument::Null: { - TemporaryContainer C(*this, "null"); - break; - } - case TemplateArgument::Type: { - dispatch(A.getAsType()); - break; - } - case TemplateArgument::Template: - case TemplateArgument::TemplateExpansion: - case TemplateArgument::NullPtr: - // FIXME: Implement! - break; - - case TemplateArgument::Declaration: { - visitDeclRef(A.getAsDecl()); - break; - } - case TemplateArgument::Integral: { - push("integer"); - setInteger("value", A.getAsIntegral()); - completeAttrs(); - pop(); - break; - } - case TemplateArgument::Expression: { - dispatch(A.getAsExpr()); - break; - } - case TemplateArgument::Pack: { - for (TemplateArgument::pack_iterator P = A.pack_begin(), - PEnd = A.pack_end(); - P != PEnd; ++P) - dispatch(*P); - break; - } - } - } - - void dispatch(const TemplateArgumentLoc &A) { - dispatch(A.getArgument()); - } - - //---- Declarations ------------------------------------------------// - // Calls are made in this order: - // # Enter a new node. - // push("FieldDecl") - // - // # In this phase, attributes are set on the node. - // visitDeclAttrs(D) - // visitNamedDeclAttrs(D) - // ... - // visitFieldDeclAttrs(D) - // - // # No more attributes after this point. - // completeAttrs() - // - // # Create "header" child nodes, i.e. those which logically - // # belong to the declaration itself. - // visitDeclChildren(D) - // visitNamedDeclChildren(D) - // ... - // visitFieldDeclChildren(D) - // - // # Create nodes for the lexical children. - // visitDeclAsContext(D) - // visitNamedDeclAsContext(D) - // ... - // visitFieldDeclAsContext(D) - // - // # Finish the node. - // pop(); - void dispatch(Decl *D) { - push(D->getDeclKindName()); - XMLDeclVisitor::dispatch(D); - pop(); - } - void visitDeclAttrs(Decl *D) { - setPointer(D); - } - - /// Visit all the lexical decls in the given context. - void visitDeclContext(DeclContext *DC) { - for (DeclContext::decl_iterator - I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) - dispatch(*I); - - // FIXME: point out visible declarations not in lexical context? - } - - /// Set the "access" attribute on the current node according to the - /// given specifier. - void setAccess(AccessSpecifier AS) { - switch (AS) { - case AS_public: return set("access", "public"); - case AS_protected: return set("access", "protected"); - case AS_private: return set("access", "private"); - case AS_none: llvm_unreachable("explicit forbidden access"); - } - } - - template void visitRedeclarableAttrs(T *D) { - if (T *Prev = D->getPreviousDecl()) - setPointer("previous", Prev); - } - - - // TranslationUnitDecl - void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) { - visitDeclContext(D); - } - - // LinkageSpecDecl - void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) { - StringRef lang = ""; - switch (D->getLanguage()) { - case LinkageSpecDecl::lang_c: lang = "C"; break; - case LinkageSpecDecl::lang_cxx: lang = "C++"; break; - } - set("lang", lang); - } - void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) { - visitDeclContext(D); - } - - // NamespaceDecl - void visitNamespaceDeclAttrs(NamespaceDecl *D) { - setFlag("inline", D->isInline()); - if (!D->isOriginalNamespace()) - setPointer("original", D->getOriginalNamespace()); - } - void visitNamespaceDeclAsContext(NamespaceDecl *D) { - visitDeclContext(D); - } - - // NamedDecl - void visitNamedDeclAttrs(NamedDecl *D) { - setName(D->getDeclName()); - } - - // ValueDecl - void visitValueDeclChildren(ValueDecl *D) { - dispatch(D->getType()); - } - - // DeclaratorDecl - void visitDeclaratorDeclChildren(DeclaratorDecl *D) { - //dispatch(D->getTypeSourceInfo()->getTypeLoc()); - } - - // VarDecl - void visitVarDeclAttrs(VarDecl *D) { - visitRedeclarableAttrs(D); - if (D->getStorageClass() != SC_None) - set("storage", - VarDecl::getStorageClassSpecifierString(D->getStorageClass())); - StringRef initStyle = ""; - switch (D->getInitStyle()) { - case VarDecl::CInit: initStyle = "c"; break; - case VarDecl::CallInit: initStyle = "call"; break; - case VarDecl::ListInit: initStyle = "list"; break; - } - set("initstyle", initStyle); - setFlag("nrvo", D->isNRVOVariable()); - // TODO: instantiation, etc. - } - void visitVarDeclChildren(VarDecl *D) { - if (D->hasInit()) dispatch(D->getInit()); - } - - // ParmVarDecl? - - // FunctionDecl - void visitFunctionDeclAttrs(FunctionDecl *D) { - visitRedeclarableAttrs(D); - setFlag("pure", D->isPure()); - setFlag("trivial", D->isTrivial()); - setFlag("returnzero", D->hasImplicitReturnZero()); - setFlag("prototype", D->hasWrittenPrototype()); - setFlag("deleted", D->isDeletedAsWritten()); - if (D->getStorageClass() != SC_None) - set("storage", - VarDecl::getStorageClassSpecifierString(D->getStorageClass())); - setFlag("inline", D->isInlineSpecified()); - if (const AsmLabelAttr *ALA = D->getAttr()) - set("asmlabel", ALA->getLabel()); - // TODO: instantiation, etc. - } - void visitFunctionDeclChildren(FunctionDecl *D) { - for (FunctionDecl::param_iterator - I = D->param_begin(), E = D->param_end(); I != E; ++I) - dispatch(*I); - for (ArrayRef::iterator I = D->getDeclsInPrototypeScope().begin(), - E = D->getDeclsInPrototypeScope().end(); - I != E; ++I) - dispatch(*I); - if (D->doesThisDeclarationHaveABody()) - dispatch(D->getBody()); - } - - // CXXMethodDecl ? - // CXXConstructorDecl ? - // CXXDestructorDecl ? - // CXXConversionDecl ? - - void dispatch(CXXCtorInitializer *Init) { - // TODO - } - - // FieldDecl - void visitFieldDeclAttrs(FieldDecl *D) { - setFlag("mutable", D->isMutable()); - } - void visitFieldDeclChildren(FieldDecl *D) { - if (D->isBitField()) { - TemporaryContainer C(*this, "bitwidth"); - dispatch(D->getBitWidth()); - } - // TODO: C++0x member initializer - } - - // EnumConstantDecl - void visitEnumConstantDeclChildren(EnumConstantDecl *D) { - // value in any case? - if (D->getInitExpr()) dispatch(D->getInitExpr()); - } - - // IndirectFieldDecl - void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) { - for (IndirectFieldDecl::chain_iterator - I = D->chain_begin(), E = D->chain_end(); I != E; ++I) { - NamedDecl *VD = const_cast(*I); - push(isa(VD) ? "variable" : "field"); - setPointer("ptr", VD); - completeAttrs(); - pop(); - } - } - - // TypeDecl - void visitTypeDeclAttrs(TypeDecl *D) { - setPointer("typeptr", D->getTypeForDecl()); - } - - // TypedefDecl - void visitTypedefDeclAttrs(TypedefDecl *D) { - visitRedeclarableAttrs(D); - } - void visitTypedefDeclChildren(TypedefDecl *D) { - dispatch(D->getTypeSourceInfo()->getTypeLoc()); - } - - // TypeAliasDecl - void visitTypeAliasDeclAttrs(TypeAliasDecl *D) { - visitRedeclarableAttrs(D); - } - void visitTypeAliasDeclChildren(TypeAliasDecl *D) { - dispatch(D->getTypeSourceInfo()->getTypeLoc()); - } - - // TagDecl - void visitTagDeclAttrs(TagDecl *D) { - visitRedeclarableAttrs(D); - } - void visitTagDeclAsContext(TagDecl *D) { - visitDeclContext(D); - } - - // EnumDecl - void visitEnumDeclAttrs(EnumDecl *D) { - setFlag("scoped", D->isScoped()); - setFlag("fixed", D->isFixed()); - } - void visitEnumDeclChildren(EnumDecl *D) { - { - TemporaryContainer C(*this, "promotion_type"); - dispatch(D->getPromotionType()); - } - { - TemporaryContainer C(*this, "integer_type"); - dispatch(D->getIntegerType()); - } - } - - // RecordDecl ? - - void visitCXXRecordDeclChildren(CXXRecordDecl *D) { - if (!D->isThisDeclarationADefinition()) return; - - for (CXXRecordDecl::base_class_iterator - I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { - push("base"); - setAccess(I->getAccessSpecifier()); - completeAttrs(); - dispatch(I->getTypeSourceInfo()->getTypeLoc()); - pop(); - } - } - - // ClassTemplateSpecializationDecl ? - - // FileScopeAsmDecl ? - - // BlockDecl - void visitBlockDeclAttrs(BlockDecl *D) { - setFlag("variadic", D->isVariadic()); - } - void visitBlockDeclChildren(BlockDecl *D) { - for (FunctionDecl::param_iterator - I = D->param_begin(), E = D->param_end(); I != E; ++I) - dispatch(*I); - dispatch(D->getBody()); - } - - // AccessSpecDecl - void visitAccessSpecDeclAttrs(AccessSpecDecl *D) { - setAccess(D->getAccess()); - } - - // TemplateDecl - void visitTemplateDeclChildren(TemplateDecl *D) { - visitTemplateParameters(D->getTemplateParameters()); - if (D->getTemplatedDecl()) - dispatch(D->getTemplatedDecl()); - } - - // FunctionTemplateDecl - void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) { - visitRedeclarableAttrs(D); - } - void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) { - // Mention all the specializations which don't have explicit - // declarations elsewhere. - for (FunctionTemplateDecl::spec_iterator - I = D->spec_begin(), E = D->spec_end(); I != E; ++I) { - FunctionTemplateSpecializationInfo *Info - = I->getTemplateSpecializationInfo(); - - bool Unknown = false; - switch (Info->getTemplateSpecializationKind()) { - case TSK_ImplicitInstantiation: Unknown = false; break; - case TSK_Undeclared: Unknown = true; break; - - // These will be covered at their respective sites. - case TSK_ExplicitSpecialization: continue; - case TSK_ExplicitInstantiationDeclaration: continue; - case TSK_ExplicitInstantiationDefinition: continue; - } - - TemporaryContainer C(*this, - Unknown ? "uninstantiated" : "instantiation"); - visitTemplateArguments(*Info->TemplateArguments); - dispatch(Info->Function); - } - } - - // ClasTemplateDecl - void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) { - visitRedeclarableAttrs(D); - } - void visitClassTemplateDeclChildren(ClassTemplateDecl *D) { - // Mention all the specializations which don't have explicit - // declarations elsewhere. - for (ClassTemplateDecl::spec_iterator - I = D->spec_begin(), E = D->spec_end(); I != E; ++I) { - - bool Unknown = false; - switch (I->getTemplateSpecializationKind()) { - case TSK_ImplicitInstantiation: Unknown = false; break; - case TSK_Undeclared: Unknown = true; break; - - // These will be covered at their respective sites. - case TSK_ExplicitSpecialization: continue; - case TSK_ExplicitInstantiationDeclaration: continue; - case TSK_ExplicitInstantiationDefinition: continue; - } - - TemporaryContainer C(*this, - Unknown ? "uninstantiated" : "instantiation"); - visitTemplateArguments(I->getTemplateArgs()); - dispatch(*I); - } - } - - // TemplateTypeParmDecl - void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) { - setInteger("depth", D->getDepth()); - setInteger("index", D->getIndex()); - } - void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) { - if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) - dispatch(D->getDefaultArgumentInfo()->getTypeLoc()); - // parameter pack? - } - - // NonTypeTemplateParmDecl - void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) { - setInteger("depth", D->getDepth()); - setInteger("index", D->getIndex()); - } - void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) { - if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) - dispatch(D->getDefaultArgument()); - // parameter pack? - } - - // TemplateTemplateParmDecl - void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) { - setInteger("depth", D->getDepth()); - setInteger("index", D->getIndex()); - } - void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) { - if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) - dispatch(D->getDefaultArgument()); - // parameter pack? - } - - // FriendDecl - void visitFriendDeclChildren(FriendDecl *D) { - if (TypeSourceInfo *T = D->getFriendType()) - dispatch(T->getTypeLoc()); - else - dispatch(D->getFriendDecl()); - } - - // UsingDirectiveDecl ? - // UsingDecl ? - // UsingShadowDecl ? - // NamespaceAliasDecl ? - // UnresolvedUsingValueDecl ? - // UnresolvedUsingTypenameDecl ? - // StaticAssertDecl ? - - // ObjCImplDecl - void visitObjCImplDeclChildren(ObjCImplDecl *D) { - visitDeclRef(D->getClassInterface()); - } - void visitObjCImplDeclAsContext(ObjCImplDecl *D) { - visitDeclContext(D); - } - - void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) { - setPointer("typeptr", D->getTypeForDecl()); - setFlag("forward_decl", !D->isThisDeclarationADefinition()); - setFlag("implicit_interface", D->isImplicitInterfaceDecl()); - } - void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) { - visitDeclRef("super", D->getSuperClass()); - visitDeclRef("implementation", D->getImplementation()); - if (D->protocol_begin() != D->protocol_end()) { - TemporaryContainer C(*this, "protocols"); - for (ObjCInterfaceDecl::protocol_iterator - I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) - visitDeclRef(*I); - } - - 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); - } - - // ObjCCategoryDecl - void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) { - setFlag("extension", D->IsClassExtension()); - } - void visitObjCCategoryDeclChildren(ObjCCategoryDecl *D) { - visitDeclRef("interface", D->getClassInterface()); - visitDeclRef("implementation", D->getImplementation()); - if (D->protocol_begin() != D->protocol_end()) { - TemporaryContainer C(*this, "protocols"); - for (ObjCCategoryDecl::protocol_iterator - I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) - visitDeclRef(*I); - } - } - void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) { - visitDeclContext(D); - } - - // ObjCCategoryImplDecl - void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) { - set("identifier", D->getName()); - } - void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) { - visitDeclRef(D->getCategoryDecl()); - } - - // ObjCImplementationDecl - void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) { - set("identifier", D->getName()); - } - void visitObjCImplementationDeclChildren(ObjCImplementationDecl *D) { - visitDeclRef("super", D->getSuperClass()); - if (D->init_begin() != D->init_end()) { - TemporaryContainer C(*this, "initializers"); - for (ObjCImplementationDecl::init_iterator - I = D->init_begin(), E = D->init_end(); I != E; ++I) - dispatch(*I); - } - } - - // ObjCProtocolDecl - void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) { - if (!D->isThisDeclarationADefinition()) - return; - - if (D->protocol_begin() != D->protocol_end()) { - TemporaryContainer C(*this, "protocols"); - for (ObjCInterfaceDecl::protocol_iterator - I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) - visitDeclRef(*I); - } - } - void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) { - if (!D->isThisDeclarationADefinition()) - return; - - visitDeclContext(D); - } - - // ObjCMethodDecl - void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) { - // decl qualifier? - // implementation control? - - setFlag("instance", D->isInstanceMethod()); - setFlag("variadic", D->isVariadic()); - setFlag("property_accessor", D->isPropertyAccessor()); - setFlag("defined", D->isDefined()); - setFlag("related_result_type", D->hasRelatedResultType()); - } - void visitObjCMethodDeclChildren(ObjCMethodDecl *D) { - dispatch(D->getResultType()); - for (ObjCMethodDecl::param_iterator - I = D->param_begin(), E = D->param_end(); I != E; ++I) - dispatch(*I); - if (D->isThisDeclarationADefinition()) - dispatch(D->getBody()); - } - - // ObjCIvarDecl - void setAccessControl(StringRef prop, ObjCIvarDecl::AccessControl AC) { - switch (AC) { - case ObjCIvarDecl::None: return set(prop, "none"); - case ObjCIvarDecl::Private: return set(prop, "private"); - case ObjCIvarDecl::Protected: return set(prop, "protected"); - case ObjCIvarDecl::Public: return set(prop, "public"); - case ObjCIvarDecl::Package: return set(prop, "package"); - } - } - void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) { - setFlag("synthesize", D->getSynthesize()); - setAccessControl("access", D->getAccessControl()); - } - - // ObjCCompatibleAliasDecl - void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) { - visitDeclRef(D->getClassInterface()); - } - - // FIXME: ObjCPropertyDecl - // FIXME: ObjCPropertyImplDecl - - //---- Types -----------------------------------------------------// - void dispatch(TypeLoc TL) { - dispatch(TL.getType()); // for now - } - - void dispatch(QualType T) { - if (T.hasLocalQualifiers()) { - push("QualType"); - Qualifiers Qs = T.getLocalQualifiers(); - setFlag("const", Qs.hasConst()); - setFlag("volatile", Qs.hasVolatile()); - setFlag("restrict", Qs.hasRestrict()); - if (Qs.hasAddressSpace()) setInteger("addrspace", Qs.getAddressSpace()); - if (Qs.hasObjCGCAttr()) { - switch (Qs.getObjCGCAttr()) { - case Qualifiers::Weak: set("gc", "weak"); break; - case Qualifiers::Strong: set("gc", "strong"); break; - case Qualifiers::GCNone: llvm_unreachable("explicit none"); - } - } - - completeAttrs(); - dispatch(QualType(T.getTypePtr(), 0)); - pop(); - return; - } - - Type *Ty = const_cast(T.getTypePtr()); - push(getTypeKindName(Ty)); - XMLTypeVisitor::dispatch(const_cast(T.getTypePtr())); - pop(); - } - - void setCallingConv(CallingConv CC) { - switch (CC) { - case CC_Default: return; - case CC_C: return set("cc", "cdecl"); - case CC_X86FastCall: return set("cc", "x86_fastcall"); - case CC_X86StdCall: return set("cc", "x86_stdcall"); - case CC_X86ThisCall: return set("cc", "x86_thiscall"); - case CC_X86Pascal: return set("cc", "x86_pascal"); - case CC_X86_64Win64: return set("cc", "x86_64_win64"); - case CC_X86_64SysV: return set("cc", "x86_64_sysv"); - 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"); - } - } - - void visitTypeAttrs(Type *D) { - setPointer(D); - setFlag("dependent", D->isDependentType()); - setFlag("variably_modified", D->isVariablyModifiedType()); - - setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr()); - } - - void visitPointerTypeChildren(PointerType *T) { - dispatch(T->getPointeeType()); - } - void visitReferenceTypeChildren(ReferenceType *T) { - dispatch(T->getPointeeType()); - } - void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) { - dispatch(T->getPointeeType()); - } - void visitBlockPointerTypeChildren(BlockPointerType *T) { - dispatch(T->getPointeeType()); - } - - // Types that just wrap declarations. - void visitTagTypeChildren(TagType *T) { - visitDeclRef(T->getDecl()); - } - void visitTypedefTypeChildren(TypedefType *T) { - visitDeclRef(T->getDecl()); - } - void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) { - visitDeclRef(T->getDecl()); - } - void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) { - visitDeclRef(T->getDecl()); - } - void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) { - visitDeclRef(T->getDecl()); - } - - void visitFunctionTypeAttrs(FunctionType *T) { - setFlag("noreturn", T->getNoReturnAttr()); - setCallingConv(T->getCallConv()); - if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType()); - } - void visitFunctionTypeChildren(FunctionType *T) { - dispatch(T->getResultType()); - } - - void visitFunctionProtoTypeAttrs(FunctionProtoType *T) { - setFlag("const", T->isConst()); - setFlag("volatile", T->isVolatile()); - setFlag("restrict", T->isRestrict()); - switch (T->getExceptionSpecType()) { - case EST_None: break; - case EST_DynamicNone: set("exception_spec", "throw()"); break; - case EST_Dynamic: set("exception_spec", "throw(T)"); break; - case EST_MSAny: set("exception_spec", "throw(...)"); break; - case EST_BasicNoexcept: set("exception_spec", "noexcept"); break; - case EST_ComputedNoexcept: set("exception_spec", "noexcept(expr)"); break; - case EST_Unevaluated: set("exception_spec", "unevaluated"); break; - case EST_Uninstantiated: set("exception_spec", "uninstantiated"); break; - } - } - void visitFunctionProtoTypeChildren(FunctionProtoType *T) { - push("parameters"); - setFlag("variadic", T->isVariadic()); - completeAttrs(); - for (FunctionProtoType::arg_type_iterator - I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I) - dispatch(*I); - pop(); - - if (T->hasDynamicExceptionSpec()) { - push("exception_specifiers"); - setFlag("any", T->getExceptionSpecType() == EST_MSAny); - completeAttrs(); - for (FunctionProtoType::exception_iterator - I = T->exception_begin(), E = T->exception_end(); I != E; ++I) - dispatch(*I); - pop(); - } - // FIXME: noexcept specifier - } - - void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) { - if (const RecordType *RT = T->getAs()) - visitDeclRef(RT->getDecl()); - - // TODO: TemplateName - - push("template_arguments"); - completeAttrs(); - for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I) - dispatch(T->getArg(I)); - pop(); - } - - //---- Statements ------------------------------------------------// - void dispatch(Stmt *S) { - // FIXME: this is not really XML at all - push("Stmt"); - out << ">\n"; - Stack.back().State = NS_Children; // explicitly become non-lazy - S->dump(out, Context.getSourceManager()); - out << '\n'; - pop(); - } -}; -} - -void Decl::dumpXML() const { - dumpXML(llvm::errs()); -} - -void Decl::dumpXML(raw_ostream &out) const { - XMLDumper(out, getASTContext()).dispatch(const_cast(this)); -} - -#else /* ifndef NDEBUG */ - -void Decl::dumpXML() const {} -void Decl::dumpXML(raw_ostream &out) const {} - -#endif diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index 9538ddf..9055ddac 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -20,6 +20,7 @@ #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/Builtins.h" @@ -50,9 +51,9 @@ const CXXRecordDecl *Expr::getBestDynamicClassType() const { return cast(D); } -const Expr * -Expr::skipRValueSubobjectAdjustments( - SmallVectorImpl &Adjustments) const { +const Expr *Expr::skipRValueSubobjectAdjustments( + SmallVectorImpl &CommaLHSs, + SmallVectorImpl &Adjustments) const { const Expr *E = this; while (true) { E = E->IgnoreParens(); @@ -73,12 +74,14 @@ Expr::skipRValueSubobjectAdjustments( continue; } } else if (const MemberExpr *ME = dyn_cast(E)) { - if (!ME->isArrow() && ME->getBase()->isRValue()) { + if (!ME->isArrow()) { assert(ME->getBase()->getType()->isRecordType()); if (FieldDecl *Field = dyn_cast(ME->getMemberDecl())) { - E = ME->getBase(); - Adjustments.push_back(SubobjectAdjustment(Field)); - continue; + if (!Field->isBitField() && !Field->getType()->isReferenceType()) { + E = ME->getBase(); + Adjustments.push_back(SubobjectAdjustment(Field)); + continue; + } } } } else if (const BinaryOperator *BO = dyn_cast(E)) { @@ -88,6 +91,11 @@ Expr::skipRValueSubobjectAdjustments( const MemberPointerType *MPT = BO->getRHS()->getType()->getAs(); Adjustments.push_back(SubobjectAdjustment(MPT, BO->getRHS())); + continue; + } else if (BO->getOpcode() == BO_Comma) { + CommaLHSs.push_back(BO->getLHS()); + E = BO->getRHS(); + continue; } } @@ -231,8 +239,8 @@ SourceLocation Expr::getExprLoc() const { /// \brief Compute the type-, value-, and instantiation-dependence of a /// declaration reference /// based on the declaration being referenced. -static void computeDeclRefDependence(ASTContext &Ctx, NamedDecl *D, QualType T, - bool &TypeDependent, +static void computeDeclRefDependence(const ASTContext &Ctx, NamedDecl *D, + QualType T, bool &TypeDependent, bool &ValueDependent, bool &InstantiationDependent) { TypeDependent = false; @@ -307,6 +315,9 @@ static void computeDeclRefDependence(ASTContext &Ctx, NamedDecl *D, QualType T, Var->getDeclContext()->isDependentContext()) { ValueDependent = true; InstantiationDependent = true; + TypeSourceInfo *TInfo = Var->getFirstDecl()->getTypeSourceInfo(); + if (TInfo->getType()->isIncompleteArrayType()) + TypeDependent = true; } return; @@ -321,7 +332,7 @@ static void computeDeclRefDependence(ASTContext &Ctx, NamedDecl *D, QualType T, } } -void DeclRefExpr::computeDependence(ASTContext &Ctx) { +void DeclRefExpr::computeDependence(const ASTContext &Ctx) { bool TypeDependent = false; bool ValueDependent = false; bool InstantiationDependent = false; @@ -355,7 +366,7 @@ void DeclRefExpr::computeDependence(ASTContext &Ctx) { ExprBits.ContainsUnexpandedParameterPack = true; } -DeclRefExpr::DeclRefExpr(ASTContext &Ctx, +DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingLocal, @@ -392,7 +403,7 @@ DeclRefExpr::DeclRefExpr(ASTContext &Ctx, computeDependence(Ctx); } -DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, +DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, @@ -408,7 +419,7 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, T, VK, FoundD, TemplateArgs); } -DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, +DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, @@ -423,7 +434,7 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, FoundD = 0; std::size_t Size = sizeof(DeclRefExpr); - if (QualifierLoc != 0) + if (QualifierLoc) Size += sizeof(NestedNameSpecifierLoc); if (FoundD) Size += sizeof(NamedDecl *); @@ -438,7 +449,7 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, NameInfo, FoundD, TemplateArgs, T, VK); } -DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, +DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context, bool HasQualifier, bool HasFoundDecl, bool HasTemplateKWAndArgsInfo, @@ -471,6 +482,30 @@ SourceLocation DeclRefExpr::getLocEnd() const { std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { ASTContext &Context = CurrentDecl->getASTContext(); + if (IT == PredefinedExpr::FuncDName) { + if (const NamedDecl *ND = dyn_cast(CurrentDecl)) { + OwningPtr MC; + MC.reset(Context.createMangleContext()); + + if (MC->shouldMangleDeclName(ND)) { + SmallString<256> Buffer; + llvm::raw_svector_ostream Out(Buffer); + if (const CXXConstructorDecl *CD = dyn_cast(ND)) + MC->mangleCXXCtor(CD, Ctor_Base, Out); + else if (const CXXDestructorDecl *DD = dyn_cast(ND)) + MC->mangleCXXDtor(DD, Dtor_Base, Out); + else + MC->mangleName(ND, Out); + + Out.flush(); + if (!Buffer.empty() && Buffer.front() == '\01') + return Buffer.substr(1); + return Buffer.str(); + } else + return ND->getIdentifier()->getName(); + } + return ""; + } if (const FunctionDecl *FD = dyn_cast(CurrentDecl)) { if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual) return FD->getNameAsString(); @@ -578,7 +613,18 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { POut.flush(); - if (!isa(FD) && !isa(FD)) + // Print "auto" for all deduced return types. This includes C++1y return + // type deduction and lambdas. For trailing return types resolve the + // decltype expression. Otherwise print the real type when this is + // not a constructor or destructor. + if ((isa(FD) && + cast(FD)->getParent()->isLambda()) || + (FT && FT->getResultType()->getAs())) + Proto = "auto " + Proto; + else if (FT && FT->getResultType()->getAs()) + FT->getResultType()->getAs()->getUnderlyingType() + .getAsStringInternal(Proto, Policy); + else if (!isa(FD) && !isa(FD)) AFT->getResultType().getAsStringInternal(Proto, Policy); Out << Proto; @@ -586,6 +632,16 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { Out.flush(); return Name.str().str(); } + if (const CapturedDecl *CD = dyn_cast(CurrentDecl)) { + for (const DeclContext *DC = CD->getParent(); DC; DC = DC->getParent()) + // Skip to its enclosing function or method, but not its enclosing + // CapturedDecl. + if (DC->isFunctionOrMethod() && (DC->getDeclKind() != Decl::Captured)) { + const Decl *D = Decl::castFromDeclContext(DC); + return ComputeName(IT, D); + } + llvm_unreachable("CapturedDecl not inside a function or method"); + } if (const ObjCMethodDecl *MD = dyn_cast(CurrentDecl)) { SmallString<256> Name; llvm::raw_svector_ostream Out(Name); @@ -615,7 +671,8 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { return ""; } -void APNumericStorage::setIntValue(ASTContext &C, const llvm::APInt &Val) { +void APNumericStorage::setIntValue(const ASTContext &C, + const llvm::APInt &Val) { if (hasAllocation()) C.Deallocate(pVal); @@ -631,7 +688,7 @@ void APNumericStorage::setIntValue(ASTContext &C, const llvm::APInt &Val) { VAL = 0; } -IntegerLiteral::IntegerLiteral(ASTContext &C, const llvm::APInt &V, +IntegerLiteral::IntegerLiteral(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l) : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary, false, false, false, false), @@ -643,17 +700,17 @@ IntegerLiteral::IntegerLiteral(ASTContext &C, const llvm::APInt &V, } IntegerLiteral * -IntegerLiteral::Create(ASTContext &C, const llvm::APInt &V, +IntegerLiteral::Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l) { return new (C) IntegerLiteral(C, V, type, l); } IntegerLiteral * -IntegerLiteral::Create(ASTContext &C, EmptyShell Empty) { +IntegerLiteral::Create(const ASTContext &C, EmptyShell Empty) { return new (C) IntegerLiteral(Empty); } -FloatingLiteral::FloatingLiteral(ASTContext &C, const llvm::APFloat &V, +FloatingLiteral::FloatingLiteral(const 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) { @@ -662,20 +719,20 @@ FloatingLiteral::FloatingLiteral(ASTContext &C, const llvm::APFloat &V, setValue(C, V); } -FloatingLiteral::FloatingLiteral(ASTContext &C, EmptyShell Empty) +FloatingLiteral::FloatingLiteral(const ASTContext &C, EmptyShell Empty) : Expr(FloatingLiteralClass, Empty) { setRawSemantics(IEEEhalf); FloatingLiteralBits.IsExact = false; } FloatingLiteral * -FloatingLiteral::Create(ASTContext &C, const llvm::APFloat &V, +FloatingLiteral::Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L) { return new (C) FloatingLiteral(C, V, isexact, Type, L); } FloatingLiteral * -FloatingLiteral::Create(ASTContext &C, EmptyShell Empty) { +FloatingLiteral::Create(const ASTContext &C, EmptyShell Empty) { return new (C) FloatingLiteral(C, Empty); } @@ -749,7 +806,7 @@ int StringLiteral::mapCharByteWidth(TargetInfo const &target,StringKind k) { return CharByteWidth; } -StringLiteral *StringLiteral::Create(ASTContext &C, StringRef Str, +StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str, StringKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumStrs) { @@ -771,7 +828,8 @@ StringLiteral *StringLiteral::Create(ASTContext &C, StringRef Str, return SL; } -StringLiteral *StringLiteral::CreateEmpty(ASTContext &C, unsigned NumStrs) { +StringLiteral *StringLiteral::CreateEmpty(const ASTContext &C, + unsigned NumStrs) { void *Mem = C.Allocate(sizeof(StringLiteral)+ sizeof(SourceLocation)*(NumStrs-1), llvm::alignOf()); @@ -875,7 +933,7 @@ void StringLiteral::outputString(raw_ostream &OS) const { OS << '"'; } -void StringLiteral::setString(ASTContext &C, StringRef Str, +void StringLiteral::setString(const ASTContext &C, StringRef Str, StringKind Kind, bool IsPascal) { //FIXME: we assume that the string data comes from a target that uses the same // code unit size and endianess for the type of string. @@ -1028,9 +1086,9 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) { // Postfix Operators. //===----------------------------------------------------------------------===// -CallExpr::CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs, - ArrayRef args, QualType t, ExprValueKind VK, - SourceLocation rparenloc) +CallExpr::CallExpr(const ASTContext& C, StmtClass SC, Expr *fn, + unsigned NumPreArgs, ArrayRef args, QualType t, + ExprValueKind VK, SourceLocation rparenloc) : Expr(SC, t, VK, OK_Ordinary, fn->isTypeDependent(), fn->isValueDependent(), @@ -1057,7 +1115,7 @@ CallExpr::CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs, RParenLoc = rparenloc; } -CallExpr::CallExpr(ASTContext& C, Expr *fn, ArrayRef args, +CallExpr::CallExpr(const ASTContext& C, Expr *fn, ArrayRef args, QualType t, ExprValueKind VK, SourceLocation rparenloc) : Expr(CallExprClass, t, VK, OK_Ordinary, fn->isTypeDependent(), @@ -1085,14 +1143,14 @@ CallExpr::CallExpr(ASTContext& C, Expr *fn, ArrayRef args, RParenLoc = rparenloc; } -CallExpr::CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty) +CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty) : Expr(SC, Empty), SubExprs(0), NumArgs(0) { // FIXME: Why do we allocate this? SubExprs = new (C) Stmt*[PREARGS_START]; CallExprBits.NumPreArgs = 0; } -CallExpr::CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs, +CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty) : Expr(SC, Empty), SubExprs(0), NumArgs(0) { // FIXME: Why do we allocate this? @@ -1131,7 +1189,7 @@ FunctionDecl *CallExpr::getDirectCallee() { /// setNumArgs - This changes the number of arguments present in this call. /// Any orphaned expressions are deleted by this, and any new operands are set /// to null. -void CallExpr::setNumArgs(ASTContext& C, unsigned NumArgs) { +void CallExpr::setNumArgs(const ASTContext& C, unsigned NumArgs) { // No change, just return. if (NumArgs == getNumArgs()) return; @@ -1220,7 +1278,7 @@ SourceLocation CallExpr::getLocEnd() const { return end; } -OffsetOfExpr *OffsetOfExpr::Create(ASTContext &C, QualType type, +OffsetOfExpr *OffsetOfExpr::Create(const ASTContext &C, QualType type, SourceLocation OperatorLoc, TypeSourceInfo *tsi, ArrayRef comps, @@ -1234,7 +1292,7 @@ OffsetOfExpr *OffsetOfExpr::Create(ASTContext &C, QualType type, RParenLoc); } -OffsetOfExpr *OffsetOfExpr::CreateEmpty(ASTContext &C, +OffsetOfExpr *OffsetOfExpr::CreateEmpty(const ASTContext &C, unsigned numComps, unsigned numExprs) { void *Mem = C.Allocate(sizeof(OffsetOfExpr) + sizeof(OffsetOfNode) * numComps + @@ -1242,7 +1300,7 @@ OffsetOfExpr *OffsetOfExpr::CreateEmpty(ASTContext &C, return new (Mem) OffsetOfExpr(numComps, numExprs); } -OffsetOfExpr::OffsetOfExpr(ASTContext &C, QualType type, +OffsetOfExpr::OffsetOfExpr(const ASTContext &C, QualType type, SourceLocation OperatorLoc, TypeSourceInfo *tsi, ArrayRef comps, ArrayRef exprs, SourceLocation RParenLoc) @@ -1276,7 +1334,7 @@ IdentifierInfo *OffsetOfExpr::OffsetOfNode::getFieldName() const { return reinterpret_cast (Data & ~(uintptr_t)Mask); } -MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, +MemberExpr *MemberExpr::Create(const ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *memberdecl, @@ -1630,7 +1688,7 @@ void CastExpr::setCastPath(const CXXCastPath &Path) { memcpy(path_buffer(), Path.data(), Path.size() * sizeof(CXXBaseSpecifier*)); } -ImplicitCastExpr *ImplicitCastExpr::Create(ASTContext &C, QualType T, +ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind VK) { @@ -1643,7 +1701,7 @@ ImplicitCastExpr *ImplicitCastExpr::Create(ASTContext &C, QualType T, return E; } -ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(ASTContext &C, +ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { void *Buffer = C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); @@ -1651,7 +1709,7 @@ ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(ASTContext &C, } -CStyleCastExpr *CStyleCastExpr::Create(ASTContext &C, QualType T, +CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, @@ -1665,7 +1723,8 @@ CStyleCastExpr *CStyleCastExpr::Create(ASTContext &C, QualType T, return E; } -CStyleCastExpr *CStyleCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) { +CStyleCastExpr *CStyleCastExpr::CreateEmpty(const ASTContext &C, + unsigned PathSize) { void *Buffer = C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize); @@ -1774,7 +1833,7 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) { return OverOps[Opc]; } -InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc, +InitListExpr::InitListExpr(const ASTContext &C, SourceLocation lbraceloc, ArrayRef initExprs, SourceLocation rbraceloc) : Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, false, false), @@ -1782,7 +1841,6 @@ InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc, LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), AltForm(0, true) { sawArrayRangeDesignator(false); - setInitializesStdInitializerList(false); for (unsigned I = 0; I != initExprs.size(); ++I) { if (initExprs[I]->isTypeDependent()) ExprBits.TypeDependent = true; @@ -1797,16 +1855,16 @@ InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc, InitExprs.insert(C, InitExprs.end(), initExprs.begin(), initExprs.end()); } -void InitListExpr::reserveInits(ASTContext &C, unsigned NumInits) { +void InitListExpr::reserveInits(const ASTContext &C, unsigned NumInits) { if (NumInits > InitExprs.size()) InitExprs.reserve(C, NumInits); } -void InitListExpr::resizeInits(ASTContext &C, unsigned NumInits) { +void InitListExpr::resizeInits(const ASTContext &C, unsigned NumInits) { InitExprs.resize(C, NumInits, 0); } -Expr *InitListExpr::updateInit(ASTContext &C, unsigned Init, Expr *expr) { +Expr *InitListExpr::updateInit(const ASTContext &C, unsigned Init, Expr *expr) { if (Init >= InitExprs.size()) { InitExprs.insert(C, InitExprs.end(), Init - InitExprs.size() + 1, 0); InitExprs.back() = expr; @@ -1923,6 +1981,9 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, case GenericSelectionExprClass: return cast(this)->getResultExpr()-> isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); + case ChooseExprClass: + return cast(this)->getChosenSubExpr()-> + isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); case UnaryOperatorClass: { const UnaryOperator *UO = cast(this); @@ -2066,17 +2127,24 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, return false; case CXXTemporaryObjectExprClass: - case CXXConstructExprClass: + case CXXConstructExprClass: { + if (const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl()) { + if (Type->hasAttr()) { + WarnE = this; + Loc = getLocStart(); + R1 = getSourceRange(); + return true; + } + } return false; + } case ObjCMessageExprClass: { const ObjCMessageExpr *ME = cast(this); if (Ctx.getLangOpts().ObjCAutoRefCount && ME->isInstanceMessage() && !ME->getType()->isVoidType() && - ME->getSelector().getIdentifierInfoForSlot(0) && - ME->getSelector().getIdentifierInfoForSlot(0) - ->getName().startswith("init")) { + ME->getMethodFamily() == OMF_init) { WarnE = this; Loc = getExprLoc(); R1 = ME->getSourceRange(); @@ -2161,7 +2229,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, WarnE = this; if (const CXXFunctionalCastExpr *CXXCE = dyn_cast(this)) { - Loc = CXXCE->getTypeBeginLoc(); + Loc = CXXCE->getLocStart(); R1 = CXXCE->getSubExpr()->getSourceRange(); } else { const CStyleCastExpr *CStyleCE = cast(this); @@ -2291,6 +2359,12 @@ Expr* Expr::IgnoreParens() { continue; } } + if (ChooseExpr* P = dyn_cast(E)) { + if (!P->isConditionDependent()) { + E = P->getChosenSubExpr(); + continue; + } + } return E; } } @@ -2300,26 +2374,11 @@ Expr* Expr::IgnoreParens() { Expr *Expr::IgnoreParenCasts() { Expr *E = this; while (true) { - if (ParenExpr* P = dyn_cast(E)) { - E = P->getSubExpr(); - continue; - } + E = E->IgnoreParens(); if (CastExpr *P = dyn_cast(E)) { E = P->getSubExpr(); continue; } - if (UnaryOperator* P = dyn_cast(E)) { - if (P->getOpcode() == UO_Extension) { - E = P->getSubExpr(); - continue; - } - } - if (GenericSelectionExpr* P = dyn_cast(E)) { - if (!P->isResultDependent()) { - E = P->getResultExpr(); - continue; - } - } if (MaterializeTemporaryExpr *Materialize = dyn_cast(E)) { E = Materialize->GetTemporaryExpr(); @@ -2341,24 +2400,12 @@ Expr *Expr::IgnoreParenCasts() { Expr *Expr::IgnoreParenLValueCasts() { Expr *E = this; while (true) { - if (ParenExpr *P = dyn_cast(E)) { - E = P->getSubExpr(); - continue; - } else if (CastExpr *P = dyn_cast(E)) { + E = E->IgnoreParens(); + if (CastExpr *P = dyn_cast(E)) { if (P->getCastKind() == CK_LValueToRValue) { E = P->getSubExpr(); continue; } - } else if (UnaryOperator* P = dyn_cast(E)) { - if (P->getOpcode() == UO_Extension) { - E = P->getSubExpr(); - continue; - } - } else if (GenericSelectionExpr* P = dyn_cast(E)) { - if (!P->isResultDependent()) { - E = P->getResultExpr(); - continue; - } } else if (MaterializeTemporaryExpr *Materialize = dyn_cast(E)) { E = Materialize->GetTemporaryExpr(); @@ -2376,10 +2423,7 @@ Expr *Expr::IgnoreParenLValueCasts() { Expr *Expr::ignoreParenBaseCasts() { Expr *E = this; while (true) { - if (ParenExpr *P = dyn_cast(E)) { - E = P->getSubExpr(); - continue; - } + E = E->IgnoreParens(); if (CastExpr *CE = dyn_cast(E)) { if (CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_UncheckedDerivedToBase || @@ -2396,26 +2440,11 @@ Expr *Expr::ignoreParenBaseCasts() { Expr *Expr::IgnoreParenImpCasts() { Expr *E = this; while (true) { - if (ParenExpr *P = dyn_cast(E)) { - E = P->getSubExpr(); - continue; - } + E = E->IgnoreParens(); if (ImplicitCastExpr *P = dyn_cast(E)) { E = P->getSubExpr(); continue; } - if (UnaryOperator* P = dyn_cast(E)) { - if (P->getOpcode() == UO_Extension) { - E = P->getSubExpr(); - continue; - } - } - if (GenericSelectionExpr* P = dyn_cast(E)) { - if (!P->isResultDependent()) { - E = P->getResultExpr(); - continue; - } - } if (MaterializeTemporaryExpr *Materialize = dyn_cast(E)) { E = Materialize->GetTemporaryExpr(); @@ -2444,10 +2473,7 @@ Expr *Expr::IgnoreConversionOperator() { Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { Expr *E = this; while (true) { - if (ParenExpr *P = dyn_cast(E)) { - E = P->getSubExpr(); - continue; - } + E = E->IgnoreParens(); if (CastExpr *P = dyn_cast(E)) { // We ignore integer <-> casts that are of the same width, ptr<->ptr and @@ -2469,20 +2495,6 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { } } - if (UnaryOperator* P = dyn_cast(E)) { - if (P->getOpcode() == UO_Extension) { - E = P->getSubExpr(); - continue; - } - } - - if (GenericSelectionExpr* P = dyn_cast(E)) { - if (!P->isResultDependent()) { - E = P->getResultExpr(); - continue; - } - } - if (SubstNonTypeTemplateParmExpr *NTTP = dyn_cast(E)) { E = NTTP->getReplacement(); @@ -2628,11 +2640,11 @@ bool Expr::hasAnyTypeDependentArguments(ArrayRef Exprs) { bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { // This function is attempting whether an expression is an initializer - // which can be evaluated at compile-time. isEvaluatable handles most - // of the cases, but it can't deal with some initializer-specific - // expressions, and it can't deal with aggregates; we deal with those here, - // and fall back to isEvaluatable for the other cases. - + // which can be evaluated at compile-time. It very closely parallels + // ConstExprEmitter in CGExprConstant.cpp; if they don't match, it + // will lead to unexpected results. Like ConstExprEmitter, it falls back + // to isEvaluatable most of the time. + // // If we ever capture reference-binding directly in the AST, we can // kill the second parameter. @@ -2643,30 +2655,23 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { switch (getStmtClass()) { default: break; - case IntegerLiteralClass: - case FloatingLiteralClass: case StringLiteralClass: - case ObjCStringLiteralClass: case ObjCEncodeExprClass: return true; case CXXTemporaryObjectExprClass: case CXXConstructExprClass: { const CXXConstructExpr *CE = cast(this); - // Only if it's - if (CE->getConstructor()->isTrivial()) { - // 1) an application of the trivial default constructor or + if (CE->getConstructor()->isTrivial() && + CE->getConstructor()->getParent()->hasTrivialDestructor()) { + // Trivial default constructor if (!CE->getNumArgs()) return true; - // 2) an elidable trivial copy construction of an operand which is - // itself a constant initializer. Note that we consider the - // operand on its own, *not* as a reference binding. - if (CE->isElidable() && - CE->getArg(0)->isConstantInitializer(Ctx, false)) - return true; + // Trivial copy constructor + assert(CE->getNumArgs() == 1 && "trivial ctor with > 1 argument"); + return CE->getArg(0)->isConstantInitializer(Ctx, false); } - // 3) a foldable constexpr constructor. break; } case CompoundLiteralExprClass: { @@ -2677,16 +2682,47 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { return Exp->isConstantInitializer(Ctx, false); } case InitListExprClass: { - // FIXME: This doesn't deal with fields with reference types correctly. - // FIXME: This incorrectly allows pointers cast to integers to be assigned - // to bitfields. - const InitListExpr *Exp = cast(this); - unsigned numInits = Exp->getNumInits(); - for (unsigned i = 0; i < numInits; i++) { - if (!Exp->getInit(i)->isConstantInitializer(Ctx, false)) - return false; + const InitListExpr *ILE = cast(this); + if (ILE->getType()->isArrayType()) { + unsigned numInits = ILE->getNumInits(); + for (unsigned i = 0; i < numInits; i++) { + if (!ILE->getInit(i)->isConstantInitializer(Ctx, false)) + return false; + } + return true; } - return true; + + if (ILE->getType()->isRecordType()) { + unsigned ElementNo = 0; + RecordDecl *RD = ILE->getType()->getAs()->getDecl(); + for (RecordDecl::field_iterator Field = RD->field_begin(), + FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { + // If this is a union, skip all the fields that aren't being initialized. + if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field) + continue; + + // Don't emit anonymous bitfields, they just affect layout. + if (Field->isUnnamedBitfield()) + continue; + + if (ElementNo < ILE->getNumInits()) { + const Expr *Elt = ILE->getInit(ElementNo++); + if (Field->isBitField()) { + // Bitfields have to evaluate to an integer. + llvm::APSInt ResultTmp; + if (!Elt->EvaluateAsInt(ResultTmp, Ctx)) + return false; + } else { + bool RefType = Field->getType()->isReferenceType(); + if (!Elt->isConstantInitializer(Ctx, RefType)) + return false; + } + } + } + return true; + } + + break; } case ImplicitValueInitExprClass: return true; @@ -2694,12 +2730,12 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { return cast(this)->getSubExpr() ->isConstantInitializer(Ctx, IsForRef); case GenericSelectionExprClass: - if (cast(this)->isResultDependent()) - return false; return cast(this)->getResultExpr() ->isConstantInitializer(Ctx, IsForRef); case ChooseExprClass: - return cast(this)->getChosenSubExpr(Ctx) + if (cast(this)->isConditionDependent()) + return false; + return cast(this)->getChosenSubExpr() ->isConstantInitializer(Ctx, IsForRef); case UnaryOperatorClass: { const UnaryOperator* Exp = cast(this); @@ -2710,31 +2746,20 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { case CXXFunctionalCastExprClass: case CXXStaticCastExprClass: case ImplicitCastExprClass: - case CStyleCastExprClass: { + case CStyleCastExprClass: + case ObjCBridgedCastExprClass: + case CXXDynamicCastExprClass: + case CXXReinterpretCastExprClass: + case CXXConstCastExprClass: { const CastExpr *CE = cast(this); - // If we're promoting an integer to an _Atomic type then this is constant - // if the integer is constant. We also need to check the converse in case - // someone does something like: - // - // int a = (_Atomic(int))42; - // - // I doubt anyone would write code like this directly, but it's quite - // possible as the result of macro expansions. - if (CE->getCastKind() == CK_NonAtomicToAtomic || - CE->getCastKind() == CK_AtomicToNonAtomic) - return CE->getSubExpr()->isConstantInitializer(Ctx, false); - - // Handle bitcasts of vector constants. - if (getType()->isVectorType() && CE->getCastKind() == CK_BitCast) - return CE->getSubExpr()->isConstantInitializer(Ctx, false); - // Handle misc casts we want to ignore. - // FIXME: Is it really safe to ignore all these? if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue || CE->getCastKind() == CK_ToUnion || - CE->getCastKind() == CK_ConstructorConversion) + CE->getCastKind() == CK_ConstructorConversion || + CE->getCastKind() == CK_NonAtomicToAtomic || + CE->getCastKind() == CK_AtomicToNonAtomic) return CE->getSubExpr()->isConstantInitializer(Ctx, false); break; @@ -2742,6 +2767,16 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { case MaterializeTemporaryExprClass: return cast(this)->GetTemporaryExpr() ->isConstantInitializer(Ctx, false); + + case SubstNonTypeTemplateParmExprClass: + return cast(this)->getReplacement() + ->isConstantInitializer(Ctx, false); + case CXXDefaultArgExprClass: + return cast(this)->getExpr() + ->isConstantInitializer(Ctx, false); + case CXXDefaultInitExprClass: + return cast(this)->getExpr() + ->isConstantInitializer(Ctx, false); } return isEvaluatable(Ctx); } @@ -2829,9 +2864,11 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { case DesignatedInitExprClass: case ParenListExprClass: case CXXPseudoDestructorExprClass: + case CXXStdInitializerListExprClass: case SubstNonTypeTemplateParmExprClass: case MaterializeTemporaryExprClass: case ShuffleVectorExprClass: + case ConvertVectorExprClass: case AsTypeExprClass: // These have a side-effect if any subexpression does. break; @@ -2858,7 +2895,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { HasSideEffects(Ctx); case ChooseExprClass: - return cast(this)->getChosenSubExpr(Ctx)->HasSideEffects(Ctx); + return cast(this)->getChosenSubExpr()->HasSideEffects(Ctx); case CXXDefaultArgExprClass: return cast(this)->getExpr()->HasSideEffects(Ctx); @@ -3017,7 +3054,8 @@ bool Expr::hasNonTrivialCall(ASTContext &Ctx) { Expr::NullPointerConstantKind Expr::isNullPointerConstant(ASTContext &Ctx, NullPointerConstantValueDependence NPC) const { - if (isValueDependent()) { + if (isValueDependent() && + (!Ctx.getLangOpts().CPlusPlus11 || Ctx.getLangOpts().MicrosoftMode)) { switch (NPC) { case NPC_NeverValueDependent: llvm_unreachable("Unexpected value dependent expression!"); @@ -3053,7 +3091,13 @@ Expr::isNullPointerConstant(ASTContext &Ctx, return PE->getSubExpr()->isNullPointerConstant(Ctx, NPC); } else if (const GenericSelectionExpr *GE = dyn_cast(this)) { + if (GE->isResultDependent()) + return NPCK_NotNull; return GE->getResultExpr()->isNullPointerConstant(Ctx, NPC); + } else if (const ChooseExpr *CE = dyn_cast(this)) { + if (CE->isConditionDependent()) + return NPCK_NotNull; + return CE->getChosenSubExpr()->isNullPointerConstant(Ctx, NPC); } else if (const CXXDefaultArgExpr *DefaultArg = dyn_cast(this)) { // See through default argument expressions. @@ -3078,7 +3122,8 @@ Expr::isNullPointerConstant(ASTContext &Ctx, return NPCK_CXX11_nullptr; if (const RecordType *UT = getType()->getAsUnionType()) - if (UT && UT->getDecl()->hasAttr()) + if (!Ctx.getLangOpts().CPlusPlus11 && + UT && UT->getDecl()->hasAttr()) if (const CompoundLiteralExpr *CLE = dyn_cast(this)){ const Expr *InitExpr = CLE->getInitializer(); if (const InitListExpr *ILE = dyn_cast(InitExpr)) @@ -3089,14 +3134,19 @@ Expr::isNullPointerConstant(ASTContext &Ctx, (Ctx.getLangOpts().CPlusPlus && getType()->isEnumeralType())) return NPCK_NotNull; - // If we have an integer constant expression, we need to *evaluate* it and - // 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().CPlusPlus11) { - if (!isCXX98IntegralConstantExpr(Ctx)) + // C++11 [conv.ptr]p1: A null pointer constant is an integer literal with + // value zero or a prvalue of type std::nullptr_t. + // Microsoft mode permits C++98 rules reflecting MSVC behavior. + const IntegerLiteral *Lit = dyn_cast(this); + if (Lit && !Lit->getValue()) + return NPCK_ZeroLiteral; + else if (!Ctx.getLangOpts().MicrosoftMode || + !isCXX98IntegralConstantExpr(Ctx)) return NPCK_NotNull; } else { + // If we have an integer constant expression, we need to *evaluate* it and + // test for the value 0. if (!isIntegerConstantExpr(Ctx)) return NPCK_NotNull; } @@ -3370,7 +3420,7 @@ void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef Args, } } -ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, +ObjCMessageExpr *ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK, SourceLocation LBracLoc, SourceLocation SuperLoc, @@ -3395,7 +3445,7 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, Method, Args, RBracLoc, isImplicit); } -ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, +ObjCMessageExpr *ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK, SourceLocation LBracLoc, TypeSourceInfo *Receiver, @@ -3418,7 +3468,7 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, isImplicit); } -ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, +ObjCMessageExpr *ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK, SourceLocation LBracLoc, Expr *Receiver, @@ -3441,14 +3491,14 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, isImplicit); } -ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context, +ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(const ASTContext &Context, unsigned NumArgs, unsigned NumStoredSelLocs) { ObjCMessageExpr *Mem = alloc(Context, NumArgs, NumStoredSelLocs); return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs); } -ObjCMessageExpr *ObjCMessageExpr::alloc(ASTContext &C, +ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, ArrayRef Args, SourceLocation RBraceLoc, ArrayRef SelLocs, @@ -3460,7 +3510,7 @@ ObjCMessageExpr *ObjCMessageExpr::alloc(ASTContext &C, return alloc(C, Args.size(), NumStoredSelLocs); } -ObjCMessageExpr *ObjCMessageExpr::alloc(ASTContext &C, +ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, unsigned NumArgs, unsigned NumStoredSelLocs) { unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + @@ -3537,11 +3587,7 @@ StringRef ObjCBridgedCastExpr::getBridgeKindName() const { llvm_unreachable("Invalid BridgeKind!"); } -bool ChooseExpr::isConditionTrue(const ASTContext &C) const { - return getCond()->EvaluateKnownConstInt(C) != 0; -} - -ShuffleVectorExpr::ShuffleVectorExpr(ASTContext &C, ArrayRef args, +ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef args, QualType Type, SourceLocation BLoc, SourceLocation RP) : Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary, @@ -3565,16 +3611,15 @@ ShuffleVectorExpr::ShuffleVectorExpr(ASTContext &C, ArrayRef args, } } -void ShuffleVectorExpr::setExprs(ASTContext &C, Expr ** Exprs, - unsigned NumExprs) { +void ShuffleVectorExpr::setExprs(const ASTContext &C, ArrayRef Exprs) { if (SubExprs) C.Deallocate(SubExprs); - SubExprs = new (C) Stmt* [NumExprs]; - this->NumExprs = NumExprs; - memcpy(SubExprs, Exprs, sizeof(Expr *) * NumExprs); + this->NumExprs = Exprs.size(); + SubExprs = new (C) Stmt*[NumExprs]; + memcpy(SubExprs, Exprs.data(), sizeof(Expr *) * Exprs.size()); } -GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context, +GenericSelectionExpr::GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef AssocTypes, ArrayRef AssocExprs, @@ -3600,7 +3645,7 @@ GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context, std::copy(AssocExprs.begin(), AssocExprs.end(), SubExprs+END_EXPR); } -GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context, +GenericSelectionExpr::GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef AssocTypes, ArrayRef AssocExprs, @@ -3637,7 +3682,7 @@ IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() const { return getField()->getIdentifier(); } -DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty, +DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, unsigned NumDesignators, const Designator *Designators, SourceLocation EqualOrColonLoc, @@ -3704,7 +3749,7 @@ DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty, } DesignatedInitExpr * -DesignatedInitExpr::Create(ASTContext &C, Designator *Designators, +DesignatedInitExpr::Create(const ASTContext &C, Designator *Designators, unsigned NumDesignators, ArrayRef IndexExprs, SourceLocation ColonOrEqualLoc, @@ -3716,14 +3761,14 @@ DesignatedInitExpr::Create(ASTContext &C, Designator *Designators, IndexExprs, Init); } -DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(ASTContext &C, +DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(const ASTContext &C, unsigned NumIndexExprs) { void *Mem = C.Allocate(sizeof(DesignatedInitExpr) + sizeof(Stmt *) * (NumIndexExprs + 1), 8); return new (Mem) DesignatedInitExpr(NumIndexExprs + 1); } -void DesignatedInitExpr::setDesignators(ASTContext &C, +void DesignatedInitExpr::setDesignators(const ASTContext &C, const Designator *Desigs, unsigned NumDesigs) { Designators = new (C) Designator[NumDesigs]; @@ -3790,7 +3835,7 @@ Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator &D) const { /// \brief Replaces the designator at index @p Idx with the series /// of designators in [First, Last). -void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx, +void DesignatedInitExpr::ExpandDesignator(const ASTContext &C, unsigned Idx, const Designator *First, const Designator *Last) { unsigned NumNewDesignators = Last - First; @@ -3815,7 +3860,7 @@ void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx, NumDesignators = NumDesignators - 1 + NumNewDesignators; } -ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc, +ParenListExpr::ParenListExpr(const ASTContext& C, SourceLocation lparenloc, ArrayRef exprs, SourceLocation rparenloc) : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, @@ -3847,7 +3892,8 @@ const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { return cast(e); } -PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &Context, EmptyShell sh, +PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &Context, + EmptyShell sh, unsigned numSemanticExprs) { void *buffer = Context.Allocate(sizeof(PseudoObjectExpr) + (1 + numSemanticExprs) * sizeof(Expr*), @@ -3860,7 +3906,7 @@ PseudoObjectExpr::PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs) PseudoObjectExprBits.NumSubExprs = numSemanticExprs + 1; } -PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &C, Expr *syntax, +PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &C, Expr *syntax, ArrayRef semantics, unsigned resultIndex) { assert(syntax && "no syntactic expression!"); @@ -3975,7 +4021,7 @@ ObjCArrayLiteral::ObjCArrayLiteral(ArrayRef Elements, } } -ObjCArrayLiteral *ObjCArrayLiteral::Create(ASTContext &C, +ObjCArrayLiteral *ObjCArrayLiteral::Create(const ASTContext &C, ArrayRef Elements, QualType T, ObjCMethodDecl * Method, SourceRange SR) { @@ -3984,7 +4030,7 @@ ObjCArrayLiteral *ObjCArrayLiteral::Create(ASTContext &C, return new (Mem) ObjCArrayLiteral(Elements, T, Method, SR); } -ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(ASTContext &C, +ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(const ASTContext &C, unsigned NumElements) { void *Mem = C.Allocate(sizeof(ObjCArrayLiteral) @@ -4029,7 +4075,7 @@ ObjCDictionaryLiteral::ObjCDictionaryLiteral( } ObjCDictionaryLiteral * -ObjCDictionaryLiteral::Create(ASTContext &C, +ObjCDictionaryLiteral::Create(const ASTContext &C, ArrayRef VK, bool HasPackExpansions, QualType T, ObjCMethodDecl *method, @@ -4044,7 +4090,7 @@ ObjCDictionaryLiteral::Create(ASTContext &C, } ObjCDictionaryLiteral * -ObjCDictionaryLiteral::CreateEmpty(ASTContext &C, unsigned NumElements, +ObjCDictionaryLiteral::CreateEmpty(const ASTContext &C, unsigned NumElements, bool HasPackExpansions) { unsigned ExpansionsSize = 0; if (HasPackExpansions) @@ -4055,7 +4101,7 @@ ObjCDictionaryLiteral::CreateEmpty(ASTContext &C, unsigned NumElements, HasPackExpansions); } -ObjCSubscriptRefExpr *ObjCSubscriptRefExpr::Create(ASTContext &C, +ObjCSubscriptRefExpr *ObjCSubscriptRefExpr::Create(const ASTContext &C, Expr *base, Expr *key, QualType T, ObjCMethodDecl *getMethod, diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp index 402d7b5..3738c0e 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -40,46 +40,106 @@ bool CXXTypeidExpr::isPotentiallyEvaluated() const { return false; } -QualType CXXTypeidExpr::getTypeOperand() const { +QualType CXXTypeidExpr::getTypeOperand(ASTContext &Context) const { assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); - return Operand.get()->getType().getNonReferenceType() - .getUnqualifiedType(); + Qualifiers Quals; + return Context.getUnqualifiedArrayType( + Operand.get()->getType().getNonReferenceType(), Quals); } -QualType CXXUuidofExpr::getTypeOperand() const { +QualType CXXUuidofExpr::getTypeOperand(ASTContext &Context) const { assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); - return Operand.get()->getType().getNonReferenceType() - .getUnqualifiedType(); + Qualifiers Quals; + return Context.getUnqualifiedArrayType( + Operand.get()->getType().getNonReferenceType(), Quals); } // static -UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT) { +UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT, + bool *RDHasMultipleGUIDsPtr) { // Optionally remove one level of pointer, reference or array indirection. const Type *Ty = QT.getTypePtr(); if (QT->isPointerType() || QT->isReferenceType()) Ty = QT->getPointeeType().getTypePtr(); else if (QT->isArrayType()) - Ty = cast(QT)->getElementType().getTypePtr(); + Ty = Ty->getBaseElementTypeUnsafe(); // Loop all record redeclaration looking for an uuid attribute. CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + if (!RD) + return 0; + + // __uuidof can grab UUIDs from template arguments. + if (ClassTemplateSpecializationDecl *CTSD = + dyn_cast(RD)) { + const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); + UuidAttr *UuidForRD = 0; + + for (unsigned I = 0, N = TAL.size(); I != N; ++I) { + const TemplateArgument &TA = TAL[I]; + bool SeenMultipleGUIDs = false; + + UuidAttr *UuidForTA = 0; + if (TA.getKind() == TemplateArgument::Type) + UuidForTA = GetUuidAttrOfType(TA.getAsType(), &SeenMultipleGUIDs); + else if (TA.getKind() == TemplateArgument::Declaration) + UuidForTA = + GetUuidAttrOfType(TA.getAsDecl()->getType(), &SeenMultipleGUIDs); + + // If the template argument has a UUID, there are three cases: + // - This is the first UUID seen for this RecordDecl. + // - This is a different UUID than previously seen for this RecordDecl. + // - This is the same UUID than previously seen for this RecordDecl. + if (UuidForTA) { + if (!UuidForRD) + UuidForRD = UuidForTA; + else if (UuidForRD != UuidForTA) + SeenMultipleGUIDs = true; + } + + // Seeing multiple UUIDs means that we couldn't find a UUID + if (SeenMultipleGUIDs) { + if (RDHasMultipleGUIDsPtr) + *RDHasMultipleGUIDsPtr = true; + return 0; + } + } + + return UuidForRD; + } + for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(), - E = RD->redecls_end(); I != E; ++I) { + E = RD->redecls_end(); + I != E; ++I) if (UuidAttr *Uuid = I->getAttr()) return Uuid; - } return 0; } +StringRef CXXUuidofExpr::getUuidAsStringRef(ASTContext &Context) const { + StringRef Uuid; + if (isTypeOperand()) + Uuid = CXXUuidofExpr::GetUuidAttrOfType(getTypeOperand(Context))->getGuid(); + else { + // Special case: __uuidof(0) means an all-zero GUID. + Expr *Op = getExprOperand(); + if (!Op->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) + Uuid = CXXUuidofExpr::GetUuidAttrOfType(Op->getType())->getGuid(); + else + Uuid = "00000000-0000-0000-0000-000000000000"; + } + return Uuid; +} + // CXXScalarValueInitExpr SourceLocation CXXScalarValueInitExpr::getLocStart() const { return TypeInfo ? TypeInfo->getTypeLoc().getBeginLoc() : RParenLoc; } // CXXNewExpr -CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, - FunctionDecl *operatorDelete, +CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew, + FunctionDecl *operatorNew, FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize, ArrayRef placementArgs, SourceRange typeIdParens, Expr *arraySize, @@ -134,11 +194,14 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, this->Range.setEnd(DirectInitRange.getEnd()); break; case ListInit: this->Range.setEnd(getInitializer()->getSourceRange().getEnd()); break; - default: break; + default: + if (TypeIdParens.isValid()) + this->Range.setEnd(TypeIdParens.getEnd()); + break; } } -void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray, +void CXXNewExpr::AllocateArgsArray(const ASTContext &C, bool isArray, unsigned numPlaceArgs, bool hasInitializer){ assert(SubExprs == 0 && "SubExprs already allocated"); Array = isArray; @@ -148,7 +211,7 @@ void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray, SubExprs = new (C) Stmt*[TotalSize]; } -bool CXXNewExpr::shouldNullCheckAllocation(ASTContext &Ctx) const { +bool CXXNewExpr::shouldNullCheckAllocation(const ASTContext &Ctx) const { return getOperatorNew()->getType()-> castAs()->isNothrow(Ctx); } @@ -172,14 +235,16 @@ PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info) Location = Info->getTypeLoc().getLocalSourceRange().getBegin(); } -CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context, +CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(const ASTContext &Context, Expr *Base, bool isArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType, SourceLocation ColonColonLoc, SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType) : Expr(CXXPseudoDestructorExprClass, - Context.getPointerType(Context.getFunctionType(Context.VoidTy, None, - FunctionProtoType::ExtProtoInfo())), + Context.getPointerType(Context.getFunctionType( + Context.VoidTy, None, + FunctionProtoType::ExtProtoInfo( + Context.getDefaultCallingConvention(false, true)))), VK_RValue, OK_Ordinary, /*isTypeDependent=*/(Base->isTypeDependent() || (DestroyedType.getTypeSourceInfo() && @@ -224,7 +289,7 @@ SourceLocation CXXPseudoDestructorExpr::getLocEnd() const { // UnresolvedLookupExpr UnresolvedLookupExpr * -UnresolvedLookupExpr::Create(ASTContext &C, +UnresolvedLookupExpr::Create(const ASTContext &C, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, @@ -245,7 +310,7 @@ UnresolvedLookupExpr::Create(ASTContext &C, } UnresolvedLookupExpr * -UnresolvedLookupExpr::CreateEmpty(ASTContext &C, +UnresolvedLookupExpr::CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { std::size_t size = sizeof(UnresolvedLookupExpr); @@ -258,7 +323,7 @@ UnresolvedLookupExpr::CreateEmpty(ASTContext &C, return E; } -OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, +OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, @@ -330,7 +395,7 @@ OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, setType(C.DependentTy); } -void OverloadExpr::initializeResults(ASTContext &C, +void OverloadExpr::initializeResults(const ASTContext &C, UnresolvedSetIterator Begin, UnresolvedSetIterator End) { assert(Results == 0 && "Results already initialized!"); @@ -386,11 +451,12 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T, } DependentScopeDeclRefExpr * -DependentScopeDeclRefExpr::Create(ASTContext &C, +DependentScopeDeclRefExpr::Create(const ASTContext &C, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *Args) { + assert(QualifierLoc && "should be created for dependent qualifiers"); std::size_t size = sizeof(DependentScopeDeclRefExpr); if (Args) size += ASTTemplateKWAndArgsInfo::sizeFor(Args->size()); @@ -402,7 +468,7 @@ DependentScopeDeclRefExpr::Create(ASTContext &C, } DependentScopeDeclRefExpr * -DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C, +DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { std::size_t size = sizeof(DependentScopeDeclRefExpr); @@ -427,8 +493,8 @@ SourceLocation CXXConstructExpr::getLocEnd() const { if (isa(this)) return cast(this)->getLocEnd(); - if (ParenRange.isValid()) - return ParenRange.getEnd(); + if (ParenOrBraceRange.isValid()) + return ParenOrBraceRange.getEnd(); SourceLocation End = Loc; for (unsigned I = getNumArgs(); I > 0; --I) { @@ -520,7 +586,7 @@ const char *CXXNamedCastExpr::getCastName() const { } } -CXXStaticCastExpr *CXXStaticCastExpr::Create(ASTContext &C, QualType T, +CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, @@ -538,14 +604,14 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(ASTContext &C, QualType T, return E; } -CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(ASTContext &C, +CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { void *Buffer = C.Allocate(sizeof(CXXStaticCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize); } -CXXDynamicCastExpr *CXXDynamicCastExpr::Create(ASTContext &C, QualType T, +CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, @@ -563,7 +629,7 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(ASTContext &C, QualType T, return E; } -CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(ASTContext &C, +CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { void *Buffer = C.Allocate(sizeof(CXXDynamicCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); @@ -604,8 +670,8 @@ bool CXXDynamicCastExpr::isAlwaysNull() const } CXXReinterpretCastExpr * -CXXReinterpretCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK, - CastKind K, Expr *Op, +CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T, + ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation RParenLoc, @@ -621,13 +687,13 @@ CXXReinterpretCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK, } CXXReinterpretCastExpr * -CXXReinterpretCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) { +CXXReinterpretCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { void *Buffer = C.Allocate(sizeof(CXXReinterpretCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize); } -CXXConstCastExpr *CXXConstCastExpr::Create(ASTContext &C, QualType T, +CXXConstCastExpr *CXXConstCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK, Expr *Op, TypeSourceInfo *WrittenTy, SourceLocation L, @@ -636,31 +702,39 @@ CXXConstCastExpr *CXXConstCastExpr::Create(ASTContext &C, QualType T, return new (C) CXXConstCastExpr(T, VK, Op, WrittenTy, L, RParenLoc, AngleBrackets); } -CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(ASTContext &C) { +CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(const ASTContext &C) { return new (C) CXXConstCastExpr(EmptyShell()); } CXXFunctionalCastExpr * -CXXFunctionalCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK, - TypeSourceInfo *Written, SourceLocation L, - CastKind K, Expr *Op, const CXXCastPath *BasePath, - SourceLocation R) { +CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK, + TypeSourceInfo *Written, CastKind K, Expr *Op, + const CXXCastPath *BasePath, + SourceLocation L, SourceLocation R) { unsigned PathSize = (BasePath ? BasePath->size() : 0); void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); CXXFunctionalCastExpr *E = - new (Buffer) CXXFunctionalCastExpr(T, VK, Written, L, K, Op, PathSize, R); + new (Buffer) CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, L, R); if (PathSize) E->setCastPath(*BasePath); return E; } CXXFunctionalCastExpr * -CXXFunctionalCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) { +CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize); } +SourceLocation CXXFunctionalCastExpr::getLocStart() const { + return getTypeInfoAsWritten()->getTypeLoc().getLocStart(); +} + +SourceLocation CXXFunctionalCastExpr::getLocEnd() const { + return RParenLoc.isValid() ? RParenLoc : getSubExpr()->getLocEnd(); +} + UserDefinedLiteral::LiteralOperatorKind UserDefinedLiteral::getLiteralOperatorKind() const { if (getNumArgs() == 0) @@ -696,14 +770,14 @@ const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const { } CXXDefaultArgExpr * -CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc, +CXXDefaultArgExpr::Create(const ASTContext &C, SourceLocation Loc, ParmVarDecl *Param, Expr *SubExpr) { void *Mem = C.Allocate(sizeof(CXXDefaultArgExpr) + sizeof(Stmt *)); return new (Mem) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param, SubExpr); } -CXXDefaultInitExpr::CXXDefaultInitExpr(ASTContext &C, SourceLocation Loc, +CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc, FieldDecl *Field, QualType T) : Expr(CXXDefaultInitExprClass, T.getNonLValueExprType(C), T->isLValueReferenceType() ? VK_LValue : T->isRValueReferenceType() @@ -714,12 +788,12 @@ CXXDefaultInitExpr::CXXDefaultInitExpr(ASTContext &C, SourceLocation Loc, assert(Field->hasInClassInitializer()); } -CXXTemporary *CXXTemporary::Create(ASTContext &C, +CXXTemporary *CXXTemporary::Create(const ASTContext &C, const CXXDestructorDecl *Destructor) { return new (C) CXXTemporary(Destructor); } -CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(ASTContext &C, +CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(const ASTContext &C, CXXTemporary *Temp, Expr* SubExpr) { assert((SubExpr->getType()->isRecordType() || @@ -729,11 +803,11 @@ CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(ASTContext &C, return new (C) CXXBindTemporaryExpr(Temp, SubExpr); } -CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C, +CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(const ASTContext &C, CXXConstructorDecl *Cons, TypeSourceInfo *Type, ArrayRef Args, - SourceRange parenRange, + SourceRange ParenOrBraceRange, bool HadMultipleCandidates, bool ListInitialization, bool ZeroInitialization) @@ -743,7 +817,7 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C, Cons, false, Args, HadMultipleCandidates, ListInitialization, ZeroInitialization, - CXXConstructExpr::CK_Complete, parenRange), + CXXConstructExpr::CK_Complete, ParenOrBraceRange), Type(Type) { } @@ -752,10 +826,13 @@ SourceLocation CXXTemporaryObjectExpr::getLocStart() const { } SourceLocation CXXTemporaryObjectExpr::getLocEnd() const { - return getParenRange().getEnd(); + SourceLocation Loc = getParenOrBraceRange().getEnd(); + if (Loc.isInvalid() && getNumArgs()) + Loc = getArg(getNumArgs()-1)->getLocEnd(); + return Loc; } -CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T, +CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T, SourceLocation Loc, CXXConstructorDecl *D, bool Elidable, ArrayRef Args, @@ -763,28 +840,29 @@ CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T, bool ListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, - SourceRange ParenRange) { + SourceRange ParenOrBraceRange) { return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, Elidable, Args, HadMultipleCandidates, ListInitialization, ZeroInitialization, ConstructKind, - ParenRange); + ParenOrBraceRange); } -CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, - SourceLocation Loc, +CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC, + QualType T, SourceLocation Loc, CXXConstructorDecl *D, bool elidable, ArrayRef args, bool HadMultipleCandidates, bool ListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, - SourceRange ParenRange) + SourceRange ParenOrBraceRange) : Expr(SC, T, VK_RValue, OK_Ordinary, T->isDependentType(), T->isDependentType(), T->isInstantiationDependentType(), T->containsUnexpandedParameterPack()), - Constructor(D), Loc(Loc), ParenRange(ParenRange), NumArgs(args.size()), + Constructor(D), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange), + NumArgs(args.size()), Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates), ListInitialization(ListInitialization), ZeroInitialization(ZeroInitialization), @@ -811,7 +889,7 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, LambdaExpr::Capture::Capture(SourceLocation Loc, bool Implicit, LambdaCaptureKind Kind, VarDecl *Var, SourceLocation EllipsisLoc) - : VarAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc) + : DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc) { unsigned Bits = 0; if (Implicit) @@ -829,20 +907,22 @@ LambdaExpr::Capture::Capture(SourceLocation Loc, bool Implicit, assert(Var && "capture must have a variable!"); break; } - VarAndBits.setInt(Bits); + DeclAndBits.setInt(Bits); } LambdaCaptureKind LambdaExpr::Capture::getCaptureKind() const { - if (capturesThis()) + Decl *D = DeclAndBits.getPointer(); + if (!D) return LCK_This; - return (VarAndBits.getInt() & Capture_ByCopy)? LCK_ByCopy : LCK_ByRef; + return (DeclAndBits.getInt() & Capture_ByCopy) ? LCK_ByCopy : LCK_ByRef; } -LambdaExpr::LambdaExpr(QualType T, +LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, - ArrayRef Captures, + SourceLocation CaptureDefaultLoc, + ArrayRef Captures, bool ExplicitParams, bool ExplicitResultType, ArrayRef CaptureInits, @@ -854,6 +934,7 @@ LambdaExpr::LambdaExpr(QualType T, T->isDependentType(), T->isDependentType(), T->isDependentType(), ContainsUnexpandedParameterPack), IntroducerRange(IntroducerRange), + CaptureDefaultLoc(CaptureDefaultLoc), NumCaptures(Captures.size()), CaptureDefault(CaptureDefault), ExplicitParams(ExplicitParams), @@ -867,7 +948,7 @@ LambdaExpr::LambdaExpr(QualType T, // FIXME: Propagate "has unexpanded parameter pack" bit. // Copy captures. - ASTContext &Context = Class->getASTContext(); + const ASTContext &Context = Class->getASTContext(); Data.NumCaptures = NumCaptures; Data.NumExplicitCaptures = 0; Data.Captures = (Capture *)Context.Allocate(sizeof(Capture) * NumCaptures); @@ -899,11 +980,12 @@ LambdaExpr::LambdaExpr(QualType T, } } -LambdaExpr *LambdaExpr::Create(ASTContext &Context, +LambdaExpr *LambdaExpr::Create(const ASTContext &Context, CXXRecordDecl *Class, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, - ArrayRef Captures, + SourceLocation CaptureDefaultLoc, + ArrayRef Captures, bool ExplicitParams, bool ExplicitResultType, ArrayRef CaptureInits, @@ -923,13 +1005,15 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context, Size += sizeof(VarDecl *) * ArrayIndexVars.size(); } void *Mem = Context.Allocate(Size); - return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault, - Captures, ExplicitParams, ExplicitResultType, + return new (Mem) LambdaExpr(T, IntroducerRange, + CaptureDefault, CaptureDefaultLoc, Captures, + ExplicitParams, ExplicitResultType, CaptureInits, ArrayIndexVars, ArrayIndexStarts, ClosingBrace, ContainsUnexpandedParameterPack); } -LambdaExpr *LambdaExpr::CreateDeserialized(ASTContext &C, unsigned NumCaptures, +LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C, + unsigned NumCaptures, unsigned NumArrayIndexVars) { unsigned Size = sizeof(LambdaExpr) + sizeof(Stmt *) * (NumCaptures + 1); if (NumArrayIndexVars) @@ -984,13 +1068,13 @@ CXXRecordDecl *LambdaExpr::getLambdaClass() const { CXXMethodDecl *LambdaExpr::getCallOperator() const { CXXRecordDecl *Record = getLambdaClass(); - DeclarationName Name - = Record->getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); - DeclContext::lookup_result Calls = Record->lookup(Name); - assert(!Calls.empty() && "Missing lambda call operator!"); - assert(Calls.size() == 1 && "More than one lambda call operator!"); - CXXMethodDecl *Result = cast(Calls.front()); - return Result; + return Record->getLambdaCallOperator(); +} + +TemplateParameterList *LambdaExpr::getTemplateParameterList() const { + CXXRecordDecl *Record = getLambdaClass(); + return Record->getGenericLambdaTemplateParameterList(); + } CompoundStmt *LambdaExpr::getBody() const { @@ -1017,7 +1101,7 @@ ExprWithCleanups::ExprWithCleanups(Expr *subexpr, getObjectsBuffer()[i] = objects[i]; } -ExprWithCleanups *ExprWithCleanups::Create(ASTContext &C, Expr *subexpr, +ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr, ArrayRef objects) { size_t size = sizeof(ExprWithCleanups) + objects.size() * sizeof(CleanupObject); @@ -1030,7 +1114,8 @@ ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects) ExprWithCleanupsBits.NumObjects = numObjects; } -ExprWithCleanups *ExprWithCleanups::Create(ASTContext &C, EmptyShell empty, +ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, + EmptyShell empty, unsigned numObjects) { size_t size = sizeof(ExprWithCleanups) + numObjects * sizeof(CleanupObject); void *buffer = C.Allocate(size, llvm::alignOf()); @@ -1063,7 +1148,7 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type, } CXXUnresolvedConstructExpr * -CXXUnresolvedConstructExpr::Create(ASTContext &C, +CXXUnresolvedConstructExpr::Create(const ASTContext &C, TypeSourceInfo *Type, SourceLocation LParenLoc, ArrayRef Args, @@ -1074,7 +1159,7 @@ CXXUnresolvedConstructExpr::Create(ASTContext &C, } CXXUnresolvedConstructExpr * -CXXUnresolvedConstructExpr::CreateEmpty(ASTContext &C, unsigned NumArgs) { +CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &C, unsigned NumArgs) { Stmt::EmptyShell Empty; void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) + sizeof(Expr *) * NumArgs); @@ -1085,7 +1170,7 @@ SourceLocation CXXUnresolvedConstructExpr::getLocStart() const { return Type->getTypeLoc().getBeginLoc(); } -CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, +CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, @@ -1121,7 +1206,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, } } -CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, +CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, @@ -1142,7 +1227,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, MemberNameInfo(MemberNameInfo) { } CXXDependentScopeMemberExpr * -CXXDependentScopeMemberExpr::Create(ASTContext &C, +CXXDependentScopeMemberExpr::Create(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, @@ -1171,7 +1256,7 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C, } CXXDependentScopeMemberExpr * -CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C, +CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { if (!HasTemplateKWAndArgsInfo) @@ -1222,7 +1307,7 @@ static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin, return true; } -UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, +UnresolvedMemberExpr::UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, @@ -1260,8 +1345,7 @@ bool UnresolvedMemberExpr::isImplicitAccess() const { } UnresolvedMemberExpr * -UnresolvedMemberExpr::Create(ASTContext &C, - bool HasUnresolvedUsing, +UnresolvedMemberExpr::Create(const ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, @@ -1284,7 +1368,8 @@ UnresolvedMemberExpr::Create(ASTContext &C, } UnresolvedMemberExpr * -UnresolvedMemberExpr::CreateEmpty(ASTContext &C, bool HasTemplateKWAndArgsInfo, +UnresolvedMemberExpr::CreateEmpty(const ASTContext &C, + bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { std::size_t size = sizeof(UnresolvedMemberExpr); if (HasTemplateKWAndArgsInfo) @@ -1352,7 +1437,7 @@ FunctionParmPackExpr::FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack, } FunctionParmPackExpr * -FunctionParmPackExpr::Create(ASTContext &Context, QualType T, +FunctionParmPackExpr::Create(const ASTContext &Context, QualType T, ParmVarDecl *ParamPack, SourceLocation NameLoc, ArrayRef Params) { return new (Context.Allocate(sizeof(FunctionParmPackExpr) + @@ -1361,7 +1446,8 @@ FunctionParmPackExpr::Create(ASTContext &Context, QualType T, } FunctionParmPackExpr * -FunctionParmPackExpr::CreateEmpty(ASTContext &Context, unsigned NumParams) { +FunctionParmPackExpr::CreateEmpty(const ASTContext &Context, + unsigned NumParams) { return new (Context.Allocate(sizeof(FunctionParmPackExpr) + sizeof(ParmVarDecl*) * NumParams)) FunctionParmPackExpr(QualType(), 0, SourceLocation(), 0, 0); @@ -1396,7 +1482,7 @@ TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, } } -TypeTraitExpr *TypeTraitExpr::Create(ASTContext &C, QualType T, +TypeTraitExpr *TypeTraitExpr::Create(const ASTContext &C, QualType T, SourceLocation Loc, TypeTrait Kind, ArrayRef Args, @@ -1407,7 +1493,7 @@ TypeTraitExpr *TypeTraitExpr::Create(ASTContext &C, QualType T, return new (Mem) TypeTraitExpr(T, Loc, Kind, Args, RParenLoc, Value); } -TypeTraitExpr *TypeTraitExpr::CreateDeserialized(ASTContext &C, +TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C, unsigned NumArgs) { unsigned Size = sizeof(TypeTraitExpr) + sizeof(TypeSourceInfo*) * NumArgs; void *Mem = C.Allocate(Size); diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp index bcb6d4e..54f77ef 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp @@ -155,6 +155,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::OffsetOfExprClass: case Expr::CXXThrowExprClass: case Expr::ShuffleVectorExprClass: + case Expr::ConvertVectorExprClass: case Expr::IntegerLiteralClass: case Expr::CharacterLiteralClass: case Expr::AddrLabelExprClass: @@ -286,13 +287,16 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { // __builtin_choose_expr is equivalent to the chosen expression. case Expr::ChooseExprClass: - return ClassifyInternal(Ctx, cast(E)->getChosenSubExpr(Ctx)); + return ClassifyInternal(Ctx, cast(E)->getChosenSubExpr()); // Extended vector element access is an lvalue unless there are duplicates // in the shuffle expression. case Expr::ExtVectorElementExprClass: - return cast(E)->containsDuplicateElements() ? - Cl::CL_DuplicateVectorComponents : Cl::CL_LValue; + if (cast(E)->containsDuplicateElements()) + return Cl::CL_DuplicateVectorComponents; + if (cast(E)->isArrow()) + return Cl::CL_LValue; + return ClassifyInternal(Ctx, cast(E)->getBase()); // Simply look at the actual default argument. case Expr::CXXDefaultArgExprClass: @@ -353,6 +357,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::CXXConstructExprClass: case Expr::CXXTemporaryObjectExprClass: case Expr::LambdaExprClass: + case Expr::CXXStdInitializerListExprClass: return Cl::CL_ClassTemporary; case Expr::VAArgExprClass: @@ -587,6 +592,8 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, // Const stuff is obviously not modifiable. if (CT.isConstQualified()) return Cl::CM_ConstQualified; + if (CT.getQualifiers().getAddressSpace() == LangAS::opencl_constant) + return Cl::CM_ConstQualified; // Arrays are not modifiable, only their elements are. if (CT->isArrayType()) diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index 8c65029..390cfe9 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -23,8 +23,8 @@ // where it is possible to determine the evaluated result regardless. // // * A set of notes indicating why the evaluation was not a constant expression -// (under the C++11 rules only, at the moment), or, if folding failed too, -// why the expression could not be folded. +// (under the C++11 / C++1y rules only, at the moment), or, if folding failed +// too, why the expression could not be folded. // // If we are checking for a potential constant expression, failure to constant // fold a potential constant sub-expression will be indicated by a 'false' @@ -63,7 +63,25 @@ namespace { if (!B) return QualType(); if (const ValueDecl *D = B.dyn_cast()) return D->getType(); - return B.get()->getType(); + + const Expr *Base = B.get(); + + // For a materialized temporary, the type of the temporary we materialized + // may not be the type of the expression. + if (const MaterializeTemporaryExpr *MTE = + dyn_cast(Base)) { + SmallVector CommaLHSs; + SmallVector Adjustments; + const Expr *Temp = MTE->GetTemporaryExpr(); + const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs, + Adjustments); + // Keep any cv-qualifiers from the reference if we generated a temporary + // for it. + if (Inner != Temp) + return Inner->getType(); + } + + return Base->getType(); } /// Get an LValue path entry, which is known to not be an array index, as a @@ -284,7 +302,7 @@ namespace { /// This - The binding for the this pointer in this call, if any. const LValue *This; - /// ParmBindings - Parameter bindings for this function call, indexed by + /// Arguments - Parameter bindings for this function call, indexed by /// parameters' function scope indices. APValue *Arguments; @@ -299,6 +317,12 @@ namespace { const FunctionDecl *Callee, const LValue *This, APValue *Arguments); ~CallStackFrame(); + + APValue *getTemporary(const void *Key) { + MapTy::iterator I = Temporaries.find(Key); + return I == Temporaries.end() ? 0 : &I->second; + } + APValue &createTemporary(const void *Key, bool IsLifetimeExtended); }; /// Temporarily override 'this'. @@ -343,14 +367,37 @@ namespace { OptionalDiagnostic &operator<<(const APFloat &F) { if (Diag) { + // FIXME: Force the precision of the source value down so we don't + // print digits which are usually useless (we don't really care here if + // we truncate a digit by accident in edge cases). Ideally, + // APFloat::toString would automatically print the shortest + // representation which rounds to the correct value, but it's a bit + // tricky to implement. + unsigned precision = + llvm::APFloat::semanticsPrecision(F.getSemantics()); + precision = (precision * 59 + 195) / 196; SmallVector Buffer; - F.toString(Buffer); + F.toString(Buffer, precision); *Diag << StringRef(Buffer.data(), Buffer.size()); } return *this; } }; + /// A cleanup, and a flag indicating whether it is lifetime-extended. + class Cleanup { + llvm::PointerIntPair Value; + + public: + Cleanup(APValue *Val, bool IsLifetimeExtended) + : Value(Val, IsLifetimeExtended) {} + + bool isLifetimeExtended() const { return Value.getInt(); } + void endLifetime() { + *Value.getPointer() = APValue(); + } + }; + /// EvalInfo - This is a private struct used by the evaluator to capture /// information about a subexpression as it is folded. It retains information /// about the AST context, but also maintains information about the folded @@ -380,13 +427,22 @@ namespace { /// NextCallIndex - The next call index to assign. unsigned NextCallIndex; + /// StepsLeft - The remaining number of evaluation steps we're permitted + /// to perform. This is essentially a limit for the number of statements + /// we will evaluate. + unsigned StepsLeft; + /// BottomFrame - The frame in which evaluation started. This must be /// initialized after CurrentCall and CallStackDepth. CallStackFrame BottomFrame; + /// A stack of values whose lifetimes end at the end of some surrounding + /// evaluation frame. + llvm::SmallVector CleanupStack; + /// EvaluatingDecl - This is the declaration whose initializer is being /// evaluated, if any. - const VarDecl *EvaluatingDecl; + APValue::LValueBase EvaluatingDecl; /// EvaluatingDeclValue - This is the value being constructed for the /// declaration whose initializer is being evaluated, if any. @@ -396,24 +452,52 @@ namespace { /// notes attached to it will also be stored, otherwise they will not be. bool HasActiveDiagnostic; - /// CheckingPotentialConstantExpression - Are we checking whether the - /// expression is a potential constant expression? If so, some diagnostics - /// are suppressed. - bool CheckingPotentialConstantExpression; - - bool IntOverflowCheckMode; + enum EvaluationMode { + /// Evaluate as a constant expression. Stop if we find that the expression + /// is not a constant expression. + EM_ConstantExpression, - EvalInfo(const ASTContext &C, Expr::EvalStatus &S, - bool OverflowCheckMode=false) + /// Evaluate as a potential constant expression. Keep going if we hit a + /// construct that we can't evaluate yet (because we don't yet know the + /// value of something) but stop if we hit something that could never be + /// a constant expression. + EM_PotentialConstantExpression, + + /// Fold the expression to a constant. Stop if we hit a side-effect that + /// we can't model. + EM_ConstantFold, + + /// Evaluate the expression looking for integer overflow and similar + /// issues. Don't worry about side-effects, and try to visit all + /// subexpressions. + EM_EvaluateForOverflow, + + /// Evaluate in any way we know how. Don't worry about side-effects that + /// can't be modeled. + EM_IgnoreSideEffects + } EvalMode; + + /// Are we checking whether the expression is a potential constant + /// expression? + bool checkingPotentialConstantExpression() const { + return EvalMode == EM_PotentialConstantExpression; + } + + /// Are we checking an expression for overflow? + // FIXME: We should check for any kind of undefined or suspicious behavior + // in such constructs, not just overflow. + bool checkingForOverflow() { return EvalMode == EM_EvaluateForOverflow; } + + EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode) : Ctx(const_cast(C)), EvalStatus(S), CurrentCall(0), CallStackDepth(0), NextCallIndex(1), + StepsLeft(getLangOpts().ConstexprStepLimit), BottomFrame(*this, SourceLocation(), 0, 0, 0), - EvaluatingDecl(0), EvaluatingDeclValue(0), HasActiveDiagnostic(false), - CheckingPotentialConstantExpression(false), - IntOverflowCheckMode(OverflowCheckMode) {} + EvaluatingDecl((const ValueDecl*)0), EvaluatingDeclValue(0), + HasActiveDiagnostic(false), EvalMode(Mode) {} - void setEvaluatingDecl(const VarDecl *VD, APValue &Value) { - EvaluatingDecl = VD; + void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { + EvaluatingDecl = Base; EvaluatingDeclValue = &Value; } @@ -422,7 +506,7 @@ namespace { bool CheckCallLimit(SourceLocation Loc) { // Don't perform any constexpr calls (other than the call we're checking) // when checking a potential constant expression. - if (CheckingPotentialConstantExpression && CallStackDepth > 1) + if (checkingPotentialConstantExpression() && CallStackDepth > 1) return false; if (NextCallIndex == 0) { // NextCallIndex has wrapped around. @@ -446,6 +530,15 @@ namespace { return (Frame->Index == CallIndex) ? Frame : 0; } + bool nextStep(const Stmt *S) { + if (!StepsLeft) { + Diag(S->getLocStart(), diag::note_constexpr_step_limit_exceeded); + return false; + } + --StepsLeft; + return true; + } + private: /// Add a diagnostic to the diagnostics list. PartialDiagnostic &addDiag(SourceLocation Loc, diag::kind DiagId) { @@ -462,22 +555,41 @@ namespace { OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes = 0) { - // If we have a prior diagnostic, it will be noting that the expression - // isn't a constant expression. This diagnostic is more important. - // FIXME: We might want to show both diagnostics to the user. if (EvalStatus.Diag) { + // If we have a prior diagnostic, it will be noting that the expression + // isn't a constant expression. This diagnostic is more important, + // unless we require this evaluation to produce a constant expression. + // + // FIXME: We might want to show both diagnostics to the user in + // EM_ConstantFold mode. + if (!EvalStatus.Diag->empty()) { + switch (EvalMode) { + case EM_ConstantFold: + case EM_IgnoreSideEffects: + case EM_EvaluateForOverflow: + if (!EvalStatus.HasSideEffects) + break; + // We've had side-effects; we want the diagnostic from them, not + // some later problem. + case EM_ConstantExpression: + case EM_PotentialConstantExpression: + HasActiveDiagnostic = false; + return OptionalDiagnostic(); + } + } + unsigned CallStackNotes = CallStackDepth - 1; unsigned Limit = Ctx.getDiagnostics().getConstexprBacktraceLimit(); if (Limit) CallStackNotes = std::min(CallStackNotes, Limit + 1); - if (CheckingPotentialConstantExpression) + if (checkingPotentialConstantExpression()) CallStackNotes = 0; HasActiveDiagnostic = true; EvalStatus.Diag->clear(); EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes); addDiag(Loc, DiagId); - if (!CheckingPotentialConstantExpression) + if (!checkingPotentialConstantExpression()) addCallStack(Limit); return OptionalDiagnostic(&(*EvalStatus.Diag)[0].second); } @@ -494,15 +606,17 @@ namespace { return OptionalDiagnostic(); } - bool getIntOverflowCheckMode() { return IntOverflowCheckMode; } - /// Diagnose that the evaluation does not produce a C++11 core constant /// expression. + /// + /// FIXME: Stop evaluating if we're in EM_ConstantExpression or + /// EM_PotentialConstantExpression mode and we produce one of these. template OptionalDiagnostic CCEDiag(LocArg Loc, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes = 0) { - // Don't override a previous diagnostic. + // Don't override a previous diagnostic. Don't bother collecting + // diagnostics if we're evaluating for overflow. if (!EvalStatus.Diag || !EvalStatus.Diag->empty()) { HasActiveDiagnostic = false; return OptionalDiagnostic(); @@ -525,30 +639,72 @@ namespace { } } + /// Should we continue evaluation after encountering a side-effect that we + /// couldn't model? + bool keepEvaluatingAfterSideEffect() { + switch (EvalMode) { + case EM_PotentialConstantExpression: + case EM_EvaluateForOverflow: + case EM_IgnoreSideEffects: + return true; + + case EM_ConstantExpression: + case EM_ConstantFold: + return false; + } + llvm_unreachable("Missed EvalMode case"); + } + + /// Note that we have had a side-effect, and determine whether we should + /// keep evaluating. + bool noteSideEffect() { + EvalStatus.HasSideEffects = true; + return keepEvaluatingAfterSideEffect(); + } + /// Should we continue evaluation as much as possible after encountering a - /// construct which can't be folded? + /// construct which can't be reduced to a value? bool keepEvaluatingAfterFailure() { - // 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()); + if (!StepsLeft) + return false; + + switch (EvalMode) { + case EM_PotentialConstantExpression: + case EM_EvaluateForOverflow: + return true; + + case EM_ConstantExpression: + case EM_ConstantFold: + case EM_IgnoreSideEffects: + return false; + } + llvm_unreachable("Missed EvalMode case"); } }; /// Object used to treat all foldable expressions as constant expressions. struct FoldConstant { + EvalInfo &Info; bool Enabled; - - explicit FoldConstant(EvalInfo &Info) - : Enabled(Info.EvalStatus.Diag && Info.EvalStatus.Diag->empty() && - !Info.EvalStatus.HasSideEffects) { - } - // Treat the value we've computed since this object was created as constant. - void Fold(EvalInfo &Info) { - if (Enabled && !Info.EvalStatus.Diag->empty() && + bool HadNoPriorDiags; + EvalInfo::EvaluationMode OldMode; + + explicit FoldConstant(EvalInfo &Info, bool Enabled) + : Info(Info), + Enabled(Enabled), + HadNoPriorDiags(Info.EvalStatus.Diag && + Info.EvalStatus.Diag->empty() && + !Info.EvalStatus.HasSideEffects), + OldMode(Info.EvalMode) { + if (Enabled && Info.EvalMode == EvalInfo::EM_ConstantExpression) + Info.EvalMode = EvalInfo::EM_ConstantFold; + } + void keepDiagnostics() { Enabled = false; } + ~FoldConstant() { + if (Enabled && HadNoPriorDiags && !Info.EvalStatus.Diag->empty() && !Info.EvalStatus.HasSideEffects) Info.EvalStatus.Diag->clear(); + Info.EvalMode = OldMode; } }; @@ -563,11 +719,50 @@ namespace { SmallVectorImpl *NewDiag = 0) : Info(Info), Old(Info.EvalStatus) { Info.EvalStatus.Diag = NewDiag; + // If we're speculatively evaluating, we may have skipped over some + // evaluations and missed out a side effect. + Info.EvalStatus.HasSideEffects = true; } ~SpeculativeEvaluationRAII() { Info.EvalStatus = Old; } }; + + /// RAII object wrapping a full-expression or block scope, and handling + /// the ending of the lifetime of temporaries created within it. + template + class ScopeRAII { + EvalInfo &Info; + unsigned OldStackSize; + public: + ScopeRAII(EvalInfo &Info) + : Info(Info), OldStackSize(Info.CleanupStack.size()) {} + ~ScopeRAII() { + // Body moved to a static method to encourage the compiler to inline away + // instances of this class. + cleanup(Info, OldStackSize); + } + private: + static void cleanup(EvalInfo &Info, unsigned OldStackSize) { + unsigned NewEnd = OldStackSize; + for (unsigned I = OldStackSize, N = Info.CleanupStack.size(); + I != N; ++I) { + if (IsFullExpression && Info.CleanupStack[I].isLifetimeExtended()) { + // Full-expression cleanup of a lifetime-extended temporary: nothing + // to do, just move this cleanup to the right place in the stack. + std::swap(Info.CleanupStack[I], Info.CleanupStack[NewEnd]); + ++NewEnd; + } else { + // End the lifetime of the object. + Info.CleanupStack[I].endLifetime(); + } + } + Info.CleanupStack.erase(Info.CleanupStack.begin() + NewEnd, + Info.CleanupStack.end()); + } + }; + typedef ScopeRAII BlockScopeRAII; + typedef ScopeRAII FullExpressionRAII; } bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E, @@ -610,32 +805,16 @@ CallStackFrame::~CallStackFrame() { Info.CurrentCall = Caller; } -/// Produce a string describing the given constexpr call. -static void describeCall(CallStackFrame *Frame, raw_ostream &Out) { - unsigned ArgIndex = 0; - bool IsMemberCall = isa(Frame->Callee) && - !isa(Frame->Callee) && - cast(Frame->Callee)->isInstance(); - - if (!IsMemberCall) - Out << *Frame->Callee << '('; - - for (FunctionDecl::param_const_iterator I = Frame->Callee->param_begin(), - E = Frame->Callee->param_end(); I != E; ++I, ++ArgIndex) { - if (ArgIndex > (unsigned)IsMemberCall) - Out << ", "; - - const ParmVarDecl *Param = *I; - const APValue &Arg = Frame->Arguments[ArgIndex]; - Arg.printPretty(Out, Frame->Info.Ctx, Param->getType()); - - if (ArgIndex == 0 && IsMemberCall) - Out << "->" << *Frame->Callee << '('; - } - - Out << ')'; +APValue &CallStackFrame::createTemporary(const void *Key, + bool IsLifetimeExtended) { + APValue &Result = Temporaries[Key]; + assert(Result.isUninit() && "temporary created multiple times"); + Info.CleanupStack.push_back(Cleanup(&Result, IsLifetimeExtended)); + return Result; } +static void describeCall(CallStackFrame *Frame, raw_ostream &Out); + void EvalInfo::addCallStack(unsigned Limit) { // Determine which calls to skip, if any. unsigned ActiveCalls = CallStackDepth - 1; @@ -884,19 +1063,11 @@ namespace { return false; return LHS.Path == RHS.Path; } - - /// Kinds of constant expression checking, for diagnostics. - enum CheckConstantExpressionKind { - CCEK_Constant, ///< A normal constant. - CCEK_ReturnValue, ///< A constexpr function return value. - CCEK_MemberInit ///< A constexpr constructor mem-initializer. - }; } static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E); static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, const Expr *E, - CheckConstantExpressionKind CCEK = CCEK_Constant, bool AllowNonLiteralTypes = false); static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info); static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info); @@ -908,23 +1079,66 @@ static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, EvalInfo &Info); static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info); static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo &Info); +static bool EvaluateAtomic(const Expr *E, APValue &Result, EvalInfo &Info); //===----------------------------------------------------------------------===// // Misc utilities //===----------------------------------------------------------------------===// +/// Produce a string describing the given constexpr call. +static void describeCall(CallStackFrame *Frame, raw_ostream &Out) { + unsigned ArgIndex = 0; + bool IsMemberCall = isa(Frame->Callee) && + !isa(Frame->Callee) && + cast(Frame->Callee)->isInstance(); + + if (!IsMemberCall) + Out << *Frame->Callee << '('; + + if (Frame->This && IsMemberCall) { + APValue Val; + Frame->This->moveInto(Val); + Val.printPretty(Out, Frame->Info.Ctx, + Frame->This->Designator.MostDerivedType); + // FIXME: Add parens around Val if needed. + Out << "->" << *Frame->Callee << '('; + IsMemberCall = false; + } + + for (FunctionDecl::param_const_iterator I = Frame->Callee->param_begin(), + E = Frame->Callee->param_end(); I != E; ++I, ++ArgIndex) { + if (ArgIndex > (unsigned)IsMemberCall) + Out << ", "; + + const ParmVarDecl *Param = *I; + const APValue &Arg = Frame->Arguments[ArgIndex]; + Arg.printPretty(Out, Frame->Info.Ctx, Param->getType()); + + if (ArgIndex == 0 && IsMemberCall) + Out << "->" << *Frame->Callee << '('; + } + + Out << ')'; +} + /// Evaluate an expression to see if it had side-effects, and discard its /// result. /// \return \c true if the caller should keep evaluating. static bool EvaluateIgnoredValue(EvalInfo &Info, const Expr *E) { APValue Scratch; - if (!Evaluate(Scratch, Info, E)) { - Info.EvalStatus.HasSideEffects = true; - return Info.keepEvaluatingAfterFailure(); - } + if (!Evaluate(Scratch, Info, E)) + // We don't need the value, but we might have skipped a side effect here. + return Info.noteSideEffect(); return true; } +/// Sign- or zero-extend a value to 64 bits. If it's already 64 bits, just +/// return its existing value. +static int64_t getExtValue(const APSInt &Value) { + return Value.isSigned() ? Value.getSExtValue() + : static_cast(Value.getZExtValue()); +} + /// Should this call expression be treated as a string literal? static bool IsStringLiteralCall(const CallExpr *E) { unsigned Builtin = E->isBuiltinCall(); @@ -956,6 +1170,10 @@ static bool IsGlobalLValue(APValue::LValueBase B) { const CompoundLiteralExpr *CLE = cast(E); return CLE->isFileScope() && CLE->isLValue(); } + case Expr::MaterializeTemporaryExprClass: + // A materialized temporary might have been lifetime-extended to static + // storage duration. + return cast(E)->getStorageDuration() == SD_Static; // A string literal has static storage duration. case Expr::StringLiteralClass: case Expr::PredefinedExprClass: @@ -1020,7 +1238,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, // Don't allow references to temporaries to escape. return false; } - assert((Info.CheckingPotentialConstantExpression || + assert((Info.checkingPotentialConstantExpression() || LVal.getLValueCallIndex() == 0) && "have call index for global lvalue"); @@ -1057,10 +1275,18 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, /// Check that this core constant expression is of literal type, and if not, /// produce an appropriate diagnostic. -static bool CheckLiteralType(EvalInfo &Info, const Expr *E) { +static bool CheckLiteralType(EvalInfo &Info, const Expr *E, + const LValue *This = 0) { if (!E->isRValue() || E->getType()->isLiteralType(Info.Ctx)) return true; + // C++1y: A constant initializer for an object o [...] may also invoke + // constexpr constructors for o and its subobjects even if those objects + // are of non-literal class types. + if (Info.getLangOpts().CPlusPlus1y && This && + Info.EvaluatingDecl == This->getLValueBase()) + return true; + // Prvalue constant expressions must be of literal types. if (Info.getLangOpts().CPlusPlus11) Info.Diag(E, diag::note_constexpr_nonliteral) @@ -1075,6 +1301,12 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E) { /// check that the expression is of literal type. static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, QualType Type, const APValue &Value) { + if (Value.isUninit()) { + Info.Diag(DiagLoc, diag::note_constexpr_uninitialized) + << true << Type; + return false; + } + // Core issue 1454: For a literal constant expression of array or class type, // each subobject of its value shall have been initialized by a constant // expression. @@ -1129,7 +1361,10 @@ const ValueDecl *GetLValueBaseDecl(const LValue &LVal) { } static bool IsLiteralLValue(const LValue &Value) { - return Value.Base.dyn_cast() && !Value.CallIndex; + if (Value.CallIndex) + return false; + const Expr *E = Value.Base.dyn_cast(); + return E && !isa(E); } static bool IsWeakLValue(const LValue &Value) { @@ -1252,6 +1487,27 @@ static bool HandleIntToFloatCast(EvalInfo &Info, const Expr *E, return true; } +static bool truncateBitfieldValue(EvalInfo &Info, const Expr *E, + APValue &Value, const FieldDecl *FD) { + assert(FD->isBitField() && "truncateBitfieldValue on non-bitfield"); + + if (!Value.isInt()) { + // Trying to store a pointer-cast-to-integer into a bitfield. + // FIXME: In this case, we should provide the diagnostic for casting + // a pointer to an integer. + assert(Value.isLValue() && "integral value neither int nor lvalue?"); + Info.Diag(E); + return false; + } + + APSInt &Int = Value.getInt(); + unsigned OldBitWidth = Int.getBitWidth(); + unsigned NewBitWidth = FD->getBitWidthValue(Info.Ctx); + if (NewBitWidth < OldBitWidth) + Int = Int.trunc(NewBitWidth).extend(OldBitWidth); + return true; +} + static bool EvalAndBitcastToAPInt(EvalInfo &Info, const Expr *E, llvm::APInt &Res) { APValue SVal; @@ -1299,6 +1555,155 @@ static bool EvalAndBitcastToAPInt(EvalInfo &Info, const Expr *E, return false; } +/// Perform the given integer operation, which is known to need at most BitWidth +/// bits, and check for overflow in the original type (if that type was not an +/// unsigned type). +template +static APSInt CheckedIntArithmetic(EvalInfo &Info, const Expr *E, + const APSInt &LHS, const APSInt &RHS, + unsigned BitWidth, Operation Op) { + if (LHS.isUnsigned()) + return Op(LHS, RHS); + + APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false); + APSInt Result = Value.trunc(LHS.getBitWidth()); + if (Result.extend(BitWidth) != Value) { + if (Info.checkingForOverflow()) + 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; +} + +/// Perform the given binary integer operation. +static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS, + BinaryOperatorKind Opcode, APSInt RHS, + APSInt &Result) { + switch (Opcode) { + default: + Info.Diag(E); + return false; + case BO_Mul: + Result = CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() * 2, + std::multiplies()); + return true; + case BO_Add: + Result = CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1, + std::plus()); + return true; + case BO_Sub: + Result = CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1, + std::minus()); + return true; + case BO_And: Result = LHS & RHS; return true; + case BO_Xor: Result = LHS ^ RHS; return true; + case BO_Or: Result = LHS | RHS; return true; + case BO_Div: + case BO_Rem: + if (RHS == 0) { + Info.Diag(E, diag::note_expr_divide_by_zero); + return false; + } + // Check for overflow case: INT_MIN / -1 or INT_MIN % -1. + if (RHS.isNegative() && RHS.isAllOnesValue() && + LHS.isSigned() && LHS.isMinSignedValue()) + HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1), E->getType()); + Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS); + return true; + case BO_Shl: { + if (Info.getLangOpts().OpenCL) + // OpenCL 6.3j: shift values are effectively % word size of LHS. + RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), + static_cast(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. + Info.CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; + RHS = -RHS; + goto shift_right; + } + shift_left: + // C++11 [expr.shift]p1: Shift width must be less than the bit width of + // the shifted type. + unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1); + if (SA != RHS) { + Info.CCEDiag(E, diag::note_constexpr_large_shift) + << RHS << E->getType() << LHS.getBitWidth(); + } else if (LHS.isSigned()) { + // C++11 [expr.shift]p2: A signed left shift must have a non-negative + // operand, and must not overflow the corresponding unsigned type. + if (LHS.isNegative()) + Info.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS; + else if (LHS.countLeadingZeros() < SA) + Info.CCEDiag(E, diag::note_constexpr_lshift_discards); + } + Result = LHS << SA; + return true; + } + case BO_Shr: { + if (Info.getLangOpts().OpenCL) + // OpenCL 6.3j: shift values are effectively % word size of LHS. + RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), + static_cast(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. + Info.CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; + RHS = -RHS; + goto shift_left; + } + shift_right: + // C++11 [expr.shift]p1: Shift width must be less than the bit width of the + // shifted type. + unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1); + if (SA != RHS) + Info.CCEDiag(E, diag::note_constexpr_large_shift) + << RHS << E->getType() << LHS.getBitWidth(); + Result = LHS >> SA; + return true; + } + + case BO_LT: Result = LHS < RHS; return true; + case BO_GT: Result = LHS > RHS; return true; + case BO_LE: Result = LHS <= RHS; return true; + case BO_GE: Result = LHS >= RHS; return true; + case BO_EQ: Result = LHS == RHS; return true; + case BO_NE: Result = LHS != RHS; return true; + } +} + +/// Perform the given binary floating-point operation, in-place, on LHS. +static bool handleFloatFloatBinOp(EvalInfo &Info, const Expr *E, + APFloat &LHS, BinaryOperatorKind Opcode, + const APFloat &RHS) { + switch (Opcode) { + default: + Info.Diag(E); + return false; + case BO_Mul: + LHS.multiply(RHS, APFloat::rmNearestTiesToEven); + break; + case BO_Add: + LHS.add(RHS, APFloat::rmNearestTiesToEven); + break; + case BO_Sub: + LHS.subtract(RHS, APFloat::rmNearestTiesToEven); + break; + case BO_Div: + LHS.divide(RHS, APFloat::rmNearestTiesToEven); + break; + } + + if (LHS.isInfinity() || LHS.isNaN()) + Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) << LHS.isNaN(); + return true; +} + /// Cast an lvalue referring to a base subobject to a derived class, by /// truncating the lvalue's path to the given length. static bool CastToDerivedClass(EvalInfo &Info, const Expr *E, LValue &Result, @@ -1369,6 +1774,19 @@ static bool HandleLValueBase(EvalInfo &Info, const Expr *E, LValue &Obj, return true; } +static bool HandleLValueBasePath(EvalInfo &Info, const CastExpr *E, + QualType Type, LValue &Result) { + for (CastExpr::path_const_iterator PathI = E->path_begin(), + PathE = E->path_end(); + PathI != PathE; ++PathI) { + if (!HandleLValueBase(Info, E, Result, Type->getAsCXXRecordDecl(), + *PathI)) + return false; + Type = (*PathI)->getType(); + } + return true; +} + /// Update LVal to refer to the given field, which must be a member of the type /// currently described by LVal. static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal, @@ -1470,7 +1888,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, if (const ParmVarDecl *PVD = dyn_cast(VD)) { // Assume arguments of a potential constant expression are unknown // constant expressions. - if (Info.CheckingPotentialConstantExpression) + if (Info.checkingPotentialConstantExpression()) return false; if (!Frame || !Frame->Arguments) { Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); @@ -1482,11 +1900,9 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, // If this is a local variable, dig out its value. if (Frame) { - Result = &Frame->Temporaries[VD]; - // If we've carried on past an unevaluatable local variable initializer, - // we can't go any further. This can happen during potential constant - // expression checking. - return !Result->isUninit(); + Result = Frame->getTemporary(VD); + assert(Result && "missing value for local variable"); + return true; } // Dig out the initializer, and use the declaration which it's attached to. @@ -1494,16 +1910,16 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, if (!Init || Init->isValueDependent()) { // If we're checking a potential constant expression, the variable could be // initialized later. - if (!Info.CheckingPotentialConstantExpression) + if (!Info.checkingPotentialConstantExpression()) Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); return false; } // If we're currently evaluating the initializer of this declaration, use that // in-flight value. - if (Info.EvaluatingDecl == VD) { + if (Info.EvaluatingDecl.dyn_cast() == VD) { Result = Info.EvaluatingDeclValue; - return !Result->isUninit(); + return true; } // Never evaluate the initializer of a weak variable. We can't be sure that @@ -1615,7 +2031,7 @@ static void expandArray(APValue &Array, unsigned Index) { Array.swap(NewValue); } -/// Kinds of access we can perform on an object. +/// Kinds of access we can perform on an object, for diagnostics. enum AccessKinds { AK_Read, AK_Assign, @@ -1637,7 +2053,7 @@ struct CompleteObject { assert(Value && "missing value for complete object"); } - operator bool() const { return Value; } + LLVM_EXPLICIT operator bool() const { return Value; } }; /// Find the designated sub-object of an rvalue. @@ -1656,16 +2072,33 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, Info.Diag(E); return handler.failed(); } - if (Sub.Entries.empty()) - return handler.found(*Obj.Value, Obj.Type); - if (Info.CheckingPotentialConstantExpression && Obj.Value->isUninit()) - // This object might be initialized later. - return handler.failed(); APValue *O = Obj.Value; QualType ObjType = Obj.Type; + const FieldDecl *LastField = 0; + // Walk the designator's path to find the subobject. - for (unsigned I = 0, N = Sub.Entries.size(); I != N; ++I) { + for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) { + if (O->isUninit()) { + if (!Info.checkingPotentialConstantExpression()) + Info.Diag(E, diag::note_constexpr_access_uninit) << handler.AccessKind; + return handler.failed(); + } + + if (I == N) { + if (!handler.found(*O, ObjType)) + return false; + + // If we modified a bit-field, truncate it to the right width. + if (handler.AccessKind != AK_Read && + LastField && LastField->isBitField() && + !truncateBitfieldValue(Info, E, *O, LastField)) + return false; + + return true; + } + + LastField = 0; if (ObjType->isArrayType()) { // Next subobject is an array element. const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(ObjType); @@ -1767,6 +2200,8 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, } return handler.failed(); } + + LastField = Field; } else { // Next subobject is a base class. const CXXRecordDecl *Derived = ObjType->getAsCXXRecordDecl(); @@ -1778,15 +2213,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, if (WasConstQualified) ObjType.addConst(); } - - if (O->isUninit()) { - if (!Info.CheckingPotentialConstantExpression) - Info.Diag(E, diag::note_constexpr_access_uninit) << handler.AccessKind; - return handler.failed(); - } } - - return handler.found(*O, ObjType); } namespace { @@ -1963,9 +2390,6 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, NoteLValueLocation(Info, LVal.Base); return CompleteObject(); } - } else if (AK != AK_Read) { - Info.Diag(E, diag::note_constexpr_modify_global); - return CompleteObject(); } // C++11 DR1311: An lvalue-to-rvalue conversion on a volatile-qualified type @@ -1983,7 +2407,7 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, // Compute value storage location and type of base object. APValue *BaseVal = 0; - QualType BaseType; + QualType BaseType = getType(LVal.Base); if (const ValueDecl *D = LVal.Base.dyn_cast()) { // In C++98, const, non-volatile integers initialized with ICEs are ICEs. @@ -2004,7 +2428,6 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, } // Accesses of volatile-qualified objects are not allowed. - BaseType = VD->getType(); if (BaseType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) { Info.Diag(E, diag::note_constexpr_access_volatile_obj, 1) @@ -2019,8 +2442,16 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, // Unless we're looking at a local variable or argument in a constexpr call, // the variable we're reading must be const. if (!Frame) { - assert(AK == AK_Read && "can't modify non-local"); - if (VD->isConstexpr()) { + if (Info.getLangOpts().CPlusPlus1y && + VD == Info.EvaluatingDecl.dyn_cast()) { + // OK, we can read and modify an object if we're in the process of + // evaluating its initializer, because its lifetime began in this + // evaluation. + } else if (AK != AK_Read) { + // All the remaining cases only permit reading. + Info.Diag(E, diag::note_constexpr_modify_global); + return CompleteObject(); + } else if (VD->isConstexpr()) { // OK, we can read this variable. } else if (BaseType->isIntegralOrEnumerationType()) { if (!BaseType.isConstQualified()) { @@ -2060,12 +2491,45 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, const Expr *Base = LVal.Base.dyn_cast(); if (!Frame) { - Info.Diag(E); - return CompleteObject(); - } + if (const MaterializeTemporaryExpr *MTE = + dyn_cast(Base)) { + assert(MTE->getStorageDuration() == SD_Static && + "should have a frame for a non-global materialized temporary"); + + // Per C++1y [expr.const]p2: + // an lvalue-to-rvalue conversion [is not allowed unless it applies to] + // - a [...] glvalue of integral or enumeration type that refers to + // a non-volatile const object [...] + // [...] + // - a [...] glvalue of literal type that refers to a non-volatile + // object whose lifetime began within the evaluation of e. + // + // C++11 misses the 'began within the evaluation of e' check and + // instead allows all temporaries, including things like: + // int &&r = 1; + // int x = ++r; + // constexpr int k = r; + // Therefore we use the C++1y rules in C++11 too. + const ValueDecl *VD = Info.EvaluatingDecl.dyn_cast(); + const ValueDecl *ED = MTE->getExtendingDecl(); + if (!(BaseType.isConstQualified() && + BaseType->isIntegralOrEnumerationType()) && + !(VD && VD->getCanonicalDecl() == ED->getCanonicalDecl())) { + Info.Diag(E, diag::note_constexpr_access_static_temporary, 1) << AK; + Info.Note(MTE->getExprLoc(), diag::note_constexpr_temporary_here); + return CompleteObject(); + } - BaseType = Base->getType(); - BaseVal = &Frame->Temporaries[Base]; + BaseVal = Info.Ctx.getMaterializedTemporaryValue(MTE, false); + assert(BaseVal && "got reference to unevaluated temporary"); + } else { + Info.Diag(E); + return CompleteObject(); + } + } else { + BaseVal = Frame->getTemporary(Base); + assert(BaseVal && "missing value for temporary"); + } // Volatile temporary objects cannot be accessed in constant expressions. if (BaseType.isVolatileQualified()) { @@ -2080,10 +2544,22 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, } } - // In C++1y, we can't safely access any mutable state when checking a - // potential constant expression. + // During the construction of an object, it is not yet 'const'. + // FIXME: We don't set up EvaluatingDecl for local variables or temporaries, + // and this doesn't do quite the right thing for const subobjects of the + // object under construction. + if (LVal.getLValueBase() == Info.EvaluatingDecl) { + BaseType = Info.Ctx.getCanonicalType(BaseType); + BaseType.removeLocalConst(); + } + + // In C++1y, we can't safely access any mutable state when we might be + // evaluating after an unmodeled side effect or an evaluation failure. + // + // FIXME: Not all local state is mutable. Allow local constant subobjects + // to be read here (but take care with 'mutable' fields). if (Frame && Info.getLangOpts().CPlusPlus1y && - Info.CheckingPotentialConstantExpression) + (Info.EvalStatus.HasSideEffects || Info.keepEvaluatingAfterFailure())) return CompleteObject(); return CompleteObject(BaseVal, BaseType); @@ -2159,6 +2635,124 @@ static bool isOverflowingIntegerType(ASTContext &Ctx, QualType T) { } namespace { +struct CompoundAssignSubobjectHandler { + EvalInfo &Info; + const Expr *E; + QualType PromotedLHSType; + BinaryOperatorKind Opcode; + const APValue &RHS; + + static const AccessKinds AccessKind = AK_Assign; + + typedef bool result_type; + + bool checkConst(QualType QT) { + // Assigning to a const object has undefined behavior. + if (QT.isConstQualified()) { + Info.Diag(E, diag::note_constexpr_modify_const_type) << QT; + return false; + } + return true; + } + + bool failed() { return false; } + bool found(APValue &Subobj, QualType SubobjType) { + switch (Subobj.getKind()) { + case APValue::Int: + return found(Subobj.getInt(), SubobjType); + case APValue::Float: + return found(Subobj.getFloat(), SubobjType); + case APValue::ComplexInt: + case APValue::ComplexFloat: + // FIXME: Implement complex compound assignment. + Info.Diag(E); + return false; + case APValue::LValue: + return foundPointer(Subobj, SubobjType); + default: + // FIXME: can this happen? + Info.Diag(E); + return false; + } + } + bool found(APSInt &Value, QualType SubobjType) { + if (!checkConst(SubobjType)) + return false; + + if (!SubobjType->isIntegerType() || !RHS.isInt()) { + // We don't support compound assignment on integer-cast-to-pointer + // values. + Info.Diag(E); + return false; + } + + APSInt LHS = HandleIntToIntCast(Info, E, PromotedLHSType, + SubobjType, Value); + if (!handleIntIntBinOp(Info, E, LHS, Opcode, RHS.getInt(), LHS)) + return false; + Value = HandleIntToIntCast(Info, E, SubobjType, PromotedLHSType, LHS); + return true; + } + bool found(APFloat &Value, QualType SubobjType) { + return checkConst(SubobjType) && + HandleFloatToFloatCast(Info, E, SubobjType, PromotedLHSType, + Value) && + handleFloatFloatBinOp(Info, E, Value, Opcode, RHS.getFloat()) && + HandleFloatToFloatCast(Info, E, PromotedLHSType, SubobjType, Value); + } + bool foundPointer(APValue &Subobj, QualType SubobjType) { + if (!checkConst(SubobjType)) + return false; + + QualType PointeeType; + if (const PointerType *PT = SubobjType->getAs()) + PointeeType = PT->getPointeeType(); + + if (PointeeType.isNull() || !RHS.isInt() || + (Opcode != BO_Add && Opcode != BO_Sub)) { + Info.Diag(E); + return false; + } + + int64_t Offset = getExtValue(RHS.getInt()); + if (Opcode == BO_Sub) + Offset = -Offset; + + LValue LVal; + LVal.setFrom(Info.Ctx, Subobj); + if (!HandleLValueArrayAdjustment(Info, E, LVal, PointeeType, Offset)) + return false; + LVal.moveInto(Subobj); + return true; + } + bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) { + llvm_unreachable("shouldn't encounter string elements here"); + } +}; +} // end anonymous namespace + +const AccessKinds CompoundAssignSubobjectHandler::AccessKind; + +/// Perform a compound assignment of LVal = RVal. +static bool handleCompoundAssignment( + EvalInfo &Info, const Expr *E, + const LValue &LVal, QualType LValType, QualType PromotedLValType, + BinaryOperatorKind Opcode, const APValue &RVal) { + if (LVal.Designator.Invalid) + return false; + + if (!Info.getLangOpts().CPlusPlus1y) { + Info.Diag(E); + return false; + } + + CompleteObject Obj = findCompleteObject(Info, E, AK_Assign, LVal, LValType); + CompoundAssignSubobjectHandler Handler = { Info, E, PromotedLValType, Opcode, + RVal }; + return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler); +} + +namespace { struct IncDecSubobjectHandler { EvalInfo &Info; const Expr *E; @@ -2326,54 +2920,53 @@ static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object, /// lvalue referring to the result. /// /// \param Info - Information about the ongoing evaluation. -/// \param BO - The member pointer access operation. -/// \param LV - Filled in with a reference to the resulting object. +/// \param LV - An lvalue referring to the base of the member pointer. +/// \param RHS - The member pointer expression. /// \param IncludeMember - Specifies whether the member itself is included in /// the resulting LValue subobject designator. This is not possible when /// creating a bound member function. /// \return The field or method declaration to which the member pointer refers, /// or 0 if evaluation fails. static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, - const BinaryOperator *BO, + QualType LVType, LValue &LV, + const Expr *RHS, bool IncludeMember = true) { - assert(BO->getOpcode() == BO_PtrMemD || BO->getOpcode() == BO_PtrMemI); - - bool EvalObjOK = EvaluateObjectArgument(Info, BO->getLHS(), LV); - if (!EvalObjOK && !Info.keepEvaluatingAfterFailure()) - return 0; - MemberPtr MemPtr; - if (!EvaluateMemberPointer(BO->getRHS(), MemPtr, Info)) + if (!EvaluateMemberPointer(RHS, MemPtr, Info)) return 0; // C++11 [expr.mptr.oper]p6: If the second operand is the null pointer to // member value, the behavior is undefined. - if (!MemPtr.getDecl()) - return 0; - - if (!EvalObjOK) + if (!MemPtr.getDecl()) { + // FIXME: Specific diagnostic. + Info.Diag(RHS); return 0; + } if (MemPtr.isDerivedMember()) { // This is a member of some derived class. Truncate LV appropriately. // The end of the derived-to-base path for the base object must match the // derived-to-base path for the member pointer. if (LV.Designator.MostDerivedPathLength + MemPtr.Path.size() > - LV.Designator.Entries.size()) + LV.Designator.Entries.size()) { + Info.Diag(RHS); return 0; + } unsigned PathLengthToMember = LV.Designator.Entries.size() - MemPtr.Path.size(); for (unsigned I = 0, N = MemPtr.Path.size(); I != N; ++I) { const CXXRecordDecl *LVDecl = getAsBaseClass( LV.Designator.Entries[PathLengthToMember + I]); const CXXRecordDecl *MPDecl = MemPtr.Path[I]; - if (LVDecl->getCanonicalDecl() != MPDecl->getCanonicalDecl()) + if (LVDecl->getCanonicalDecl() != MPDecl->getCanonicalDecl()) { + Info.Diag(RHS); return 0; + } } // Truncate the lvalue to the appropriate derived class. - if (!CastToDerivedClass(Info, BO, LV, MemPtr.getContainingRecord(), + if (!CastToDerivedClass(Info, RHS, LV, MemPtr.getContainingRecord(), PathLengthToMember)) return 0; } else if (!MemPtr.Path.empty()) { @@ -2382,7 +2975,6 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, MemPtr.Path.size() + IncludeMember); // Walk down to the appropriate base class. - QualType LVType = BO->getLHS()->getType(); if (const PointerType *PT = LVType->getAs()) LVType = PT->getPointeeType(); const CXXRecordDecl *RD = LVType->getAsCXXRecordDecl(); @@ -2390,23 +2982,24 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, // The first class in the path is that of the lvalue. for (unsigned I = 1, N = MemPtr.Path.size(); I != N; ++I) { const CXXRecordDecl *Base = MemPtr.Path[N - I - 1]; - if (!HandleLValueDirectBase(Info, BO, LV, RD, Base)) + if (!HandleLValueDirectBase(Info, RHS, LV, RD, Base)) return 0; RD = Base; } // Finally cast to the class containing the member. - if (!HandleLValueDirectBase(Info, BO, LV, RD, MemPtr.getContainingRecord())) + if (!HandleLValueDirectBase(Info, RHS, LV, RD, + MemPtr.getContainingRecord())) return 0; } // Add the member. Note that we cannot build bound member functions here. if (IncludeMember) { if (const FieldDecl *FD = dyn_cast(MemPtr.getDecl())) { - if (!HandleLValueMember(Info, BO, LV, FD)) + if (!HandleLValueMember(Info, RHS, LV, FD)) return 0; } else if (const IndirectFieldDecl *IFD = dyn_cast(MemPtr.getDecl())) { - if (!HandleLValueIndirectMember(Info, BO, LV, IFD)) + if (!HandleLValueIndirectMember(Info, RHS, LV, IFD)) return 0; } else { llvm_unreachable("can't construct reference to bound member function"); @@ -2416,6 +3009,24 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, return MemPtr.getDecl(); } +static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, + const BinaryOperator *BO, + LValue &LV, + bool IncludeMember = true) { + assert(BO->getOpcode() == BO_PtrMemD || BO->getOpcode() == BO_PtrMemI); + + if (!EvaluateObjectArgument(Info, BO->getLHS(), LV)) { + if (Info.keepEvaluatingAfterFailure()) { + MemberPtr MemPtr; + EvaluateMemberPointer(BO->getRHS(), MemPtr, Info); + } + return 0; + } + + return HandleMemberPointerAccess(Info, BO->getLHS()->getType(), LV, + BO->getRHS(), IncludeMember); +} + /// HandleBaseToDerivedCast - Apply the given base-to-derived cast operation on /// the provided lvalue, which currently refers to the base object. static bool HandleBaseToDerivedCast(EvalInfo &Info, const CastExpr *E, @@ -2465,7 +3076,9 @@ enum EvalStmtResult { /// Hit a 'continue' statement. ESR_Continue, /// Hit a 'break' statement. - ESR_Break + ESR_Break, + /// Still scanning for 'case' or 'default' statement. + ESR_CaseNotFound }; } @@ -2477,7 +3090,14 @@ static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { LValue Result; Result.set(VD, Info.CurrentCall->Index); - APValue &Val = Info.CurrentCall->Temporaries[VD]; + APValue &Val = Info.CurrentCall->createTemporary(VD, true); + + if (!VD->getInit()) { + Info.Diag(D->getLocStart(), diag::note_constexpr_uninitialized) + << false << VD->getType(); + Val = APValue(); + return false; + } if (!EvaluateInPlace(Val, Info, Result, VD->getInit())) { // Wipe out any partially-computed value, to allow tracking that this @@ -2493,18 +3113,21 @@ static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { /// Evaluate a condition (either a variable declaration or an expression). static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl, const Expr *Cond, bool &Result) { + FullExpressionRAII Scope(Info); if (CondDecl && !EvaluateDecl(Info, CondDecl)) return false; return EvaluateAsBooleanCondition(Cond, Result, Info); } static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, - const Stmt *S); + const Stmt *S, const SwitchCase *SC = 0); /// Evaluate the body of a loop, and translate the result as appropriate. static EvalStmtResult EvaluateLoopBody(APValue &Result, EvalInfo &Info, - const Stmt *Body) { - switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, Body)) { + const Stmt *Body, + const SwitchCase *Case = 0) { + BlockScopeRAII Scope(Info); + switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, Body, Case)) { case ESR_Break: return ESR_Succeeded; case ESR_Succeeded: @@ -2512,21 +3135,149 @@ static EvalStmtResult EvaluateLoopBody(APValue &Result, EvalInfo &Info, return ESR_Continue; case ESR_Failed: case ESR_Returned: + case ESR_CaseNotFound: return ESR; } llvm_unreachable("Invalid EvalStmtResult!"); } +/// Evaluate a switch statement. +static EvalStmtResult EvaluateSwitch(APValue &Result, EvalInfo &Info, + const SwitchStmt *SS) { + BlockScopeRAII Scope(Info); + + // Evaluate the switch condition. + APSInt Value; + { + FullExpressionRAII Scope(Info); + if (SS->getConditionVariable() && + !EvaluateDecl(Info, SS->getConditionVariable())) + return ESR_Failed; + if (!EvaluateInteger(SS->getCond(), Value, Info)) + return ESR_Failed; + } + + // Find the switch case corresponding to the value of the condition. + // FIXME: Cache this lookup. + const SwitchCase *Found = 0; + for (const SwitchCase *SC = SS->getSwitchCaseList(); SC; + SC = SC->getNextSwitchCase()) { + if (isa(SC)) { + Found = SC; + continue; + } + + const CaseStmt *CS = cast(SC); + APSInt LHS = CS->getLHS()->EvaluateKnownConstInt(Info.Ctx); + APSInt RHS = CS->getRHS() ? CS->getRHS()->EvaluateKnownConstInt(Info.Ctx) + : LHS; + if (LHS <= Value && Value <= RHS) { + Found = SC; + break; + } + } + + if (!Found) + return ESR_Succeeded; + + // Search the switch body for the switch case and evaluate it from there. + switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, SS->getBody(), Found)) { + case ESR_Break: + return ESR_Succeeded; + case ESR_Succeeded: + case ESR_Continue: + case ESR_Failed: + case ESR_Returned: + return ESR; + case ESR_CaseNotFound: + // This can only happen if the switch case is nested within a statement + // expression. We have no intention of supporting that. + Info.Diag(Found->getLocStart(), diag::note_constexpr_stmt_expr_unsupported); + return ESR_Failed; + } + llvm_unreachable("Invalid EvalStmtResult!"); +} + // Evaluate a statement. static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, - const Stmt *S) { - // FIXME: Mark all temporaries in the current frame as destroyed at - // the end of each full-expression. + const Stmt *S, const SwitchCase *Case) { + if (!Info.nextStep(S)) + return ESR_Failed; + + // If we're hunting down a 'case' or 'default' label, recurse through + // substatements until we hit the label. + if (Case) { + // FIXME: We don't start the lifetime of objects whose initialization we + // jump over. However, such objects must be of class type with a trivial + // default constructor that initialize all subobjects, so must be empty, + // so this almost never matters. + switch (S->getStmtClass()) { + case Stmt::CompoundStmtClass: + // FIXME: Precompute which substatement of a compound statement we + // would jump to, and go straight there rather than performing a + // linear scan each time. + case Stmt::LabelStmtClass: + case Stmt::AttributedStmtClass: + case Stmt::DoStmtClass: + break; + + case Stmt::CaseStmtClass: + case Stmt::DefaultStmtClass: + if (Case == S) + Case = 0; + break; + + case Stmt::IfStmtClass: { + // FIXME: Precompute which side of an 'if' we would jump to, and go + // straight there rather than scanning both sides. + const IfStmt *IS = cast(S); + + // Wrap the evaluation in a block scope, in case it's a DeclStmt + // preceded by our switch label. + BlockScopeRAII Scope(Info); + + EvalStmtResult ESR = EvaluateStmt(Result, Info, IS->getThen(), Case); + if (ESR != ESR_CaseNotFound || !IS->getElse()) + return ESR; + return EvaluateStmt(Result, Info, IS->getElse(), Case); + } + + case Stmt::WhileStmtClass: { + EvalStmtResult ESR = + EvaluateLoopBody(Result, Info, cast(S)->getBody(), Case); + if (ESR != ESR_Continue) + return ESR; + break; + } + + case Stmt::ForStmtClass: { + const ForStmt *FS = cast(S); + EvalStmtResult ESR = + EvaluateLoopBody(Result, Info, FS->getBody(), Case); + if (ESR != ESR_Continue) + return ESR; + if (FS->getInc()) { + FullExpressionRAII IncScope(Info); + if (!EvaluateIgnoredValue(Info, FS->getInc())) + return ESR_Failed; + } + break; + } + + case Stmt::DeclStmtClass: + // FIXME: If the variable has initialization that can't be jumped over, + // bail out of any immediately-surrounding compound-statement too. + default: + return ESR_CaseNotFound; + } + } + switch (S->getStmtClass()) { default: if (const Expr *E = dyn_cast(S)) { // Don't bother evaluating beyond an expression-statement which couldn't // be evaluated. + FullExpressionRAII Scope(Info); if (!EvaluateIgnoredValue(Info, E)) return ESR_Failed; return ESR_Succeeded; @@ -2541,34 +3292,45 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, case Stmt::DeclStmtClass: { const DeclStmt *DS = cast(S); for (DeclStmt::const_decl_iterator DclIt = DS->decl_begin(), - DclEnd = DS->decl_end(); DclIt != DclEnd; ++DclIt) + DclEnd = DS->decl_end(); DclIt != DclEnd; ++DclIt) { + // Each declaration initialization is its own full-expression. + // FIXME: This isn't quite right; if we're performing aggregate + // initialization, each braced subexpression is its own full-expression. + FullExpressionRAII Scope(Info); if (!EvaluateDecl(Info, *DclIt) && !Info.keepEvaluatingAfterFailure()) return ESR_Failed; + } return ESR_Succeeded; } case Stmt::ReturnStmtClass: { const Expr *RetExpr = cast(S)->getRetValue(); + FullExpressionRAII Scope(Info); if (RetExpr && !Evaluate(Result, Info, RetExpr)) return ESR_Failed; return ESR_Returned; } case Stmt::CompoundStmtClass: { + BlockScopeRAII Scope(Info); + const CompoundStmt *CS = cast(S); for (CompoundStmt::const_body_iterator BI = CS->body_begin(), BE = CS->body_end(); BI != BE; ++BI) { - EvalStmtResult ESR = EvaluateStmt(Result, Info, *BI); - if (ESR != ESR_Succeeded) + EvalStmtResult ESR = EvaluateStmt(Result, Info, *BI, Case); + if (ESR == ESR_Succeeded) + Case = 0; + else if (ESR != ESR_CaseNotFound) return ESR; } - return ESR_Succeeded; + return Case ? ESR_CaseNotFound : ESR_Succeeded; } case Stmt::IfStmtClass: { const IfStmt *IS = cast(S); // Evaluate the condition, as either a var decl or as an expression. + BlockScopeRAII Scope(Info); bool Cond; if (!EvaluateCond(Info, IS->getConditionVariable(), IS->getCond(), Cond)) return ESR_Failed; @@ -2584,6 +3346,7 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, case Stmt::WhileStmtClass: { const WhileStmt *WS = cast(S); while (true) { + BlockScopeRAII Scope(Info); bool Continue; if (!EvaluateCond(Info, WS->getConditionVariable(), WS->getCond(), Continue)) @@ -2602,10 +3365,12 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, const DoStmt *DS = cast(S); bool Continue; do { - EvalStmtResult ESR = EvaluateLoopBody(Result, Info, DS->getBody()); + EvalStmtResult ESR = EvaluateLoopBody(Result, Info, DS->getBody(), Case); if (ESR != ESR_Continue) return ESR; + Case = 0; + FullExpressionRAII CondScope(Info); if (!EvaluateAsBooleanCondition(DS->getCond(), Continue, Info)) return ESR_Failed; } while (Continue); @@ -2614,12 +3379,14 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, case Stmt::ForStmtClass: { const ForStmt *FS = cast(S); + BlockScopeRAII Scope(Info); if (FS->getInit()) { EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getInit()); if (ESR != ESR_Succeeded) return ESR; } while (true) { + BlockScopeRAII Scope(Info); bool Continue = true; if (FS->getCond() && !EvaluateCond(Info, FS->getConditionVariable(), FS->getCond(), Continue)) @@ -2631,14 +3398,18 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, if (ESR != ESR_Continue) return ESR; - if (FS->getInc() && !EvaluateIgnoredValue(Info, FS->getInc())) - return ESR_Failed; + if (FS->getInc()) { + FullExpressionRAII IncScope(Info); + if (!EvaluateIgnoredValue(Info, FS->getInc())) + return ESR_Failed; + } } return ESR_Succeeded; } case Stmt::CXXForRangeStmtClass: { const CXXForRangeStmt *FS = cast(S); + BlockScopeRAII Scope(Info); // Initialize the __range variable. EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getRangeStmt()); @@ -2652,13 +3423,17 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, while (true) { // Condition: __begin != __end. - bool Continue = true; - if (!EvaluateAsBooleanCondition(FS->getCond(), Continue, Info)) - return ESR_Failed; - if (!Continue) - break; + { + bool Continue = true; + FullExpressionRAII CondExpr(Info); + if (!EvaluateAsBooleanCondition(FS->getCond(), Continue, Info)) + return ESR_Failed; + if (!Continue) + break; + } // User's variable declaration, initialized by *__begin. + BlockScopeRAII InnerScope(Info); ESR = EvaluateStmt(Result, Info, FS->getLoopVarStmt()); if (ESR != ESR_Succeeded) return ESR; @@ -2676,11 +3451,27 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, return ESR_Succeeded; } + case Stmt::SwitchStmtClass: + return EvaluateSwitch(Result, Info, cast(S)); + case Stmt::ContinueStmtClass: return ESR_Continue; case Stmt::BreakStmtClass: return ESR_Break; + + case Stmt::LabelStmtClass: + return EvaluateStmt(Result, Info, cast(S)->getSubStmt(), Case); + + case Stmt::AttributedStmtClass: + // As a general principle, C++11 attributes can be ignored without + // any semantic impact. + return EvaluateStmt(Result, Info, cast(S)->getSubStmt(), + Case); + + case Stmt::CaseStmtClass: + case Stmt::DefaultStmtClass: + return EvaluateStmt(Result, Info, cast(S)->getSubStmt(), Case); } } @@ -2718,10 +3509,15 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Definition) { // Potential constant expressions can contain calls to declared, but not yet // defined, constexpr functions. - if (Info.CheckingPotentialConstantExpression && !Definition && + if (Info.checkingPotentialConstantExpression() && !Definition && Declaration->isConstexpr()) return false; + // Bail out with no diagnostic if the function declaration itself is invalid. + // We will have produced a relevant diagnostic while parsing it. + if (Declaration->isInvalidDecl()) + return false; + // Can we evaluate this function call? if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl()) return true; @@ -2774,6 +3570,27 @@ static bool HandleFunctionCall(SourceLocation CallLoc, return false; CallStackFrame Frame(Info, CallLoc, Callee, This, ArgValues.data()); + + // For a trivial copy or move assignment, perform an APValue copy. This is + // essential for unions, where the operations performed by the assignment + // operator cannot be represented as statements. + const CXXMethodDecl *MD = dyn_cast(Callee); + if (MD && MD->isDefaulted() && MD->isTrivial()) { + assert(This && + (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())); + LValue RHS; + RHS.setFrom(Info.Ctx, ArgValues[0]); + APValue RHSValue; + if (!handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), + RHS, RHSValue)) + return false; + if (!handleAssignment(Info, Args[0], *This, MD->getThisType(Info.Ctx), + RHSValue)) + return false; + This->moveInto(Result); + return true; + } + EvalStmtResult ESR = EvaluateStmt(Result, Info, Body); if (ESR == ESR_Succeeded) { if (Callee->getResultType()->isVoidType()) @@ -2806,8 +3623,11 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, // If it's a delegating constructor, just delegate. if (Definition->isDelegatingConstructor()) { CXXConstructorDecl::init_const_iterator I = Definition->init_begin(); - if (!EvaluateInPlace(Result, Info, This, (*I)->getInit())) - return false; + { + FullExpressionRAII InitScope(Info); + if (!EvaluateInPlace(Result, Info, This, (*I)->getInit())) + return false; + } return EvaluateStmt(Result, Info, Definition->getBody()) != ESR_Failed; } @@ -2831,6 +3651,9 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); + // A scope for temporaries lifetime-extended by reference members. + BlockScopeRAII LifetimeExtendedScope(Info); + bool Success = true; unsigned BasesSeen = 0; #ifndef NDEBUG @@ -2842,6 +3665,7 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, APValue *Value = &Result; // Determine the subobject to initialize. + FieldDecl *FD = 0; if ((*I)->isBaseInitializer()) { QualType BaseType((*I)->getBaseClass(), 0); #ifndef NDEBUG @@ -2856,7 +3680,7 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, BaseType->getAsCXXRecordDecl(), &Layout)) return false; Value = &Result.getStructBase(BasesSeen++); - } else if (FieldDecl *FD = (*I)->getMember()) { + } else if ((FD = (*I)->getMember())) { if (!HandleLValueMember(Info, (*I)->getInit(), Subobject, FD, &Layout)) return false; if (RD->isUnion()) { @@ -2871,7 +3695,7 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, for (IndirectFieldDecl::chain_iterator C = IFD->chain_begin(), CE = IFD->chain_end(); C != CE; ++C) { - FieldDecl *FD = cast(*C); + FD = cast(*C); CXXRecordDecl *CD = cast(FD->getParent()); // Switch the union field if it differs. This happens if we had // preceding zero-initialization, and we're now initializing a union @@ -2897,9 +3721,10 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, llvm_unreachable("unknown base initializer kind"); } - if (!EvaluateInPlace(*Value, Info, Subobject, (*I)->getInit(), - (*I)->isBaseInitializer() - ? CCEK_Constant : CCEK_MemberInit)) { + FullExpressionRAII InitScope(Info); + if (!EvaluateInPlace(*Value, Info, Subobject, (*I)->getInit()) || + (FD && FD->isBitField() && !truncateBitfieldValue(Info, (*I)->getInit(), + *Value, FD))) { // If we're checking for a potential constant expression, evaluate all // initializers even if some of them fail. if (!Info.keepEvaluatingAfterFailure()) @@ -2934,7 +3759,7 @@ private: // expression, then the conditional operator is not either. template void CheckPotentialConstantConditional(const ConditionalOperator *E) { - assert(Info.CheckingPotentialConstantExpression); + assert(Info.checkingPotentialConstantExpression()); // Speculatively evaluate both arms. { @@ -2959,7 +3784,7 @@ private: bool HandleConditionalOperator(const ConditionalOperator *E) { bool BoolResult; if (!EvaluateAsBooleanCondition(E->getCond(), BoolResult, Info)) { - if (Info.CheckingPotentialConstantExpression) + if (Info.checkingPotentialConstantExpression()) CheckPotentialConstantConditional(E); return false; } @@ -3008,15 +3833,19 @@ public: RetTy VisitUnaryPlus(const UnaryOperator *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } RetTy VisitChooseExpr(const ChooseExpr *E) - { return StmtVisitorTy::Visit(E->getChosenSubExpr(Info.Ctx)); } + { return StmtVisitorTy::Visit(E->getChosenSubExpr()); } RetTy VisitGenericSelectionExpr(const GenericSelectionExpr *E) { return StmtVisitorTy::Visit(E->getResultExpr()); } RetTy VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) { return StmtVisitorTy::Visit(E->getReplacement()); } RetTy VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { return StmtVisitorTy::Visit(E->getExpr()); } - RetTy VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) - { return StmtVisitorTy::Visit(E->getExpr()); } + RetTy VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) { + // The initializer may not have been parsed yet, or might be erroneous. + if (!E->getExpr()) + return Error(E); + return StmtVisitorTy::Visit(E->getExpr()); + } // We cannot create any objects for which cleanups are required, so there is // nothing to do here; all cleanups must come from unevaluated subexpressions. RetTy VisitExprWithCleanups(const ExprWithCleanups *E) @@ -3056,7 +3885,7 @@ public: RetTy VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) { // Evaluate and cache the common expression. We treat it as a temporary, // even though it's not quite the same thing. - if (!Evaluate(Info.CurrentCall->Temporaries[E->getOpaqueValue()], + if (!Evaluate(Info.CurrentCall->createTemporary(E->getOpaqueValue(), false), Info, E->getCommon())) return false; @@ -3076,33 +3905,30 @@ public: // Always assume __builtin_constant_p(...) ? ... : ... is a potential // constant expression; we can't check whether it's potentially foldable. - if (Info.CheckingPotentialConstantExpression && IsBcpCall) + if (Info.checkingPotentialConstantExpression() && IsBcpCall) return false; - FoldConstant Fold(Info); - - if (!HandleConditionalOperator(E)) + FoldConstant Fold(Info, IsBcpCall); + if (!HandleConditionalOperator(E)) { + Fold.keepDiagnostics(); return false; - - if (IsBcpCall) - Fold.Fold(Info); + } return true; } RetTy VisitOpaqueValueExpr(const OpaqueValueExpr *E) { - APValue &Value = Info.CurrentCall->Temporaries[E]; - if (Value.isUninit()) { - const Expr *Source = E->getSourceExpr(); - if (!Source) - return Error(E); - if (Source == E) { // sanity checking. - assert(0 && "OpaqueValueExpr recursively refers to itself"); - return Error(E); - } - return StmtVisitorTy::Visit(Source); + if (APValue *Value = Info.CurrentCall->getTemporary(E)) + return DerivedSuccess(*Value, E); + + const Expr *Source = E->getSourceExpr(); + if (!Source) + return Error(E); + if (Source == E) { // sanity checking. + assert(0 && "OpaqueValueExpr recursively refers to itself"); + return Error(E); } - return DerivedSuccess(Value, E); + return StmtVisitorTy::Visit(Source); } RetTy VisitCallExpr(const CallExpr *E) { @@ -3240,8 +4066,13 @@ public: default: break; - case CK_AtomicToNonAtomic: - case CK_NonAtomicToAtomic: + case CK_AtomicToNonAtomic: { + APValue AtomicVal; + if (!EvaluateAtomic(E->getSubExpr(), AtomicVal, Info)) + return false; + return DerivedSuccess(AtomicVal, E); + } + case CK_NoOp: case CK_UserDefinedConversion: return StmtVisitorTy::Visit(E->getSubExpr()); @@ -3282,6 +4113,41 @@ public: return DerivedSuccess(RVal, UO); } + RetTy VisitStmtExpr(const StmtExpr *E) { + // We will have checked the full-expressions inside the statement expression + // when they were completed, and don't need to check them again now. + if (Info.checkingForOverflow()) + return Error(E); + + BlockScopeRAII Scope(Info); + const CompoundStmt *CS = E->getSubStmt(); + for (CompoundStmt::const_body_iterator BI = CS->body_begin(), + BE = CS->body_end(); + /**/; ++BI) { + if (BI + 1 == BE) { + const Expr *FinalExpr = dyn_cast(*BI); + if (!FinalExpr) { + Info.Diag((*BI)->getLocStart(), + diag::note_constexpr_stmt_expr_unsupported); + return false; + } + return this->Visit(FinalExpr); + } + + APValue ReturnValue; + EvalStmtResult ESR = EvaluateStmt(ReturnValue, Info, *BI); + if (ESR != ESR_Succeeded) { + // FIXME: If the statement-expression terminated due to 'return', + // 'break', or 'continue', it would be nice to propagate that to + // the outer statement evaluation rather than bailing out. + if (ESR != ESR_Failed) + Info.Diag((*BI)->getLocStart(), + diag::note_constexpr_stmt_expr_unsupported); + return false; + } + } + } + /// Visit a value which is evaluated, but whose value is ignored. void VisitIgnoredValue(const Expr *E) { EvaluateIgnoredValue(Info, E); @@ -3374,24 +4240,14 @@ public: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_DerivedToBase: - case CK_UncheckedDerivedToBase: { + case CK_UncheckedDerivedToBase: if (!this->Visit(E->getSubExpr())) return false; // Now figure out the necessary offset to add to the base LV to get from // the derived class to the base class. - QualType Type = E->getSubExpr()->getType(); - - for (CastExpr::path_const_iterator PathI = E->path_begin(), - PathE = E->path_end(); PathI != PathE; ++PathI) { - if (!HandleLValueBase(this->Info, E, Result, Type->getAsCXXRecordDecl(), - *PathI)) - return false; - Type = (*PathI)->getType(); - } - - return true; - } + return HandleLValueBasePath(this->Info, E, E->getSubExpr()->getType(), + Result); } } }; @@ -3420,8 +4276,12 @@ public: // * BlockExpr // * CallExpr for a MakeStringConstant builtin // - Locals and temporaries +// * MaterializeTemporaryExpr // * Any Expr, with a CallIndex indicating the function in which the temporary -// was evaluated. +// was evaluated, for cases where the MaterializeTemporaryExpr is missing +// from the AST (FIXME). +// * A MaterializeTemporaryExpr that has static storage duration, with no +// CallIndex, for a lifetime-extended temporary. // plus an offset in bytes. //===----------------------------------------------------------------------===// namespace { @@ -3511,17 +4371,78 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { APValue *V; if (!evaluateVarDeclInit(Info, E, VD, Frame, V)) return false; + if (V->isUninit()) { + if (!Info.checkingPotentialConstantExpression()) + Info.Diag(E, diag::note_constexpr_use_uninit_reference); + return false; + } return Success(*V, E); } bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( const MaterializeTemporaryExpr *E) { - if (E->getType()->isRecordType()) - return EvaluateTemporary(E->GetTemporaryExpr(), Result, Info); + // Walk through the expression to find the materialized temporary itself. + SmallVector CommaLHSs; + SmallVector Adjustments; + const Expr *Inner = E->GetTemporaryExpr()-> + skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); + + // If we passed any comma operators, evaluate their LHSs. + for (unsigned I = 0, N = CommaLHSs.size(); I != N; ++I) + if (!EvaluateIgnoredValue(Info, CommaLHSs[I])) + return false; + + // A materialized temporary with static storage duration can appear within the + // result of a constant expression evaluation, so we need to preserve its + // value for use outside this evaluation. + APValue *Value; + if (E->getStorageDuration() == SD_Static) { + Value = Info.Ctx.getMaterializedTemporaryValue(E, true); + *Value = APValue(); + Result.set(E); + } else { + Value = &Info.CurrentCall-> + createTemporary(E, E->getStorageDuration() == SD_Automatic); + Result.set(E, Info.CurrentCall->Index); + } + + QualType Type = Inner->getType(); + + // Materialize the temporary itself. + if (!EvaluateInPlace(*Value, Info, Result, Inner) || + (E->getStorageDuration() == SD_Static && + !CheckConstantExpression(Info, E->getExprLoc(), Type, *Value))) { + *Value = APValue(); + return false; + } + + // Adjust our lvalue to refer to the desired subobject. + for (unsigned I = Adjustments.size(); I != 0; /**/) { + --I; + switch (Adjustments[I].Kind) { + case SubobjectAdjustment::DerivedToBaseAdjustment: + if (!HandleLValueBasePath(Info, Adjustments[I].DerivedToBase.BasePath, + Type, Result)) + return false; + Type = Adjustments[I].DerivedToBase.BasePath->getType(); + break; + + case SubobjectAdjustment::FieldAdjustment: + if (!HandleLValueMember(Info, E, Result, Adjustments[I].Field)) + return false; + Type = Adjustments[I].Field->getType(); + break; + + case SubobjectAdjustment::MemberPointerAdjustment: + if (!HandleMemberPointerAccess(this->Info, Type, Result, + Adjustments[I].Ptr.RHS)) + return false; + Type = Adjustments[I].Ptr.MPT->getPointeeType(); + break; + } + } - Result.set(E, Info.CurrentCall->Index); - return EvaluateInPlace(Info.CurrentCall->Temporaries[E], Info, - Result, E->GetTemporaryExpr()); + return true; } bool @@ -3576,11 +4497,9 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { APSInt Index; if (!EvaluateInteger(E->getIdx(), Index, Info)) return false; - int64_t IndexValue - = Index.isSigned() ? Index.getSExtValue() - : static_cast(Index.getZExtValue()); - return HandleLValueArrayAdjustment(Info, E, Result, E->getType(), IndexValue); + return HandleLValueArrayAdjustment(Info, E, Result, E->getType(), + getExtValue(Index)); } bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) { @@ -3634,14 +4553,10 @@ bool LValueExprEvaluator::VisitCompoundAssignOperator( if (!Evaluate(RHS, this->Info, CAO->getRHS())) return false; - // FIXME: - //return handleCompoundAssignment( - // this->Info, CAO, - // Result, CAO->getLHS()->getType(), CAO->getComputationLHSType(), - // RHS, CAO->getRHS()->getType(), - // CAO->getOpForCompoundAssignment(CAO->getOpcode()), - // CAO->getComputationResultType()); - return Error(CAO); + return handleCompoundAssignment( + this->Info, CAO, + Result, CAO->getLHS()->getType(), CAO->getComputationLHSType(), + CAO->getOpForCompoundAssignment(CAO->getOpcode()), RHS); } bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) { @@ -3705,6 +4620,9 @@ public: return Error(E); } bool VisitCXXThisExpr(const CXXThisExpr *E) { + // Can't look at 'this' when checking a potential constant expression. + if (Info.checkingPotentialConstantExpression()) + return false; if (!Info.CurrentCall->This) return Error(E); Result = *Info.CurrentCall->This; @@ -3737,9 +4655,8 @@ bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { llvm::APSInt Offset; if (!EvaluateInteger(IExp, Offset, Info) || !EvalPtrOK) return false; - int64_t AdditionalOffset - = Offset.isSigned() ? Offset.getSExtValue() - : static_cast(Offset.getZExtValue()); + + int64_t AdditionalOffset = getExtValue(Offset); if (E->getOpcode() == BO_Sub) AdditionalOffset = -AdditionalOffset; @@ -3779,7 +4696,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { return true; case CK_DerivedToBase: - case CK_UncheckedDerivedToBase: { + case CK_UncheckedDerivedToBase: if (!EvaluatePointer(E->getSubExpr(), Result, Info)) return false; if (!Result.Base && Result.Offset.isZero()) @@ -3787,19 +4704,9 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { // Now figure out the necessary offset to add to the base LV to get from // the derived class to the base class. - QualType Type = - E->getSubExpr()->getType()->castAs()->getPointeeType(); - - for (CastExpr::path_const_iterator PathI = E->path_begin(), - PathE = E->path_end(); PathI != PathE; ++PathI) { - if (!HandleLValueBase(Info, E, Result, Type->getAsCXXRecordDecl(), - *PathI)) - return false; - Type = (*PathI)->getType(); - } - - return true; - } + return HandleLValueBasePath(Info, E, E->getSubExpr()->getType()-> + castAs()->getPointeeType(), + Result); case CK_BaseToDerived: if (!Visit(E->getSubExpr())) @@ -3839,7 +4746,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { return false; } else { Result.set(SubExpr, Info.CurrentCall->Index); - if (!EvaluateInPlace(Info.CurrentCall->Temporaries[SubExpr], + if (!EvaluateInPlace(Info.CurrentCall->createTemporary(SubExpr, false), Info, Result, SubExpr)) return false; } @@ -3862,7 +4769,13 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { if (IsStringLiteralCall(E)) return Success(E); - return ExprEvaluatorBaseTy::VisitCallExpr(E); + switch (E->isBuiltinCall()) { + case Builtin::BI__builtin_addressof: + return EvaluateLValue(E->getArg(0), Result, Info); + + default: + return ExprEvaluatorBaseTy::VisitCallExpr(E); + } } //===----------------------------------------------------------------------===// @@ -3976,6 +4889,7 @@ namespace { bool VisitCastExpr(const CastExpr *E); bool VisitInitListExpr(const InitListExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E); + bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E); }; } @@ -4091,10 +5005,6 @@ bool RecordExprEvaluator::VisitCastExpr(const CastExpr *E) { } bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { - // Cannot constant-evaluate std::initializer_list inits. - if (E->initializesStdInitializerList()) - return false; - const RecordDecl *RD = E->getType()->castAs()->getDecl(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); @@ -4156,8 +5066,10 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This, isa(Init)); - if (!EvaluateInPlace(Result.getStructField(Field->getFieldIndex()), Info, - Subobject, Init)) { + APValue &FieldVal = Result.getStructField(Field->getFieldIndex()); + if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) || + (Field->isBitField() && !truncateBitfieldValue(Info, Init, + FieldVal, *Field))) { if (!Info.keepEvaluatingAfterFailure()) return false; Success = false; @@ -4210,6 +5122,58 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { Result); } +bool RecordExprEvaluator::VisitCXXStdInitializerListExpr( + const CXXStdInitializerListExpr *E) { + const ConstantArrayType *ArrayType = + Info.Ctx.getAsConstantArrayType(E->getSubExpr()->getType()); + + LValue Array; + if (!EvaluateLValue(E->getSubExpr(), Array, Info)) + return false; + + // Get a pointer to the first element of the array. + Array.addArray(Info, E, ArrayType); + + // FIXME: Perform the checks on the field types in SemaInit. + RecordDecl *Record = E->getType()->castAs()->getDecl(); + RecordDecl::field_iterator Field = Record->field_begin(); + if (Field == Record->field_end()) + return Error(E); + + // Start pointer. + if (!Field->getType()->isPointerType() || + !Info.Ctx.hasSameType(Field->getType()->getPointeeType(), + ArrayType->getElementType())) + return Error(E); + + // FIXME: What if the initializer_list type has base classes, etc? + Result = APValue(APValue::UninitStruct(), 0, 2); + Array.moveInto(Result.getStructField(0)); + + if (++Field == Record->field_end()) + return Error(E); + + if (Field->getType()->isPointerType() && + Info.Ctx.hasSameType(Field->getType()->getPointeeType(), + ArrayType->getElementType())) { + // End pointer. + if (!HandleLValueArrayAdjustment(Info, E, Array, + ArrayType->getElementType(), + ArrayType->getSize().getZExtValue())) + return false; + Array.moveInto(Result.getStructField(1)); + } else if (Info.Ctx.hasSameType(Field->getType(), Info.Ctx.getSizeType())) + // Length. + Result.getStructField(1) = APValue(APSInt(ArrayType->getSize())); + else + return Error(E); + + if (++Field != Record->field_end()) + return Error(E); + + return true; +} + static bool EvaluateRecord(const Expr *E, const LValue &This, APValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isRecordType() && @@ -4234,7 +5198,8 @@ public: /// Visit an expression which constructs the value of this temporary. bool VisitConstructExpr(const Expr *E) { Result.set(E, Info.CurrentCall->Index); - return EvaluateInPlace(Info.CurrentCall->Temporaries[E], Info, Result, E); + return EvaluateInPlace(Info.CurrentCall->createTemporary(E, false), + Info, Result, E); } bool VisitCastExpr(const CastExpr *E) { @@ -4393,7 +5358,7 @@ VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) { while (CountElts < NumElements) { // Handle nested vector initialization. if (CountInits < NumInits - && E->getInit(CountInits)->getType()->isExtVectorType()) { + && E->getInit(CountInits)->getType()->isVectorType()) { APValue v; if (!EvaluateVector(E->getInit(CountInits), v, Info)) return Error(E); @@ -4951,7 +5916,7 @@ static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) { } else if (ArgType->isPointerType() || Arg->isGLValue()) { LValue LV; Expr::EvalStatus Status; - EvalInfo Info(Ctx, Status); + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); if ((Arg->isGLValue() ? EvaluateLValue(Arg, LV, Info) : EvaluatePointer(Arg, LV, Info)) && !Status.HasSideEffects) @@ -5045,9 +6010,37 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_classify_type: return Success(EvaluateBuiltinClassifyType(E), E); + // FIXME: BI__builtin_clrsb + // FIXME: BI__builtin_clrsbl + // FIXME: BI__builtin_clrsbll + + case Builtin::BI__builtin_clz: + case Builtin::BI__builtin_clzl: + case Builtin::BI__builtin_clzll: { + APSInt Val; + if (!EvaluateInteger(E->getArg(0), Val, Info)) + return false; + if (!Val) + return Error(E); + + return Success(Val.countLeadingZeros(), E); + } + case Builtin::BI__builtin_constant_p: return Success(EvaluateBuiltinConstantP(Info.Ctx, E->getArg(0)), E); + case Builtin::BI__builtin_ctz: + case Builtin::BI__builtin_ctzl: + case Builtin::BI__builtin_ctzll: { + APSInt Val; + if (!EvaluateInteger(E->getArg(0), Val, Info)) + return false; + if (!Val) + return Error(E); + + return Success(Val.countTrailingZeros(), E); + } + case Builtin::BI__builtin_eh_return_data_regno: { int Operand = E->getArg(0)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); Operand = Info.Ctx.getTargetInfo().getEHDataRegisterNumber(Operand); @@ -5057,6 +6050,81 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_expect: return Visit(E->getArg(0)); + case Builtin::BI__builtin_ffs: + case Builtin::BI__builtin_ffsl: + case Builtin::BI__builtin_ffsll: { + APSInt Val; + if (!EvaluateInteger(E->getArg(0), Val, Info)) + return false; + + unsigned N = Val.countTrailingZeros(); + return Success(N == Val.getBitWidth() ? 0 : N + 1, E); + } + + case Builtin::BI__builtin_fpclassify: { + APFloat Val(0.0); + if (!EvaluateFloat(E->getArg(5), Val, Info)) + return false; + unsigned Arg; + switch (Val.getCategory()) { + case APFloat::fcNaN: Arg = 0; break; + case APFloat::fcInfinity: Arg = 1; break; + case APFloat::fcNormal: Arg = Val.isDenormal() ? 3 : 2; break; + case APFloat::fcZero: Arg = 4; break; + } + return Visit(E->getArg(Arg)); + } + + case Builtin::BI__builtin_isinf_sign: { + APFloat Val(0.0); + return EvaluateFloat(E->getArg(0), Val, Info) && + Success(Val.isInfinity() ? (Val.isNegative() ? -1 : 1) : 0, E); + } + + case Builtin::BI__builtin_isinf: { + APFloat Val(0.0); + return EvaluateFloat(E->getArg(0), Val, Info) && + Success(Val.isInfinity() ? 1 : 0, E); + } + + case Builtin::BI__builtin_isfinite: { + APFloat Val(0.0); + return EvaluateFloat(E->getArg(0), Val, Info) && + Success(Val.isFinite() ? 1 : 0, E); + } + + case Builtin::BI__builtin_isnan: { + APFloat Val(0.0); + return EvaluateFloat(E->getArg(0), Val, Info) && + Success(Val.isNaN() ? 1 : 0, E); + } + + case Builtin::BI__builtin_isnormal: { + APFloat Val(0.0); + return EvaluateFloat(E->getArg(0), Val, Info) && + Success(Val.isNormal() ? 1 : 0, E); + } + + case Builtin::BI__builtin_parity: + case Builtin::BI__builtin_parityl: + case Builtin::BI__builtin_parityll: { + APSInt Val; + if (!EvaluateInteger(E->getArg(0), Val, Info)) + return false; + + return Success(Val.countPopulation() % 2, E); + } + + case Builtin::BI__builtin_popcount: + case Builtin::BI__builtin_popcountl: + case Builtin::BI__builtin_popcountll: { + APSInt Val; + if (!EvaluateInteger(E->getArg(0), Val, Info)) + return false; + + return Success(Val.countPopulation(), E); + } + case Builtin::BIstrlen: // A call to strlen is not a constant expression. if (Info.getLangOpts().CPlusPlus11) @@ -5065,22 +6133,47 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { else Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); // Fall through. - case Builtin::BI__builtin_strlen: - // As an extension, we support strlen() and __builtin_strlen() as constant - // expressions when the argument is a string literal. - if (const StringLiteral *S - = dyn_cast(E->getArg(0)->IgnoreParenImpCasts())) { + case Builtin::BI__builtin_strlen: { + // As an extension, we support __builtin_strlen() as a constant expression, + // and support folding strlen() to a constant. + LValue String; + if (!EvaluatePointer(E->getArg(0), String, Info)) + return false; + + // Fast path: if it's a string literal, search the string value. + if (const StringLiteral *S = dyn_cast_or_null( + String.getLValueBase().dyn_cast())) { // The string literal may have embedded null characters. Find the first // one and truncate there. - StringRef Str = S->getString(); - StringRef::size_type Pos = Str.find(0); - if (Pos != StringRef::npos) - Str = Str.substr(0, Pos); - - return Success(Str.size(), E); + StringRef Str = S->getBytes(); + int64_t Off = String.Offset.getQuantity(); + if (Off >= 0 && (uint64_t)Off <= (uint64_t)Str.size() && + S->getCharByteWidth() == 1) { + Str = Str.substr(Off); + + StringRef::size_type Pos = Str.find(0); + if (Pos != StringRef::npos) + Str = Str.substr(0, Pos); + + return Success(Str.size(), E); + } + + // Fall through to slow path to issue appropriate diagnostic. } - - return Error(E); + + // Slow path: scan the bytes of the string looking for the terminating 0. + QualType CharTy = E->getArg(0)->getType()->getPointeeType(); + for (uint64_t Strlen = 0; /**/; ++Strlen) { + APValue Char; + if (!handleLValueToRValueConversion(Info, E, CharTy, String, Char) || + !Char.isInt()) + return false; + if (!Char.getInt()) + return Success(Strlen, E); + if (!HandleLValueArrayAdjustment(Info, E, String, CharTy, 1)) + return false; + } + } case Builtin::BI__atomic_always_lock_free: case Builtin::BI__atomic_is_lock_free: @@ -5149,29 +6242,6 @@ static bool HasSameBase(const LValue &A, const LValue &B) { A.getLValueCallIndex() == B.getLValueCallIndex(); } -/// Perform the given integer operation, which is known to need at most BitWidth -/// bits, and check for overflow in the original type (if that type was not an -/// unsigned type). -template -static APSInt CheckedIntArithmetic(EvalInfo &Info, const Expr *E, - const APSInt &LHS, const APSInt &RHS, - unsigned BitWidth, Operation Op) { - if (LHS.isUnsigned()) - return Op(LHS, RHS); - - APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false); - APSInt Result = Value.trunc(LHS.getBitWidth()); - 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; -} - namespace { /// \brief Data recursive integer evaluator of certain binary operators. @@ -5296,36 +6366,39 @@ bool DataRecursiveIntBinOpEvaluator:: if (E->getOpcode() == BO_Comma) { // Ignore LHS but note if we could not evaluate it. if (LHSResult.Failed) - Info.EvalStatus.HasSideEffects = true; + return Info.noteSideEffect(); return true; } - + if (E->isLogicalOp()) { - bool lhsResult; - if (HandleConversionToBool(LHSResult.Val, lhsResult)) { + bool LHSAsBool; + if (!LHSResult.Failed && HandleConversionToBool(LHSResult.Val, LHSAsBool)) { // We were able to evaluate the LHS, see if we can get away with not // evaluating the RHS: 0 && X -> 0, 1 || X -> 1 - if (lhsResult == (E->getOpcode() == BO_LOr)) { - Success(lhsResult, E, LHSResult.Val); + if (LHSAsBool == (E->getOpcode() == BO_LOr)) { + Success(LHSAsBool, E, LHSResult.Val); return false; // Ignore RHS } } else { + LHSResult.Failed = true; + // Since we weren't able to evaluate the left hand side, it // must have had side effects. - Info.EvalStatus.HasSideEffects = true; - + if (!Info.noteSideEffect()) + return false; + // We can't evaluate the LHS; however, sometimes the result // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. // Don't ignore RHS and suppress diagnostics from this arm. SuppressRHSDiags = true; } - + return true; } - + assert(E->getLHS()->getType()->isIntegralOrEnumerationType() && E->getRHS()->getType()->isIntegralOrEnumerationType()); - + if (LHSResult.Failed && !Info.keepEvaluatingAfterFailure()) return false; // Ignore RHS; @@ -5378,8 +6451,8 @@ bool DataRecursiveIntBinOpEvaluator:: // Handle cases like (unsigned long)&a + 4. if (E->isAdditiveOp() && LHSVal.isLValue() && RHSVal.isInt()) { Result = LHSVal; - CharUnits AdditionalOffset = CharUnits::fromQuantity( - RHSVal.getInt().getZExtValue()); + CharUnits AdditionalOffset = + CharUnits::fromQuantity(RHSVal.getInt().getZExtValue()); if (E->getOpcode() == BO_Add) Result.getLValueOffset() += AdditionalOffset; else @@ -5391,8 +6464,8 @@ bool DataRecursiveIntBinOpEvaluator:: if (E->getOpcode() == BO_Add && RHSVal.isLValue() && LHSVal.isInt()) { Result = RHSVal; - Result.getLValueOffset() += CharUnits::fromQuantity( - LHSVal.getInt().getZExtValue()); + Result.getLValueOffset() += + CharUnits::fromQuantity(LHSVal.getInt().getZExtValue()); return true; } @@ -5416,108 +6489,20 @@ bool DataRecursiveIntBinOpEvaluator:: Result = APValue(LHSAddrExpr, RHSAddrExpr); return true; } - - // All the following cases expect both operands to be an integer + + // All the remaining cases expect both operands to be an integer if (!LHSVal.isInt() || !RHSVal.isInt()) return Error(E); - - const APSInt &LHS = LHSVal.getInt(); - APSInt RHS = RHSVal.getInt(); - - switch (E->getOpcode()) { - default: - return Error(E); - case BO_Mul: - return Success(CheckedIntArithmetic(Info, E, LHS, RHS, - LHS.getBitWidth() * 2, - std::multiplies()), E, - Result); - case BO_Add: - return Success(CheckedIntArithmetic(Info, E, LHS, RHS, - LHS.getBitWidth() + 1, - std::plus()), E, Result); - case BO_Sub: - return Success(CheckedIntArithmetic(Info, E, LHS, RHS, - LHS.getBitWidth() + 1, - std::minus()), E, Result); - case BO_And: return Success(LHS & RHS, E, Result); - case BO_Xor: return Success(LHS ^ RHS, E, Result); - case BO_Or: return Success(LHS | RHS, E, Result); - case BO_Div: - case BO_Rem: - if (RHS == 0) - return Error(E, diag::note_expr_divide_by_zero); - // Check for overflow case: INT_MIN / -1 or INT_MIN % -1. The latter is - // not actually undefined behavior in C++11 due to a language defect. - if (RHS.isNegative() && RHS.isAllOnesValue() && - LHS.isSigned() && LHS.isMinSignedValue()) - HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1), E->getType()); - return Success(E->getOpcode() == BO_Rem ? LHS % RHS : LHS / RHS, E, - Result); - case BO_Shl: { - if (Info.getLangOpts().OpenCL) - // OpenCL 6.3j: shift values are effectively % word size of LHS. - RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), - static_cast(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; - } - - shift_left: - // C++11 [expr.shift]p1: Shift width must be less than the bit width of - // the shifted type. - unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1); - if (SA != RHS) { - CCEDiag(E, diag::note_constexpr_large_shift) - << RHS << E->getType() << LHS.getBitWidth(); - } else if (LHS.isSigned()) { - // C++11 [expr.shift]p2: A signed left shift must have a non-negative - // operand, and must not overflow the corresponding unsigned type. - if (LHS.isNegative()) - CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS; - else if (LHS.countLeadingZeros() < SA) - CCEDiag(E, diag::note_constexpr_lshift_discards); - } - - return Success(LHS << SA, E, Result); - } - case BO_Shr: { - if (Info.getLangOpts().OpenCL) - // OpenCL 6.3j: shift values are effectively % word size of LHS. - RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), - static_cast(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; - } - - shift_right: - // C++11 [expr.shift]p1: Shift width must be less than the bit width of the - // shifted type. - unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1); - if (SA != RHS) - CCEDiag(E, diag::note_constexpr_large_shift) - << RHS << E->getType() << LHS.getBitWidth(); - - return Success(LHS >> SA, E, Result); - } - - case BO_LT: return Success(LHS < RHS, E, Result); - case BO_GT: return Success(LHS > RHS, E, Result); - case BO_LE: return Success(LHS <= RHS, E, Result); - case BO_GE: return Success(LHS >= RHS, E, Result); - case BO_EQ: return Success(LHS == RHS, E, Result); - case BO_NE: return Success(LHS != RHS, E, Result); - } + + // Set up the width and signedness manually, in case it can't be deduced + // from the operation we're performing. + // FIXME: Don't do this in the cases where we can deduce it. + APSInt Value(Info.Ctx.getIntWidth(E->getType()), + E->getType()->isUnsignedIntegerOrEnumerationType()); + if (!handleIntIntBinOp(Info, E, LHSVal.getInt(), E->getOpcode(), + RHSVal.getInt(), Value)) + return false; + return Success(Value, E, Result); } void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) { @@ -5737,6 +6722,15 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (!HandleSizeof(Info, E->getExprLoc(), ElementType, ElementSize)) return false; + // As an extension, a type may have zero size (empty struct or union in + // C, array of zero length). Pointer subtraction in such cases has + // undefined behavior, so is not constant. + if (ElementSize.isZero()) { + Info.Diag(E, diag::note_constexpr_pointer_subtraction_zero_size) + << ElementType; + return false; + } + // FIXME: LLVM and GCC both compute LHSOffset - RHSOffset at runtime, // and produce incorrect results when it overflows. Such behavior // appears to be non-conforming, but is common, so perhaps we should @@ -5999,7 +6993,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { CurrentType = AT->getElementType(); CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(CurrentType); Result += IdxResult.getSExtValue() * ElementSize; - break; + break; } case OffsetOfExpr::OffsetOfNode::Field: { @@ -6125,6 +7119,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_IntegralComplexToFloatingComplex: case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: + case CK_NonAtomicToAtomic: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -6140,7 +7135,6 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_UserDefinedConversion: case CK_LValueToRValue: case CK_AtomicToNonAtomic: - case CK_NonAtomicToAtomic: case CK_NoOp: return ExprEvaluatorBaseTy::VisitCastExpr(E); @@ -6369,6 +7363,10 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { Result.changeSign(); return true; + // FIXME: Builtin::BI__builtin_powi + // FIXME: Builtin::BI__builtin_powif + // FIXME: Builtin::BI__builtin_powil + case Builtin::BI__builtin_copysign: case Builtin::BI__builtin_copysignf: case Builtin::BI__builtin_copysignl: { @@ -6430,28 +7428,8 @@ bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { bool LHSOK = EvaluateFloat(E->getLHS(), Result, Info); if (!LHSOK && !Info.keepEvaluatingAfterFailure()) return false; - if (!EvaluateFloat(E->getRHS(), RHS, Info) || !LHSOK) - return false; - - switch (E->getOpcode()) { - default: return Error(E); - case BO_Mul: - Result.multiply(RHS, APFloat::rmNearestTiesToEven); - break; - case BO_Add: - Result.add(RHS, APFloat::rmNearestTiesToEven); - break; - case BO_Sub: - Result.subtract(RHS, APFloat::rmNearestTiesToEven); - break; - case BO_Div: - Result.divide(RHS, APFloat::rmNearestTiesToEven); - break; - } - - if (Result.isInfinity() || Result.isNaN()) - CCEDiag(E, diag::note_constexpr_float_arithmetic) << Result.isNaN(); - return true; + return EvaluateFloat(E->getRHS(), RHS, Info) && LHSOK && + handleFloatFloatBinOp(Info, E, Result, E->getOpcode(), RHS); } bool FloatExprEvaluator::VisitFloatingLiteral(const FloatingLiteral *E) { @@ -6613,11 +7591,11 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_CopyAndAutoreleaseBlockObject: case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: + case CK_NonAtomicToAtomic: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: case CK_AtomicToNonAtomic: - case CK_NonAtomicToAtomic: case CK_NoOp: return ExprEvaluatorBaseTy::VisitCastExpr(E); @@ -6874,6 +7852,46 @@ bool ComplexExprEvaluator::VisitInitListExpr(const InitListExpr *E) { } //===----------------------------------------------------------------------===// +// Atomic expression evaluation, essentially just handling the NonAtomicToAtomic +// implicit conversion. +//===----------------------------------------------------------------------===// + +namespace { +class AtomicExprEvaluator : + public ExprEvaluatorBase { + APValue &Result; +public: + AtomicExprEvaluator(EvalInfo &Info, APValue &Result) + : ExprEvaluatorBaseTy(Info), Result(Result) {} + + bool Success(const APValue &V, const Expr *E) { + Result = V; + return true; + } + + bool ZeroInitialization(const Expr *E) { + ImplicitValueInitExpr VIE( + E->getType()->castAs()->getValueType()); + return Evaluate(Result, Info, &VIE); + } + + bool VisitCastExpr(const CastExpr *E) { + switch (E->getCastKind()) { + default: + return ExprEvaluatorBaseTy::VisitCastExpr(E); + case CK_NonAtomicToAtomic: + return Evaluate(Result, Info, E->getSubExpr()); + } + } +}; +} // end anonymous namespace + +static bool EvaluateAtomic(const Expr *E, APValue &Result, EvalInfo &Info) { + assert(E->isRValue() && E->getType()->isAtomicType()); + return AtomicExprEvaluator(Info, Result).Visit(E); +} + +//===----------------------------------------------------------------------===// // Void expression evaluation, primarily for a cast to void on the LHS of a // comma operator //===----------------------------------------------------------------------===// @@ -6910,56 +7928,62 @@ static bool EvaluateVoid(const Expr *E, EvalInfo &Info) { static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { // In C, function designators are not lvalues, but we evaluate them as if they // are. - if (E->isGLValue() || E->getType()->isFunctionType()) { + QualType T = E->getType(); + if (E->isGLValue() || T->isFunctionType()) { LValue LV; if (!EvaluateLValue(E, LV, Info)) return false; LV.moveInto(Result); - } else if (E->getType()->isVectorType()) { + } else if (T->isVectorType()) { if (!EvaluateVector(E, Result, Info)) return false; - } else if (E->getType()->isIntegralOrEnumerationType()) { + } else if (T->isIntegralOrEnumerationType()) { if (!IntExprEvaluator(Info, Result).Visit(E)) return false; - } else if (E->getType()->hasPointerRepresentation()) { + } else if (T->hasPointerRepresentation()) { LValue LV; if (!EvaluatePointer(E, LV, Info)) return false; LV.moveInto(Result); - } else if (E->getType()->isRealFloatingType()) { + } else if (T->isRealFloatingType()) { llvm::APFloat F(0.0); if (!EvaluateFloat(E, F, Info)) return false; Result = APValue(F); - } else if (E->getType()->isAnyComplexType()) { + } else if (T->isAnyComplexType()) { ComplexValue C; if (!EvaluateComplex(E, C, Info)) return false; C.moveInto(Result); - } else if (E->getType()->isMemberPointerType()) { + } else if (T->isMemberPointerType()) { MemberPtr P; if (!EvaluateMemberPointer(E, P, Info)) return false; P.moveInto(Result); return true; - } else if (E->getType()->isArrayType()) { + } else if (T->isArrayType()) { LValue LV; LV.set(E, Info.CurrentCall->Index); - if (!EvaluateArray(E, LV, Info.CurrentCall->Temporaries[E], Info)) + APValue &Value = Info.CurrentCall->createTemporary(E, false); + if (!EvaluateArray(E, LV, Value, Info)) return false; - Result = Info.CurrentCall->Temporaries[E]; - } else if (E->getType()->isRecordType()) { + Result = Value; + } else if (T->isRecordType()) { LValue LV; LV.set(E, Info.CurrentCall->Index); - if (!EvaluateRecord(E, LV, Info.CurrentCall->Temporaries[E], Info)) + APValue &Value = Info.CurrentCall->createTemporary(E, false); + if (!EvaluateRecord(E, LV, Value, Info)) return false; - Result = Info.CurrentCall->Temporaries[E]; - } else if (E->getType()->isVoidType()) { + Result = Value; + } else if (T->isVoidType()) { if (!Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_nonliteral) << E->getType(); if (!EvaluateVoid(E, Info)) return false; + } else if (T->isAtomicType()) { + if (!EvaluateAtomic(E, Result, Info)) + return false; } else if (Info.getLangOpts().CPlusPlus11) { Info.Diag(E, diag::note_constexpr_nonliteral) << E->getType(); return false; @@ -6975,9 +7999,8 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { /// cases, the in-place evaluation is essential, since later initializers for /// an object can indirectly refer to subobjects which were initialized earlier. static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, - const Expr *E, CheckConstantExpressionKind CCEK, - bool AllowNonLiteralTypes) { - if (!AllowNonLiteralTypes && !CheckLiteralType(Info, E)) + const Expr *E, bool AllowNonLiteralTypes) { + if (!AllowNonLiteralTypes && !CheckLiteralType(Info, E, &This)) return false; if (E->isRValue()) { @@ -7046,7 +8069,7 @@ bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { if (FastEvaluateAsRValue(this, Result, Ctx, IsConst)) return IsConst; - EvalInfo Info(Ctx, Result); + EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); return ::EvaluateAsRValue(Info, this, Result.Val); } @@ -7072,7 +8095,7 @@ bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx, } bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const { - EvalInfo Info(Ctx, Result); + EvalInfo Info(Ctx, Result, EvalInfo::EM_ConstantFold); LValue LV; if (!EvaluateLValue(this, LV, Info) || Result.HasSideEffects || @@ -7096,7 +8119,7 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, Expr::EvalStatus EStatus; EStatus.Diag = &Notes; - EvalInfo InitInfo(Ctx, EStatus); + EvalInfo InitInfo(Ctx, EStatus, EvalInfo::EM_ConstantFold); InitInfo.setEvaluatingDecl(VD, Value); LValue LVal; @@ -7109,13 +8132,13 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, if (Ctx.getLangOpts().CPlusPlus && !VD->hasLocalStorage() && !VD->getType()->isReferenceType()) { ImplicitValueInitExpr VIE(VD->getType()); - if (!EvaluateInPlace(Value, InitInfo, LVal, &VIE, CCEK_Constant, + if (!EvaluateInPlace(Value, InitInfo, LVal, &VIE, /*AllowNonLiteralTypes=*/true)) return false; } - if (!EvaluateInPlace(Value, InitInfo, LVal, this, CCEK_Constant, - /*AllowNonLiteralTypes=*/true) || + if (!EvaluateInPlace(Value, InitInfo, LVal, this, + /*AllowNonLiteralTypes=*/true) || EStatus.HasSideEffects) return false; @@ -7142,21 +8165,19 @@ APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx, return EvalResult.Val.getInt(); } -void Expr::EvaluateForOverflow(const ASTContext &Ctx, - SmallVectorImpl *Diags) const { +void Expr::EvaluateForOverflow(const ASTContext &Ctx) const { bool IsConst; EvalResult EvalResult; - EvalResult.Diag = Diags; if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) { - EvalInfo Info(Ctx, EvalResult, true); + EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow); (void)::EvaluateAsRValue(Info, this, EvalResult.Val); } } - bool Expr::EvalResult::isGlobalLValue() const { - assert(Val.isLValue()); - return IsGlobalLValue(Val.getLValueBase()); - } +bool Expr::EvalResult::isGlobalLValue() const { + assert(Val.isLValue()); + return IsGlobalLValue(Val.getLValueBase()); +} /// isIntegerConstantExpr - this recursive routine will test if an expression is @@ -7200,7 +8221,7 @@ 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) { +static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) { Expr::EvalResult EVResult; if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects || !EVResult.Val.isInt()) @@ -7209,7 +8230,7 @@ static ICEDiag CheckEvalInICE(const Expr* E, ASTContext &Ctx) { return NoDiag(); } -static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { +static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { assert(!E->isValueDependent() && "Should not see value dependent exprs!"); if (!E->getType()->isIntegralOrEnumerationType()) return ICEDiag(IK_NotICE, E->getLocStart()); @@ -7250,6 +8271,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::UnresolvedLookupExprClass: case Expr::DependentScopeDeclRefExprClass: case Expr::CXXConstructExprClass: + case Expr::CXXStdInitializerListExprClass: case Expr::CXXBindTemporaryExprClass: case Expr::ExprWithCleanupsClass: case Expr::CXXTemporaryObjectExprClass: @@ -7269,6 +8291,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::ObjCSubscriptRefExprClass: case Expr::ObjCIsaExprClass: case Expr::ShuffleVectorExprClass: + case Expr::ConvertVectorExprClass: case Expr::BlockExprClass: case Expr::NoStmtClass: case Expr::OpaqueValueExprClass: @@ -7561,7 +8584,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CXXDefaultInitExprClass: return CheckICE(cast(E)->getExpr(), Ctx); case Expr::ChooseExprClass: { - return CheckICE(cast(E)->getChosenSubExpr(Ctx), Ctx); + return CheckICE(cast(E)->getChosenSubExpr(), Ctx); } } @@ -7569,7 +8592,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { } /// Evaluate an expression as a C++11 integral constant expression. -static bool EvaluateCPlusPlus11IntegralConstantExpr(ASTContext &Ctx, +static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx, const Expr *E, llvm::APSInt *Value, SourceLocation *Loc) { @@ -7587,7 +8610,8 @@ static bool EvaluateCPlusPlus11IntegralConstantExpr(ASTContext &Ctx, return true; } -bool Expr::isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const { +bool Expr::isIntegerConstantExpr(const ASTContext &Ctx, + SourceLocation *Loc) const { if (Ctx.getLangOpts().CPlusPlus11) return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, 0, Loc); @@ -7599,7 +8623,7 @@ bool Expr::isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const { return true; } -bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, ASTContext &Ctx, +bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx, SourceLocation *Loc, bool isEvaluated) const { if (Ctx.getLangOpts().CPlusPlus11) return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc); @@ -7611,11 +8635,11 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, ASTContext &Ctx, return true; } -bool Expr::isCXX98IntegralConstantExpr(ASTContext &Ctx) const { +bool Expr::isCXX98IntegralConstantExpr(const ASTContext &Ctx) const { return CheckICE(this, Ctx).Kind == IK_ICE; } -bool Expr::isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result, +bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result, SourceLocation *Loc) const { // We support this checking in C++98 mode in order to diagnose compatibility // issues. @@ -7625,7 +8649,7 @@ bool Expr::isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result, Expr::EvalStatus Status; SmallVector Diags; Status.Diag = &Diags; - EvalInfo Info(Ctx, Status); + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); APValue Scratch; bool IsConstExpr = ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch); @@ -7653,13 +8677,13 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, Expr::EvalStatus Status; Status.Diag = &Diags; - EvalInfo Info(FD->getASTContext(), Status); - Info.CheckingPotentialConstantExpression = true; + EvalInfo Info(FD->getASTContext(), Status, + EvalInfo::EM_PotentialConstantExpression); const CXXMethodDecl *MD = dyn_cast(FD); const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : 0; - // FIXME: Fabricate an arbitrary expression on the stack and pretend that it + // Fabricate an arbitrary expression on the stack and pretend that it // is a temporary being used as the 'this' pointer. LValue This; ImplicitValueInitExpr VIE(RD ? Info.Ctx.getRecordType(RD) : Info.Ctx.IntTy); @@ -7670,9 +8694,12 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, SourceLocation Loc = FD->getLocation(); APValue Scratch; - if (const CXXConstructorDecl *CD = dyn_cast(FD)) + if (const CXXConstructorDecl *CD = dyn_cast(FD)) { + // Evaluate the call as a constant initializer, to allow the construction + // of objects of non-literal types. + Info.setEvaluatingDecl(This.getLValueBase(), Scratch); HandleConstructorCall(Loc, This, Args, CD, Info, Scratch); - else + } else HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : 0, Args, FD->getBody(), Info, Scratch); diff --git a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp index e03632a..3d64310 100644 --- a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp +++ b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp @@ -17,9 +17,11 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/TypeOrdering.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/GraphWriter.h" #include "llvm/Support/raw_ostream.h" #include +#include using namespace llvm; @@ -135,34 +137,28 @@ InheritanceHierarchyWriter::WriteNodeReference(QualType Type, /// class using GraphViz. void CXXRecordDecl::viewInheritance(ASTContext& Context) const { QualType Self = Context.getTypeDeclType(this); - std::string ErrMsg; - sys::Path Filename = sys::Path::GetTemporaryDirectory(&ErrMsg); - if (Filename.isEmpty()) { - llvm::errs() << "Error: " << ErrMsg << "\n"; - return; - } - Filename.appendComponent(Self.getAsString() + ".dot"); - if (Filename.makeUnique(true,&ErrMsg)) { - llvm::errs() << "Error: " << ErrMsg << "\n"; + + int FD; + SmallString<128> Filename; + error_code EC = + sys::fs::createTemporaryFile(Self.getAsString(), "dot", FD, Filename); + if (EC) { + llvm::errs() << "Error: " << EC.message() << "\n"; return; } - llvm::errs() << "Writing '" << Filename.c_str() << "'... "; + llvm::errs() << "Writing '" << Filename << "'... "; - llvm::raw_fd_ostream O(Filename.c_str(), ErrMsg); + llvm::raw_fd_ostream O(FD, true); - if (ErrMsg.empty()) { - InheritanceHierarchyWriter Writer(Context, O); - Writer.WriteGraph(Self); - llvm::errs() << " done. \n"; + InheritanceHierarchyWriter Writer(Context, O); + Writer.WriteGraph(Self); + llvm::errs() << " done. \n"; - O.close(); + O.close(); - // Display the graph - DisplayGraph(Filename); - } else { - llvm::errs() << "error opening file for writing!\n"; - } + // Display the graph + DisplayGraph(Filename); } } diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp index 894eb3b..5784660 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp @@ -20,6 +20,7 @@ #include "CXXABI.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/MangleNumberingContext.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/Type.h" #include "clang/Basic/TargetInfo.h" @@ -27,6 +28,19 @@ using namespace clang; namespace { + +/// \brief Keeps track of the mangled names of lambda expressions and block +/// literals within a particular context. +class ItaniumNumberingContext : public MangleNumberingContext { + llvm::DenseMap VarManglingNumbers; + +public: + /// Variable decls are numbered by identifier. + virtual unsigned getManglingNumber(const VarDecl *VD) { + return ++VarManglingNumbers[VD->getIdentifier()]; + } +}; + class ItaniumCXXABI : public CXXABI { protected: ASTContext &Context; @@ -61,6 +75,10 @@ public: Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); return Layout.getNonVirtualSize() == PointerSize; } + + virtual MangleNumberingContext *createMangleNumberingContext() const { + return new ItaniumNumberingContext(); + } }; class ARMCXXABI : public ItaniumCXXABI { diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index 5ad8021..0621d7b 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -56,23 +56,36 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) { = dyn_cast_or_null(RD->getLambdaContextDecl())) return ContextParam->getDeclContext(); } + + // Perform the same check for block literals. + if (const BlockDecl *BD = dyn_cast(D)) { + if (ParmVarDecl *ContextParam + = dyn_cast_or_null(BD->getBlockManglingContextDecl())) + return ContextParam->getDeclContext(); + } - return D->getDeclContext(); + const DeclContext *DC = D->getDeclContext(); + if (const CapturedDecl *CD = dyn_cast(DC)) + return getEffectiveDeclContext(CD); + + return DC; } static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { return getEffectiveDeclContext(cast(DC)); } - -static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) { - const DeclContext *DC = dyn_cast(ND); - if (!DC) - DC = getEffectiveDeclContext(ND); + +static bool isLocalContainerContext(const DeclContext *DC) { + return isa(DC) || isa(DC) || isa(DC); +} + +static const RecordDecl *GetLocalClassDecl(const Decl *D) { + const DeclContext *DC = getEffectiveDeclContext(D); while (!DC->isNamespace() && !DC->isTranslationUnit()) { - const DeclContext *Parent = getEffectiveDeclContext(cast(DC)); - if (isa(Parent)) - return dyn_cast(DC); - DC = Parent; + if (isLocalContainerContext(DC)) + return dyn_cast(D); + D = cast(DC); + DC = getEffectiveDeclContext(D); } return 0; } @@ -91,15 +104,16 @@ static const NamedDecl *getStructor(const NamedDecl *decl) { static const unsigned UnknownArity = ~0U; -class ItaniumMangleContext : public MangleContext { +class ItaniumMangleContextImpl : public ItaniumMangleContext { llvm::DenseMap AnonStructIds; - unsigned Discriminator; + typedef std::pair DiscriminatorKeyTy; + llvm::DenseMap Discriminator; llvm::DenseMap Uniquifier; public: - explicit ItaniumMangleContext(ASTContext &Context, - DiagnosticsEngine &Diags) - : MangleContext(Context, Diags) { } + explicit ItaniumMangleContextImpl(ASTContext &Context, + DiagnosticsEngine &Diags) + : ItaniumMangleContext(Context, Diags) {} uint64_t getAnonymousStructId(const TagDecl *TD) { std::pairsecond; } - void startNewFunction() { - MangleContext::startNewFunction(); - mangleInitDiscriminator(); - } - /// @name Mangler Entry Points /// @{ - bool shouldMangleDeclName(const NamedDecl *D); - void mangleName(const NamedDecl *D, raw_ostream &); + bool shouldMangleCXXName(const NamedDecl *D); + void mangleCXXName(const NamedDecl *D, raw_ostream &); void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, raw_ostream &); @@ -135,30 +144,45 @@ public: raw_ostream &); void mangleCXXRTTI(QualType T, raw_ostream &); void mangleCXXRTTIName(QualType T, raw_ostream &); + void mangleTypeName(QualType T, raw_ostream &); void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, raw_ostream &); void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, raw_ostream &); - void mangleItaniumGuardVariable(const VarDecl *D, raw_ostream &); + void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &); + void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out); + void mangleDynamicAtExitDestructor(const VarDecl *D, raw_ostream &Out); void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &); void mangleItaniumThreadLocalWrapper(const VarDecl *D, raw_ostream &); - void mangleInitDiscriminator() { - Discriminator = 0; - } - bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { - // Lambda closure types with external linkage (indicated by a - // non-zero lambda mangling number) have their own numbering scheme, so - // they do not need a discriminator. + // Lambda closure types are already numbered. if (const CXXRecordDecl *RD = dyn_cast(ND)) - if (RD->isLambda() && RD->getLambdaManglingNumber() > 0) + if (RD->isLambda()) return false; - + + // Anonymous tags are already numbered. + if (const TagDecl *Tag = dyn_cast(ND)) { + if (Tag->getName().empty() && !Tag->getTypedefNameForAnonDecl()) + return false; + } + + // Use the canonical number for externally visible decls. + if (ND->isExternallyVisible()) { + unsigned discriminator = getASTContext().getManglingNumber(ND); + if (discriminator == 1) + return false; + disc = discriminator - 2; + return true; + } + + // Make up a reasonable number for internal decls. unsigned &discriminator = Uniquifier[ND]; - if (!discriminator) - discriminator = ++Discriminator; + if (!discriminator) { + const DeclContext *DC = getEffectiveDeclContext(ND); + discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())]; + } if (discriminator == 1) return false; disc = discriminator-2; @@ -169,7 +193,7 @@ public: /// CXXNameMangler - Manage the mangling of a single name. class CXXNameMangler { - ItaniumMangleContext &Context; + ItaniumMangleContextImpl &Context; raw_ostream &Out; /// The "structor" is the top-level declaration being mangled, if @@ -225,7 +249,7 @@ class CXXNameMangler { ASTContext &getASTContext() const { return Context.getASTContext(); } public: - CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_, + CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const NamedDecl *D = 0) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0), SeqID(0) { @@ -233,11 +257,11 @@ public: assert(!D || (!isa(D) && !isa(D))); } - CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_, + CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const CXXConstructorDecl *D, CXXCtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), SeqID(0) { } - CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_, + CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const CXXDestructorDecl *D, CXXDtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), SeqID(0) { } @@ -305,7 +329,9 @@ private: void mangleUnscopedTemplateName(const TemplateDecl *ND); void mangleUnscopedTemplateName(TemplateName); void mangleSourceName(const IdentifierInfo *II); - void mangleLocalName(const NamedDecl *ND); + void mangleLocalName(const Decl *D); + void mangleBlockForPrefix(const BlockDecl *Block); + void mangleUnqualifiedBlock(const BlockDecl *Block); void mangleLambda(const CXXRecordDecl *Lambda); void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, bool NoFunction=false); @@ -315,7 +341,7 @@ private: void manglePrefix(NestedNameSpecifier *qualifier); void manglePrefix(const DeclContext *DC, bool NoFunction=false); void manglePrefix(QualType type); - void mangleTemplatePrefix(const TemplateDecl *ND); + void mangleTemplatePrefix(const TemplateDecl *ND, bool NoFunction=false); void mangleTemplatePrefix(TemplateName Template); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); void mangleQualifiers(Qualifiers Quals); @@ -334,6 +360,7 @@ private: void mangleBareFunctionType(const FunctionType *T, bool MangleReturnType); void mangleNeonVectorType(const VectorType *T); + void mangleAArch64NeonVectorType(const VectorType *T); void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value); void mangleMemberExpr(const Expr *base, bool isArrow, @@ -358,16 +385,7 @@ private: } -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()) - return false; - - // Any decl can be declared with __asm("foo") on it, and this takes precedence - // over all other naming in the .o file. - if (D->hasAttr()) - return true; - +bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { const FunctionDecl *FD = dyn_cast(D); if (FD) { LanguageLinkage L = FD->getLanguageLinkage(); @@ -405,7 +423,8 @@ bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { if (DC->isFunctionOrMethod() && D->hasLinkage()) while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = getEffectiveParentContext(DC); - if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage) + if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage && + !isa(D)) return false; } @@ -413,26 +432,6 @@ bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { } void CXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { - // Any decl can be declared with __asm("foo") on it, and this takes precedence - // over all other naming in the .o file. - if (const AsmLabelAttr *ALA = D->getAttr()) { - // If we have an asm name, then we use it as the mangling. - - // Adding the prefix can cause problems when one file has a "foo" and - // another has a "\01foo". That is known to happen on ELF with the - // tricks normally used for producing aliases (PR9177). Fortunately the - // llvm mangler on ELF is a nop, so we can just avoid adding the \01 - // marker. We also avoid adding the marker if this is an alias for an - // LLVM intrinsic. - StringRef UserLabelPrefix = - getASTContext().getTargetInfo().getUserLabelPrefix(); - if (!UserLabelPrefix.empty() && !ALA->getLabel().startswith("llvm.")) - Out << '\01'; // LLVM IR Marker for __asm("foo") - - Out << ALA->getLabel(); - return; - } - // ::= _Z // ::= // ::= @@ -441,6 +440,8 @@ void CXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { mangleFunctionEncoding(FD); else if (const VarDecl *VD = dyn_cast(D)) mangleName(VD); + else if (const IndirectFieldDecl *IFD = dyn_cast(D)) + mangleName(IFD->getAnonField()); else mangleName(cast(D)); } @@ -527,6 +528,13 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { return Spec->getSpecializedTemplate(); } + // Check if we have a variable template. + if (const VarTemplateSpecializationDecl *Spec = + dyn_cast(ND)) { + TemplateArgs = &Spec->getTemplateArgs(); + return Spec->getSpecializedTemplate(); + } + return 0; } @@ -550,7 +558,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { // is that of the containing namespace, or the translation unit. // FIXME: This is a hack; extern variables declared locally should have // a proper semantic declaration context! - if (isa(DC) && ND->hasLinkage() && !isLambda(ND)) + if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND)) while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { @@ -573,7 +581,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { return; } - if (isa(DC) || isa(DC)) { + if (isLocalContainerContext(DC)) { mangleLocalName(ND); return; } @@ -825,6 +833,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, switch (type->getTypeClass()) { case Type::Builtin: case Type::Complex: + case Type::Decayed: case Type::Pointer: case Type::BlockPointer: case Type::LValueReference: @@ -1053,7 +1062,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // static void foo(); // This naming convention is the same as that followed by GCC, // though it shouldn't actually matter. - if (ND && ND->getLinkage() == InternalLinkage && + if (ND && ND->getFormalLinkage() == InternalLinkage && getEffectiveDeclContext(ND)->isFileContext()) Out << 'L'; @@ -1129,11 +1138,11 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } } - int UnnamedMangle = Context.getASTContext().getUnnamedTagManglingNumber(TD); - if (UnnamedMangle != -1) { + if (TD->isExternallyVisible()) { + unsigned UnnamedMangle = getASTContext().getManglingNumber(TD); Out << "Ut"; - if (UnnamedMangle != 0) - Out << llvm::utostr(UnnamedMangle - 1); + if (UnnamedMangle > 1) + Out << llvm::utostr(UnnamedMangle - 2); Out << '_'; break; } @@ -1231,14 +1240,19 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, Out << 'N'; if (const CXXMethodDecl *Method = dyn_cast(ND)) { - mangleQualifiers(Qualifiers::fromCVRMask(Method->getTypeQualifiers())); + Qualifiers MethodQuals = + Qualifiers::fromCVRMask(Method->getTypeQualifiers()); + // We do not consider restrict a distinguishing attribute for overloading + // purposes so we must not mangle it. + MethodQuals.removeRestrict(); + mangleQualifiers(MethodQuals); mangleRefQualifier(Method->getRefQualifier()); } // Check if we have a template. const TemplateArgumentList *TemplateArgs = 0; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { - mangleTemplatePrefix(TD); + mangleTemplatePrefix(TD, NoFunction); mangleTemplateArgs(*TemplateArgs); } else { @@ -1261,36 +1275,37 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD, Out << 'E'; } -void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { +void CXXNameMangler::mangleLocalName(const Decl *D) { // := Z E [] // := Z E s [] // := Z E d [ ] // _ // := _ - const DeclContext *DC = getEffectiveDeclContext(ND); - if (isa(DC) && isa(ND)) { - // Don't add objc method name mangling to locally declared function - mangleUnqualifiedName(ND); - return; - } + assert(isa(D) || isa(D)); + const RecordDecl *RD = GetLocalClassDecl(D); + const DeclContext *DC = getEffectiveDeclContext(RD ? RD : D); Out << 'Z'; - if (const ObjCMethodDecl *MD = dyn_cast(DC)) { - mangleObjCMethodName(MD); - } else if (const CXXRecordDecl *RD = GetLocalClassDecl(ND)) { - mangleFunctionEncoding(cast(getEffectiveDeclContext(RD))); - Out << 'E'; + if (const ObjCMethodDecl *MD = dyn_cast(DC)) + mangleObjCMethodName(MD); + else if (const BlockDecl *BD = dyn_cast(DC)) + mangleBlockForPrefix(BD); + else + mangleFunctionEncoding(cast(DC)); + + Out << 'E'; + if (RD) { // The parameter number is omitted for the last parameter, 0 for the // second-to-last parameter, 1 for the third-to-last parameter, etc. The // will of course contain a : Its // numbering will be local to the particular argument in which it appears // -- other default arguments do not affect its encoding. - bool SkipDiscriminator = false; - if (RD->isLambda()) { + const CXXRecordDecl *CXXRD = dyn_cast(RD); + if (CXXRD->isLambda()) { if (const ParmVarDecl *Parm - = dyn_cast_or_null(RD->getLambdaContextDecl())) { + = dyn_cast_or_null(CXXRD->getLambdaContextDecl())) { if (const FunctionDecl *Func = dyn_cast(Parm->getDeclContext())) { Out << 'd'; @@ -1298,34 +1313,88 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { if (Num > 1) mangleNumber(Num - 2); Out << '_'; - SkipDiscriminator = true; } } } // Mangle the name relative to the closest enclosing function. - if (ND == RD) // equality ok because RD derived from ND above - mangleUnqualifiedName(ND); - else - mangleNestedName(ND, DC, true /*NoFunction*/); - - if (!SkipDiscriminator) { - unsigned disc; - if (Context.getNextDiscriminator(RD, disc)) { - if (disc < 10) - Out << '_' << disc; - else - Out << "__" << disc << '_'; + // equality ok because RD derived from ND above + if (D == RD) { + mangleUnqualifiedName(RD); + } else if (const BlockDecl *BD = dyn_cast(D)) { + manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/); + mangleUnqualifiedBlock(BD); + } else { + const NamedDecl *ND = cast(D); + mangleNestedName(ND, getEffectiveDeclContext(ND), true /*NoFunction*/); + } + } else if (const BlockDecl *BD = dyn_cast(D)) { + // Mangle a block in a default parameter; see above explanation for + // lambdas. + if (const ParmVarDecl *Parm + = dyn_cast_or_null(BD->getBlockManglingContextDecl())) { + if (const FunctionDecl *Func + = dyn_cast(Parm->getDeclContext())) { + Out << 'd'; + unsigned Num = Func->getNumParams() - Parm->getFunctionScopeIndex(); + if (Num > 1) + mangleNumber(Num - 2); + Out << '_'; } } - + + mangleUnqualifiedBlock(BD); + } else { + mangleUnqualifiedName(cast(D)); + } + + if (const NamedDecl *ND = dyn_cast(RD ? RD : D)) { + unsigned disc; + if (Context.getNextDiscriminator(ND, disc)) { + if (disc < 10) + Out << '_' << disc; + else + Out << "__" << disc << '_'; + } + } +} + +void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) { + if (GetLocalClassDecl(Block)) { + mangleLocalName(Block); return; } - else - mangleFunctionEncoding(cast(DC)); + const DeclContext *DC = getEffectiveDeclContext(Block); + if (isLocalContainerContext(DC)) { + mangleLocalName(Block); + return; + } + manglePrefix(getEffectiveDeclContext(Block)); + mangleUnqualifiedBlock(Block); +} - Out << 'E'; - mangleUnqualifiedName(ND); +void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) { + if (Decl *Context = Block->getBlockManglingContextDecl()) { + if ((isa(Context) || isa(Context)) && + Context->getDeclContext()->isRecord()) { + if (const IdentifierInfo *Name + = cast(Context)->getIdentifier()) { + mangleSourceName(Name); + Out << 'M'; + } + } + } + + // If we have a block mangling number, use it. + unsigned Number = Block->getBlockManglingNumber(); + // Otherwise, just make up a number. It doesn't matter what it is because + // the symbol in question isn't externally visible. + if (!Number) + Number = Context.getBlockId(Block, false); + Out << "Ub"; + if (Number > 1) + Out << Number - 2; + Out << '_'; } void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { @@ -1411,16 +1480,11 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { if (DC->isTranslationUnit()) return; - if (const BlockDecl *Block = dyn_cast(DC)) { - manglePrefix(getEffectiveParentContext(DC), NoFunction); - SmallString<64> Name; - llvm::raw_svector_ostream NameStream(Name); - Context.mangleBlock(Block, NameStream); - NameStream.flush(); - Out << Name.size() << Name; + if (NoFunction && isLocalContainerContext(DC)) return; - } - + + assert(!isLocalContainerContext(DC)); + const NamedDecl *ND = cast(DC); if (mangleSubstitution(ND)) return; @@ -1430,12 +1494,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); mangleTemplateArgs(*TemplateArgs); - } - else if(NoFunction && (isa(ND) || isa(ND))) - return; - else if (const ObjCMethodDecl *Method = dyn_cast(ND)) - mangleObjCMethodName(Method); - else { + } else { manglePrefix(getEffectiveDeclContext(ND), NoFunction); mangleUnqualifiedName(ND); } @@ -1466,7 +1525,8 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { mangleUnscopedTemplateName(Template); } -void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) { +void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND, + bool NoFunction) { // ::=