diff options
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/ASTContext.cpp | 223 | ||||
-rw-r--r-- | lib/AST/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 125 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 1 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 39 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 27 | ||||
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 9 | ||||
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 72 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 201 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 26 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 141 | ||||
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 14 | ||||
-rw-r--r-- | lib/AST/RecordLayoutBuilder.h | 2 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 14 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 77 | ||||
-rw-r--r-- | lib/AST/TemplateBase.cpp | 97 | ||||
-rw-r--r-- | lib/AST/TemplateName.cpp | 9 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 161 |
18 files changed, 966 insertions, 273 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7f5fa35..aef3d29 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -22,9 +22,10 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" #include "RecordLayoutBuilder.h" using namespace clang; @@ -138,9 +139,9 @@ void ASTContext::PrintStats() const { } -void ASTContext::InitBuiltinType(QualType &R, BuiltinType::Kind K) { +void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) { BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K); - R = QualType(Ty, 0); + R = CanQualType::CreateUnsafe(QualType(Ty, 0)); Types.push_back(Ty); } @@ -872,6 +873,55 @@ void ASTContext::CollectSynthesizedIvars(const ObjCInterfaceDecl *OI, } } +/// CollectInheritedProtocols - Collect all protocols in current class and +/// those inherited by it. +void ASTContext::CollectInheritedProtocols(const Decl *CDecl, + llvm::SmallVectorImpl<ObjCProtocolDecl*> &Protocols) { + if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) { + for (ObjCInterfaceDecl::protocol_iterator P = OI->protocol_begin(), + PE = OI->protocol_end(); P != PE; ++P) { + ObjCProtocolDecl *Proto = (*P); + Protocols.push_back(Proto); + for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), + PE = Proto->protocol_end(); P != PE; ++P) + CollectInheritedProtocols(*P, Protocols); + } + + // Categories of this Interface. + for (const ObjCCategoryDecl *CDeclChain = OI->getCategoryList(); + CDeclChain; CDeclChain = CDeclChain->getNextClassCategory()) + CollectInheritedProtocols(CDeclChain, Protocols); + if (ObjCInterfaceDecl *SD = OI->getSuperClass()) + while (SD) { + CollectInheritedProtocols(SD, Protocols); + SD = SD->getSuperClass(); + } + return; + } + if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) { + for (ObjCInterfaceDecl::protocol_iterator P = OC->protocol_begin(), + PE = OC->protocol_end(); P != PE; ++P) { + ObjCProtocolDecl *Proto = (*P); + Protocols.push_back(Proto); + for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), + PE = Proto->protocol_end(); P != PE; ++P) + CollectInheritedProtocols(*P, Protocols); + } + return; + } + if (const ObjCProtocolDecl *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) { + for (ObjCProtocolDecl::protocol_iterator P = OP->protocol_begin(), + PE = OP->protocol_end(); P != PE; ++P) { + ObjCProtocolDecl *Proto = (*P); + Protocols.push_back(Proto); + for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), + PE = Proto->protocol_end(); P != PE; ++P) + CollectInheritedProtocols(*P, Protocols); + } + return; + } +} + unsigned ASTContext::CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD) { unsigned count = 0; for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(), @@ -955,6 +1005,13 @@ DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T, return DInfo; } +DeclaratorInfo *ASTContext::getTrivialDeclaratorInfo(QualType T, + SourceLocation L) { + DeclaratorInfo *DI = CreateDeclaratorInfo(T); + DI->getTypeLoc().initialize(L); + return DI; +} + /// getInterfaceLayoutImpl - Get or compute information about the /// layout of the given interface. /// @@ -1757,6 +1814,19 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, QualType ASTContext::getTemplateSpecializationType(TemplateName Template, + const TemplateArgumentLoc *Args, + unsigned NumArgs, + QualType Canon) { + llvm::SmallVector<TemplateArgument, 4> ArgVec; + ArgVec.reserve(NumArgs); + for (unsigned i = 0; i != NumArgs; ++i) + ArgVec.push_back(Args[i].getArgument()); + + return getTemplateSpecializationType(Template, ArgVec.data(), NumArgs, Canon); +} + +QualType +ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgument *Args, unsigned NumArgs, QualType Canon) { @@ -2235,7 +2305,7 @@ CanQualType ASTContext::getCanonicalType(QualType T) { DSAT->getSizeExpr()->Retain() : 0, DSAT->getSizeModifier(), DSAT->getIndexTypeCVRQualifiers(), - DSAT->getBracketsRange())); + DSAT->getBracketsRange())->getCanonicalTypeInternal()); VariableArrayType *VAT = cast<VariableArrayType>(AT); return CanQualType::CreateUnsafe(getVariableArrayType(NewEltTy, @@ -2290,17 +2360,14 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) { return Arg; case TemplateArgument::Declaration: - return TemplateArgument(SourceLocation(), - Arg.getAsDecl()->getCanonicalDecl()); + return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl()); case TemplateArgument::Integral: - return TemplateArgument(SourceLocation(), - *Arg.getAsIntegral(), + return TemplateArgument(*Arg.getAsIntegral(), getCanonicalType(Arg.getIntegralType())); case TemplateArgument::Type: - return TemplateArgument(SourceLocation(), - getCanonicalType(Arg.getAsType())); + return TemplateArgument(getCanonicalType(Arg.getAsType())); case TemplateArgument::Pack: { // FIXME: Allocate in ASTContext @@ -2847,12 +2914,13 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) { bool HasCopyAndDispose = BlockRequiresCopying(Ty); // FIXME: Move up - static int UniqueBlockByRefTypeID = 0; - char Name[36]; - sprintf(Name, "__Block_byref_%d_%s", ++UniqueBlockByRefTypeID, DeclName); + static unsigned int UniqueBlockByRefTypeID = 0; + llvm::SmallString<36> Name; + llvm::raw_svector_ostream(Name) << "__Block_byref_" << + ++UniqueBlockByRefTypeID << '_' << DeclName; RecordDecl *T; T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), - &Idents.get(Name)); + &Idents.get(Name.str())); T->startDefinition(); QualType Int32Ty = IntTy; assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported"); @@ -2896,12 +2964,13 @@ QualType ASTContext::getBlockParmType( bool BlockHasCopyDispose, llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls) { // FIXME: Move up - static int UniqueBlockParmTypeID = 0; - char Name[36]; - sprintf(Name, "__block_literal_%u", ++UniqueBlockParmTypeID); + static unsigned int UniqueBlockParmTypeID = 0; + llvm::SmallString<36> Name; + llvm::raw_svector_ostream(Name) << "__block_literal_" + << ++UniqueBlockParmTypeID; RecordDecl *T; T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), - &Idents.get(Name)); + &Idents.get(Name.str())); QualType FieldTypes[] = { getPointerType(VoidPtrTy), IntTy, @@ -3409,7 +3478,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, return; } - if (OPT->isObjCClassType()) { + if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) { + // FIXME: Consider if we need to output qualifiers for 'Class<p>'. + // Since this is a binary compatibility issue, need to consult with runtime + // folks. Fortunately, this is a *very* obsure construct. S += '#'; return; } @@ -3447,9 +3519,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } S += '@'; - if (FD || EncodingProperty) { + if (OPT->getInterfaceDecl() && (FD || EncodingProperty)) { S += '"'; - S += OPT->getInterfaceDecl()->getNameAsCString(); + S += OPT->getInterfaceDecl()->getIdentifier()->getName(); for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), E = OPT->qual_end(); I != E; ++I) { S += '<'; @@ -3590,12 +3662,42 @@ TemplateName ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, return TemplateName(QTN); } +/// \brief Retrieve the template name that represents a dependent +/// template name such as \c MetaFun::template operator+. +TemplateName +ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, + OverloadedOperatorKind Operator) { + assert((!NNS || NNS->isDependent()) && + "Nested name specifier must be dependent"); + + llvm::FoldingSetNodeID ID; + DependentTemplateName::Profile(ID, NNS, Operator); + + void *InsertPos = 0; + DependentTemplateName *QTN = + DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); + + if (QTN) + return TemplateName(QTN); + + NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); + if (CanonNNS == NNS) { + QTN = new (*this,4) DependentTemplateName(NNS, Operator); + } else { + TemplateName Canon = getDependentTemplateName(CanonNNS, Operator); + QTN = new (*this,4) DependentTemplateName(NNS, Operator, Canon); + } + + DependentTemplateNames.InsertNode(QTN, InsertPos); + return TemplateName(QTN); +} + /// getFromTargetType - Given one of the integer types provided by /// TargetInfo, produce the corresponding type. The unsigned @p Type /// is actually a value of type @c TargetInfo::IntType. -QualType ASTContext::getFromTargetType(unsigned Type) const { +CanQualType ASTContext::getFromTargetType(unsigned Type) const { switch (Type) { - case TargetInfo::NoInt: return QualType(); + case TargetInfo::NoInt: return CanQualType(); case TargetInfo::SignedShort: return ShortTy; case TargetInfo::UnsignedShort: return UnsignedShortTy; case TargetInfo::SignedInt: return IntTy; @@ -3607,7 +3709,7 @@ QualType ASTContext::getFromTargetType(unsigned Type) const { } assert(false && "Unhandled TargetInfo::IntType value"); - return QualType(); + return CanQualType(); } //===----------------------------------------------------------------------===// @@ -3836,6 +3938,79 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, return false; } +/// getIntersectionOfProtocols - This routine finds the intersection of set +/// of protocols inherited from two distinct objective-c pointer objects. +/// It is used to build composite qualifier list of the composite type of +/// the conditional expression involving two objective-c pointer objects. +static +void getIntersectionOfProtocols(ASTContext &Context, + const ObjCObjectPointerType *LHSOPT, + const ObjCObjectPointerType *RHSOPT, + llvm::SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) { + + const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType(); + const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType(); + + llvm::SmallPtrSet<ObjCProtocolDecl *, 8> InheritedProtocolSet; + unsigned LHSNumProtocols = LHS->getNumProtocols(); + if (LHSNumProtocols > 0) + InheritedProtocolSet.insert(LHS->qual_begin(), LHS->qual_end()); + else { + llvm::SmallVector<ObjCProtocolDecl *, 8> LHSInheritedProtocols; + Context.CollectInheritedProtocols(LHS->getDecl(), LHSInheritedProtocols); + InheritedProtocolSet.insert(LHSInheritedProtocols.begin(), + LHSInheritedProtocols.end()); + } + + unsigned RHSNumProtocols = RHS->getNumProtocols(); + if (RHSNumProtocols > 0) { + ObjCProtocolDecl **RHSProtocols = (ObjCProtocolDecl **)RHS->qual_begin(); + for (unsigned i = 0; i < RHSNumProtocols; ++i) + if (InheritedProtocolSet.count(RHSProtocols[i])) + IntersectionOfProtocols.push_back(RHSProtocols[i]); + } + else { + llvm::SmallVector<ObjCProtocolDecl *, 8> RHSInheritedProtocols; + Context.CollectInheritedProtocols(RHS->getDecl(), RHSInheritedProtocols); + // FIXME. This may cause duplication of protocols in the list, but should + // be harmless. + for (unsigned i = 0, len = RHSInheritedProtocols.size(); i < len; ++i) + if (InheritedProtocolSet.count(RHSInheritedProtocols[i])) + IntersectionOfProtocols.push_back(RHSInheritedProtocols[i]); + } +} + +/// areCommonBaseCompatible - Returns common base class of the two classes if +/// one found. Note that this is O'2 algorithm. But it will be called as the +/// last type comparison in a ?-exp of ObjC pointer types before a +/// warning is issued. So, its invokation is extremely rare. +QualType ASTContext::areCommonBaseCompatible( + const ObjCObjectPointerType *LHSOPT, + const ObjCObjectPointerType *RHSOPT) { + const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType(); + const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType(); + if (!LHS || !RHS) + return QualType(); + + while (const ObjCInterfaceDecl *LHSIDecl = LHS->getDecl()->getSuperClass()) { + QualType LHSTy = getObjCInterfaceType(LHSIDecl); + LHS = LHSTy->getAs<ObjCInterfaceType>(); + if (canAssignObjCInterfaces(LHS, RHS)) { + llvm::SmallVector<ObjCProtocolDecl *, 8> IntersectionOfProtocols; + getIntersectionOfProtocols(*this, + LHSOPT, RHSOPT, IntersectionOfProtocols); + if (IntersectionOfProtocols.empty()) + LHSTy = getObjCObjectPointerType(LHSTy); + else + LHSTy = getObjCObjectPointerType(LHSTy, &IntersectionOfProtocols[0], + IntersectionOfProtocols.size()); + return LHSTy; + } + } + + return QualType(); +} + bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS, const ObjCInterfaceType *RHS) { // Verify that the base decls are compatible: the RHS must be a subclass of diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 20e1150..e541406 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -26,6 +26,7 @@ add_clang_library(clangAST StmtPrinter.cpp StmtProfile.cpp StmtViz.cpp + TemplateBase.cpp TemplateName.cpp Type.cpp TypeLoc.cpp diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index d270a95..a6996a4 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -91,13 +91,6 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, DInfo, S, DefArg); } -QualType ParmVarDecl::getOriginalType() const { - if (const OriginalParmVarDecl *PVD = - dyn_cast<OriginalParmVarDecl>(this)) - return PVD->OriginalType; - return getType(); -} - SourceRange ParmVarDecl::getDefaultArgRange() const { if (const Expr *E = getInit()) return E->getSourceRange(); @@ -140,14 +133,6 @@ bool VarDecl::isExternC() const { return false; } -OriginalParmVarDecl *OriginalParmVarDecl::Create( - ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - QualType T, DeclaratorInfo *DInfo, - QualType OT, StorageClass S, Expr *DefArg) { - return new (C) OriginalParmVarDecl(DC, L, Id, T, DInfo, OT, S, DefArg); -} - FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, @@ -193,9 +178,9 @@ void EnumConstantDecl::Destroy(ASTContext& C) { } TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - IdentifierInfo *Id, QualType T) { - return new (C) TypedefDecl(DC, L, Id, T); + SourceLocation L, IdentifierInfo *Id, + DeclaratorInfo *DInfo) { + return new (C) TypedefDecl(DC, L, Id, DInfo); } EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -398,6 +383,19 @@ bool VarDecl::isOutOfLine() const { return false; } +VarDecl *VarDecl::getOutOfLineDefinition() { + if (!isStaticDataMember()) + return 0; + + for (VarDecl::redecl_iterator RD = redecls_begin(), RDEnd = redecls_end(); + RD != RDEnd; ++RD) { + if (RD->getLexicalDeclContext()->isFileContext()) + return *RD; + } + + return 0; +} + VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const { if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) return cast<VarDecl>(MSI->getInstantiatedFrom()); @@ -644,7 +642,34 @@ unsigned FunctionDecl::getMinRequiredArguments() const { return NumRequiredArgs; } -/// \brief For an inline function definition in C, determine whether the +bool FunctionDecl::isInlined() const { + if (isInlineSpecified() || (isa<CXXMethodDecl>(this) && !isOutOfLine())) + return true; + + switch (getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + return false; + + case TSK_ImplicitInstantiation: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + // Handle below. + break; + } + + const FunctionDecl *PatternDecl = getTemplateInstantiationPattern(); + Stmt *Pattern = 0; + if (PatternDecl) + Pattern = PatternDecl->getBody(PatternDecl); + + if (Pattern && PatternDecl) + return PatternDecl->isInlined(); + + return false; +} + +/// \brief For an inline function definition in C or C++, determine whether the /// definition will be externally visible. /// /// Inline function definitions are always available for inlining optimizations. @@ -663,9 +688,10 @@ unsigned FunctionDecl::getMinRequiredArguments() const { /// externally visible symbol. bool FunctionDecl::isInlineDefinitionExternallyVisible() const { assert(isThisDeclarationADefinition() && "Must have the function definition"); - assert(isInline() && "Function must be inline"); + assert(isInlined() && "Function must be inline"); + ASTContext &Context = getASTContext(); - if (!getASTContext().getLangOptions().C99 || hasAttr<GNUInlineAttr>()) { + if (!Context.getLangOptions().C99 || hasAttr<GNUInlineAttr>()) { // GNU inline semantics. Based on a number of examples, we came up with the // following heuristic: if the "inline" keyword is present on a // declaration of the function but "extern" is not present on that @@ -675,7 +701,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end(); Redecl != RedeclEnd; ++Redecl) { - if (Redecl->isInline() && Redecl->getStorageClass() != Extern) + if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != Extern) return true; } @@ -694,7 +720,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { if (!Redecl->getLexicalDeclContext()->isTranslationUnit()) continue; - if (!Redecl->isInline() || Redecl->getStorageClass() == Extern) + if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == Extern) return true; // Not an inline definition } @@ -755,6 +781,59 @@ FunctionDecl::setInstantiationOfMemberFunction(FunctionDecl *FD, TemplateOrSpecialization = Info; } +bool FunctionDecl::isImplicitlyInstantiable() const { + // If this function already has a definition or is invalid, it can't be + // implicitly instantiated. + if (isInvalidDecl() || getBody()) + return false; + + switch (getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + case TSK_ExplicitInstantiationDefinition: + return false; + + case TSK_ImplicitInstantiation: + return true; + + case TSK_ExplicitInstantiationDeclaration: + // Handled below. + break; + } + + // Find the actual template from which we will instantiate. + const FunctionDecl *PatternDecl = getTemplateInstantiationPattern(); + Stmt *Pattern = 0; + if (PatternDecl) + Pattern = PatternDecl->getBody(PatternDecl); + + // C++0x [temp.explicit]p9: + // Except for inline functions, other explicit instantiation declarations + // have the effect of suppressing the implicit instantiation of the entity + // to which they refer. + if (!Pattern || !PatternDecl) + return true; + + return PatternDecl->isInlined(); +} + +FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { + while (Primary->getInstantiatedFromMemberTemplate()) { + // If we have hit a point where the user provided a specialization of + // this template, we're done looking. + if (Primary->isMemberSpecialization()) + break; + + Primary = Primary->getInstantiatedFromMemberTemplate(); + } + + return Primary->getTemplatedDecl(); + } + + return getInstantiatedFromMemberFunction(); +} + FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { if (FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 224bf87..6cfdcdd 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -199,7 +199,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Var: case ImplicitParam: case ParmVar: - case OriginalParmVar: case NonTypeTemplateParm: case Using: case UnresolvedUsing: diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 457f4c8..b4c0c59 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -189,7 +189,10 @@ bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context, // A user-declared copy assignment operator is a non-static non-template // member function of class X with exactly one parameter of type X, X&, // const X&, volatile X& or const volatile X&. - const CXXMethodDecl* Method = cast<CXXMethodDecl>(*Op); + const CXXMethodDecl* Method = dyn_cast<CXXMethodDecl>(*Op); + if (!Method) + continue; + if (Method->isStatic()) continue; if (Method->getPrimaryTemplate()) @@ -364,34 +367,36 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD, } } } - + if (getNumBases() == 0 && getNumVBases() == 0) return; - + llvm::SmallPtrSet<CanQualType, 8> ConversionFunctions; if (!inTopClass) collectConversionFunctions(ConversionFunctions); - + for (CXXRecordDecl::base_class_iterator VBase = vbases_begin(), E = vbases_end(); VBase != E; ++VBase) { - CXXRecordDecl *VBaseClassDecl - = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); - VBaseClassDecl->getNestedVisibleConversionFunctions(RD, - TopConversionsTypeSet, - (inTopClass ? TopConversionsTypeSet : ConversionFunctions)); - + if (const RecordType *RT = VBase->getType()->getAs<RecordType>()) { + CXXRecordDecl *VBaseClassDecl + = cast<CXXRecordDecl>(RT->getDecl()); + VBaseClassDecl->getNestedVisibleConversionFunctions(RD, + TopConversionsTypeSet, + (inTopClass ? TopConversionsTypeSet : ConversionFunctions)); + } } for (CXXRecordDecl::base_class_iterator Base = bases_begin(), E = bases_end(); Base != E; ++Base) { if (Base->isVirtual()) continue; - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - - BaseClassDecl->getNestedVisibleConversionFunctions(RD, - TopConversionsTypeSet, - (inTopClass ? TopConversionsTypeSet : ConversionFunctions)); - + if (const RecordType *RT = Base->getType()->getAs<RecordType>()) { + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(RT->getDecl()); + + BaseClassDecl->getNestedVisibleConversionFunctions(RD, + TopConversionsTypeSet, + (inTopClass ? TopConversionsTypeSet : ConversionFunctions)); + } } } diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 7f38ac1..7b48b72 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -118,6 +118,27 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { return 0; } +/// FindPropertyVisibleInPrimaryClass - Finds declaration of the property +/// with name 'PropertyId' in the primary class; including those in protocols +/// (direct or indirect) used by the promary class. +/// FIXME: Convert to DeclContext lookup... +/// +ObjCPropertyDecl * +ObjCContainerDecl::FindPropertyVisibleInPrimaryClass( + IdentifierInfo *PropertyId) const { + assert(isa<ObjCInterfaceDecl>(this) && "FindPropertyVisibleInPrimaryClass"); + for (prop_iterator I = prop_begin(), E = prop_end(); I != E; ++I) + if ((*I)->getIdentifier() == PropertyId) + return *I; + const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(this); + // Look through protocols. + for (ObjCInterfaceDecl::protocol_iterator I = OID->protocol_begin(), + E = OID->protocol_end(); I != E; ++I) + if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId)) + return P; + return 0; +} + void ObjCInterfaceDecl::mergeClassExtensionProtocolList( ObjCProtocolDecl *const* ExtList, unsigned ExtNum, ASTContext &C) @@ -288,7 +309,7 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() { } else if (ObjCCategoryImplDecl *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) { - if (ObjCCategoryDecl *CatD = CImplD->getCategoryClass()) + if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) Redecl = CatD->getMethod(getSelector(), isInstanceMethod()); } @@ -306,7 +327,7 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() { } else if (ObjCCategoryImplDecl *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) { - if (ObjCCategoryDecl *CatD = CImplD->getCategoryClass()) + if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) if (ObjCMethodDecl *MD = CatD->getMethod(getSelector(), isInstanceMethod())) return MD; @@ -635,7 +656,7 @@ ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC, return new (C) ObjCCategoryImplDecl(DC, L, Id, ClassInterface); } -ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryClass() const { +ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const { return getClassInterface()->FindCategoryDeclaration(getIdentifier()); } diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 9d0d836..d9d1950 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -52,7 +52,6 @@ namespace { void VisitFieldDecl(FieldDecl *D); void VisitVarDecl(VarDecl *D); void VisitParmVarDecl(ParmVarDecl *D); - void VisitOriginalParmVarDecl(OriginalParmVarDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); void VisitOverloadedFunctionDecl(OverloadedFunctionDecl *D); void VisitNamespaceDecl(NamespaceDecl *D); @@ -324,7 +323,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { case FunctionDecl::PrivateExtern: Out << "__private_extern__ "; break; } - if (D->isInline()) Out << "inline "; + if (D->isInlineSpecified()) Out << "inline "; if (D->isVirtualAsWritten()) Out << "virtual "; } @@ -489,7 +488,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { std::string Name = D->getNameAsString(); QualType T = D->getType(); - if (OriginalParmVarDecl *Parm = dyn_cast<OriginalParmVarDecl>(D)) + if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) T = Parm->getOriginalType(); T.getAsStringInternal(Name, Policy); Out << Name; @@ -508,10 +507,6 @@ void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) { VisitVarDecl(D); } -void DeclPrinter::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) { - VisitVarDecl(D); -} - void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { Out << "__asm ("; D->getAsmString()->printPretty(Out, Context, 0, Policy, Indentation); diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 9a1c654..9ebc91a 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -1,4 +1,4 @@ -//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===// +//===--- DeclTemplate.cpp - Template Declaration AST Node Implementation --===// // // The LLVM Compiler Infrastructure // @@ -15,6 +15,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/STLExtras.h" using namespace clang; @@ -67,6 +68,21 @@ unsigned TemplateParameterList::getMinRequiredArguments() const { return NumRequiredArgs; } +unsigned TemplateParameterList::getDepth() const { + if (size() == 0) + return 0; + + const NamedDecl *FirstParm = getParam(0); + if (const TemplateTypeParmDecl *TTP + = dyn_cast<TemplateTypeParmDecl>(FirstParm)) + return TTP->getDepth(); + else if (const NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(FirstParm)) + return NTTP->getDepth(); + else + return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth(); +} + //===----------------------------------------------------------------------===// // TemplateDecl Implementation //===----------------------------------------------------------------------===// @@ -194,8 +210,7 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) { Param != ParamEnd; ++Param) { if (isa<TemplateTypeParmDecl>(*Param)) { QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param)); - TemplateArgs.push_back(TemplateArgument((*Param)->getLocation(), - ParamType)); + TemplateArgs.push_back(TemplateArgument(ParamType)); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(), @@ -205,7 +220,7 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) { TemplateArgs.push_back(TemplateArgument(E)); } else { TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param); - TemplateArgs.push_back(TemplateArgument(TTP->getLocation(), TTP)); + TemplateArgs.push_back(TemplateArgument(TTP)); } } @@ -229,6 +244,18 @@ TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack); } +SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { + return DefaultArgument->getTypeLoc().getFullSourceRange().getBegin(); +} + +unsigned TemplateTypeParmDecl::getDepth() const { + return TypeForDecl->getAs<TemplateTypeParmType>()->getDepth(); +} + +unsigned TemplateTypeParmDecl::getIndex() const { + return TypeForDecl->getAs<TemplateTypeParmType>()->getIndex(); +} + //===----------------------------------------------------------------------===// // NonTypeTemplateParmDecl Method Implementations //===----------------------------------------------------------------------===// @@ -264,34 +291,6 @@ SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const { } //===----------------------------------------------------------------------===// -// TemplateArgument Implementation -//===----------------------------------------------------------------------===// - -TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) { - TypeOrValue = reinterpret_cast<uintptr_t>(E); - StartLoc = E->getSourceRange().getBegin(); -} - -/// \brief Construct a template argument pack. -void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs, - bool CopyArgs) { - assert(isNull() && "Must call setArgumentPack on a null argument"); - - Kind = Pack; - Args.NumArgs = NumArgs; - Args.CopyArgs = CopyArgs; - if (!Args.CopyArgs) { - Args.Args = args; - return; - } - - // FIXME: Allocate in ASTContext - Args.Args = new TemplateArgument[NumArgs]; - for (unsigned I = 0; I != Args.NumArgs; ++I) - Args.Args[I] = args[I]; -} - -//===----------------------------------------------------------------------===// // TemplateArgumentListBuilder Implementation //===----------------------------------------------------------------------===// @@ -459,12 +458,19 @@ Create(ASTContext &Context, DeclContext *DC, SourceLocation L, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, + TemplateArgumentLoc *ArgInfos, unsigned N, ClassTemplatePartialSpecializationDecl *PrevDecl) { + TemplateArgumentLoc *ClonedArgs = new (Context) TemplateArgumentLoc[N]; + for (unsigned I = 0; I != N; ++I) + ClonedArgs[I] = ArgInfos[I]; + ClassTemplatePartialSpecializationDecl *Result = new (Context)ClassTemplatePartialSpecializationDecl(Context, DC, L, Params, SpecializedTemplate, - Builder, PrevDecl); + Builder, + ClonedArgs, N, + PrevDecl); Result->setSpecializationKind(TSK_ExplicitSpecialization); Context.getTypeDeclType(Result, PrevDecl); return Result; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index a4de3e5..a8ea752 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -22,6 +22,7 @@ #include "clang/AST/StmtVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> using namespace clang; @@ -30,6 +31,91 @@ using namespace clang; // Primary Expressions. //===----------------------------------------------------------------------===// +DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *D, SourceLocation NameLoc, + bool HasExplicitTemplateArgumentList, + SourceLocation LAngleLoc, + const TemplateArgumentLoc *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + SourceLocation RAngleLoc, + QualType T, bool TD, bool VD) + : Expr(DeclRefExprClass, T, TD, VD), + DecoratedD(D, + (Qualifier? HasQualifierFlag : 0) | + (HasExplicitTemplateArgumentList? + HasExplicitTemplateArgumentListFlag : 0)), + Loc(NameLoc) { + if (Qualifier) { + NameQualifier *NQ = getNameQualifier(); + NQ->NNS = Qualifier; + NQ->Range = QualifierRange; + } + + if (HasExplicitTemplateArgumentList) { + ExplicitTemplateArgumentList *ETemplateArgs + = getExplicitTemplateArgumentList(); + ETemplateArgs->LAngleLoc = LAngleLoc; + ETemplateArgs->RAngleLoc = RAngleLoc; + ETemplateArgs->NumTemplateArgs = NumExplicitTemplateArgs; + + TemplateArgumentLoc *TemplateArgs = ETemplateArgs->getTemplateArgs(); + for (unsigned I = 0; I < NumExplicitTemplateArgs; ++I) + new (TemplateArgs + I) TemplateArgumentLoc(ExplicitTemplateArgs[I]); + } +} + +DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *D, + SourceLocation NameLoc, + QualType T, bool TD, bool VD) { + return Create(Context, Qualifier, QualifierRange, D, NameLoc, + false, SourceLocation(), 0, 0, SourceLocation(), + T, TD, VD); +} + +DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *D, + SourceLocation NameLoc, + bool HasExplicitTemplateArgumentList, + SourceLocation LAngleLoc, + const TemplateArgumentLoc *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + SourceLocation RAngleLoc, + QualType T, bool TD, bool VD) { + std::size_t Size = sizeof(DeclRefExpr); + if (Qualifier != 0) + Size += sizeof(NameQualifier); + + if (HasExplicitTemplateArgumentList) + Size += sizeof(ExplicitTemplateArgumentList) + + sizeof(TemplateArgumentLoc) * NumExplicitTemplateArgs; + + void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>()); + return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameLoc, + HasExplicitTemplateArgumentList, + LAngleLoc, + ExplicitTemplateArgs, + NumExplicitTemplateArgs, + RAngleLoc, + T, TD, VD); +} + +SourceRange DeclRefExpr::getSourceRange() const { + // FIXME: Does not handle multi-token names well, e.g., operator[]. + SourceRange R(Loc); + + if (hasQualifier()) + R.setBegin(getQualifierRange().getBegin()); + if (hasExplicitTemplateArgumentList()) + R.setEnd(getRAngleLoc()); + return R; +} + // FIXME: Maybe this should use DeclPrinter with a special "print predefined // expr" policy instead. std::string PredefinedExpr::ComputeName(ASTContext &Context, IdentType IT, @@ -343,7 +429,7 @@ MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l, bool has_explicit, SourceLocation langle, - const TemplateArgument *targs, unsigned numtargs, + const TemplateArgumentLoc *targs, unsigned numtargs, SourceLocation rangle, QualType ty) : Expr(MemberExprClass, ty, base->isTypeDependent() || (qual && qual->isDependent()), @@ -365,9 +451,9 @@ MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, ETemplateArgs->RAngleLoc = rangle; ETemplateArgs->NumTemplateArgs = numtargs; - TemplateArgument *TemplateArgs = ETemplateArgs->getTemplateArgs(); + TemplateArgumentLoc *TemplateArgs = ETemplateArgs->getTemplateArgs(); for (unsigned I = 0; I < numtargs; ++I) - new (TemplateArgs + I) TemplateArgument(targs[I]); + new (TemplateArgs + I) TemplateArgumentLoc(targs[I]); } } @@ -378,7 +464,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, SourceLocation l, bool has_explicit, SourceLocation langle, - const TemplateArgument *targs, + const TemplateArgumentLoc *targs, unsigned numtargs, SourceLocation rangle, QualType ty) { @@ -388,7 +474,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, if (has_explicit) Size += sizeof(ExplicitTemplateArgumentList) + - sizeof(TemplateArgument) * numtargs; + sizeof(TemplateArgumentLoc) * numtargs; void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>()); return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l, @@ -418,6 +504,8 @@ const char *CastExpr::getCastKindName() const { return "NullToMemberPointer"; case CastExpr::CK_BaseToDerivedMemberPointer: return "BaseToDerivedMemberPointer"; + case CastExpr::CK_DerivedToBaseMemberPointer: + return "DerivedToBaseMemberPointer"; case CastExpr::CK_UserDefinedConversion: return "UserDefinedConversion"; case CastExpr::CK_ConstructorConversion: @@ -610,7 +698,7 @@ Stmt *BlockExpr::getBody() { /// with location to warn on and the source range[s] to report with the /// warning. bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, - SourceRange &R2) const { + SourceRange &R2, ASTContext &Ctx) const { // Don't warn if the expr is type dependent. The type could end up // instantiating to void. if (isTypeDependent()) @@ -623,7 +711,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, return true; case ParenExprClass: return cast<ParenExpr>(this)->getSubExpr()-> - isUnusedResultAWarning(Loc, R1, R2); + isUnusedResultAWarning(Loc, R1, R2, Ctx); case UnaryOperatorClass: { const UnaryOperator *UO = cast<UnaryOperator>(this); @@ -636,17 +724,18 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, return false; // Not a warning. case UnaryOperator::Deref: // Dereferencing a volatile pointer is a side-effect. - if (getType().isVolatileQualified()) + if (Ctx.getCanonicalType(getType()).isVolatileQualified()) return false; break; case UnaryOperator::Real: case UnaryOperator::Imag: // accessing a piece of a volatile complex is a side-effect. - if (UO->getSubExpr()->getType().isVolatileQualified()) + if (Ctx.getCanonicalType(UO->getSubExpr()->getType()) + .isVolatileQualified()) return false; break; case UnaryOperator::Extension: - return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2); + return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx); } Loc = UO->getOperatorLoc(); R1 = UO->getSubExpr()->getSourceRange(); @@ -656,8 +745,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, const BinaryOperator *BO = cast<BinaryOperator>(this); // Consider comma to have side effects if the LHS or RHS does. if (BO->getOpcode() == BinaryOperator::Comma) - return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2) || - BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2); + return (BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) || + BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx)); if (BO->isAssignmentOp()) return false; @@ -674,15 +763,15 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, // warning, warn about them. const ConditionalOperator *Exp = cast<ConditionalOperator>(this); if (Exp->getLHS() && - Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2)) + Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx)) return true; - return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2); + return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx); } case MemberExprClass: // If the base pointer or element is to a volatile pointer/field, accessing // it is a side effect. - if (getType().isVolatileQualified()) + if (Ctx.getCanonicalType(getType()).isVolatileQualified()) return false; Loc = cast<MemberExpr>(this)->getMemberLoc(); R1 = SourceRange(Loc, Loc); @@ -692,7 +781,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, case ArraySubscriptExprClass: // If the base pointer or element is to a volatile pointer/field, accessing // it is a side effect. - if (getType().isVolatileQualified()) + if (Ctx.getCanonicalType(getType()).isVolatileQualified()) return false; Loc = cast<ArraySubscriptExpr>(this)->getRBracketLoc(); R1 = cast<ArraySubscriptExpr>(this)->getLHS()->getSourceRange(); @@ -750,7 +839,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, const CompoundStmt *CS = cast<StmtExpr>(this)->getSubStmt(); if (!CS->body_empty()) if (const Expr *E = dyn_cast<Expr>(CS->body_back())) - return E->isUnusedResultAWarning(Loc, R1, R2); + return E->isUnusedResultAWarning(Loc, R1, R2, Ctx); Loc = cast<StmtExpr>(this)->getLParenLoc(); R1 = getSourceRange(); @@ -768,20 +857,20 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, // If this is a cast to void, check the operand. Otherwise, the result of // the cast is unused. if (getType()->isVoidType()) - return cast<CastExpr>(this)->getSubExpr() - ->isUnusedResultAWarning(Loc, R1, R2); + return (cast<CastExpr>(this)->getSubExpr() + ->isUnusedResultAWarning(Loc, R1, R2, Ctx)); Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc(); R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange(); return true; case ImplicitCastExprClass: // Check the operand, since implicit casts are inserted by Sema - return cast<ImplicitCastExpr>(this) - ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2); + return (cast<ImplicitCastExpr>(this) + ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx)); case CXXDefaultArgExprClass: - return cast<CXXDefaultArgExpr>(this) - ->getExpr()->isUnusedResultAWarning(Loc, R1, R2); + return (cast<CXXDefaultArgExpr>(this) + ->getExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx)); case CXXNewExprClass: // FIXME: In theory, there might be new expressions that don't have side @@ -789,11 +878,11 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, case CXXDeleteExprClass: return false; case CXXBindTemporaryExprClass: - return cast<CXXBindTemporaryExpr>(this) - ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2); + return (cast<CXXBindTemporaryExpr>(this) + ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx)); case CXXExprWithTemporariesClass: - return cast<CXXExprWithTemporaries>(this) - ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2); + return (cast<CXXExprWithTemporaries>(this) + ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx)); } } @@ -855,8 +944,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { if (cast<ArraySubscriptExpr>(this)->getBase()->getType()->isVectorType()) return cast<ArraySubscriptExpr>(this)->getBase()->isLvalue(Ctx); return LV_Valid; - case DeclRefExprClass: - case QualifiedDeclRefExprClass: { // C99 6.5.1p2 + case DeclRefExprClass: { // C99 6.5.1p2 const NamedDecl *RefdDecl = cast<DeclRefExpr>(this)->getDecl(); if (DeclCanBeLvalue(RefdDecl, Ctx)) return LV_Valid; @@ -1042,6 +1130,18 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { return LV_Valid; } + case TemplateIdRefExprClass: { + const TemplateIdRefExpr *TID = cast<TemplateIdRefExpr>(this); + TemplateName Template = TID->getTemplateName(); + NamedDecl *ND = Template.getAsTemplateDecl(); + if (!ND) + ND = Template.getAsOverloadedFunctionDecl(); + if (ND && DeclCanBeLvalue(ND, Ctx)) + return LV_Valid; + + break; + } + default: break; } @@ -1133,8 +1233,7 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { return cast<ImplicitCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx); case CStyleCastExprClass: return cast<CStyleCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx); - case DeclRefExprClass: - case QualifiedDeclRefExprClass: { + case DeclRefExprClass: { const Decl *D = cast<DeclRefExpr>(this)->getDecl(); if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->hasGlobalStorage()) @@ -1432,7 +1531,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { return ICEDiag(2, E->getLocStart()); } case Expr::DeclRefExprClass: - case Expr::QualifiedDeclRefExprClass: if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl())) return NoDiag(); if (Ctx.getLangOptions().CPlusPlus && @@ -1442,16 +1540,35 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // type initialized by an ICE can be used in ICEs. if (const VarDecl *Dcl = dyn_cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl())) { - if (Dcl->isInitKnownICE()) { - // We have already checked whether this subexpression is an - // integral constant expression. - if (Dcl->isInitICE()) - return NoDiag(); - else - return ICEDiag(2, E->getLocStart()); - } + Qualifiers Quals = Ctx.getCanonicalType(Dcl->getType()).getQualifiers(); + if (Quals.hasVolatile() || !Quals.hasConst()) + return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); + + // Look for the definition of this variable, which will actually have + // an initializer. + const VarDecl *Def = 0; + const Expr *Init = Dcl->getDefinition(Def); + if (Init) { + if (Def->isInitKnownICE()) { + // We have already checked whether this subexpression is an + // integral constant expression. + if (Def->isInitICE()) + return NoDiag(); + else + return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); + } - if (const Expr *Init = Dcl->getInit()) { + // C++ [class.static.data]p4: + // If a static data member is of const integral or const + // enumeration type, its declaration in the class definition can + // specify a constant-initializer which shall be an integral + // constant expression (5.19). In that case, the member can appear + // in integral constant expressions. + if (Def->isOutOfLine()) { + Dcl->setInitKnownICE(Ctx, false); + return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); + } + ICEDiag Result = CheckICE(Init, Ctx); // Cache the result of the ICE test. Dcl->setInitKnownICE(Ctx, Result.Val == 0); @@ -1654,7 +1771,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, } EvalResult EvalResult; if (!Evaluate(EvalResult, Ctx)) - assert(0 && "ICE cannot be evaluated!"); + llvm::llvm_unreachable("ICE cannot be evaluated!"); assert(!EvalResult.HasSideEffects && "ICE with side effects!"); assert(EvalResult.Val.isInt() && "ICE that isn't integer!"); Result = EvalResult.Val.getInt(); diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index cba0e22..7c6fc41 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -151,7 +151,7 @@ TemplateIdRefExpr::TemplateIdRefExpr(QualType T, TemplateName Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc) : Expr(TemplateIdRefExprClass, T, @@ -164,10 +164,10 @@ TemplateIdRefExpr::TemplateIdRefExpr(QualType T, Qualifier(Qualifier), QualifierRange(QualifierRange), Template(Template), TemplateNameLoc(TemplateNameLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc), NumTemplateArgs(NumTemplateArgs) { - TemplateArgument *StoredTemplateArgs - = reinterpret_cast<TemplateArgument *> (this+1); + TemplateArgumentLoc *StoredTemplateArgs + = reinterpret_cast<TemplateArgumentLoc *> (this+1); for (unsigned I = 0; I != NumTemplateArgs; ++I) - new (StoredTemplateArgs + I) TemplateArgument(TemplateArgs[I]); + new (StoredTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]); } TemplateIdRefExpr * @@ -176,19 +176,19 @@ TemplateIdRefExpr::Create(ASTContext &Context, QualType T, SourceRange QualifierRange, TemplateName Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc) { void *Mem = Context.Allocate(sizeof(TemplateIdRefExpr) + - sizeof(TemplateArgument) * NumTemplateArgs); + sizeof(TemplateArgumentLoc) * NumTemplateArgs); return new (Mem) TemplateIdRefExpr(T, Qualifier, QualifierRange, Template, TemplateNameLoc, LAngleLoc, TemplateArgs, NumTemplateArgs, RAngleLoc); } void TemplateIdRefExpr::DoDestroy(ASTContext &Context) { - const TemplateArgument *TemplateArgs = getTemplateArgs(); + const TemplateArgumentLoc *TemplateArgs = getTemplateArgs(); for (unsigned I = 0; I != NumTemplateArgs; ++I) - if (Expr *E = TemplateArgs[I].getAsExpr()) + if (Expr *E = TemplateArgs[I].getArgument().getAsExpr()) E->Destroy(Context); this->~TemplateIdRefExpr(); Context.Deallocate(this); @@ -528,7 +528,7 @@ CXXUnresolvedMemberExpr::CXXUnresolvedMemberExpr(ASTContext &C, SourceLocation MemberLoc, bool HasExplicitTemplateArgs, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc) : Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true), @@ -545,9 +545,9 @@ CXXUnresolvedMemberExpr::CXXUnresolvedMemberExpr(ASTContext &C, ETemplateArgs->RAngleLoc = RAngleLoc; ETemplateArgs->NumTemplateArgs = NumTemplateArgs; - TemplateArgument *SavedTemplateArgs = ETemplateArgs->getTemplateArgs(); + TemplateArgumentLoc *SavedTemplateArgs = ETemplateArgs->getTemplateArgs(); for (unsigned I = 0; I < NumTemplateArgs; ++I) - new (SavedTemplateArgs + I) TemplateArgument(TemplateArgs[I]); + new (SavedTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]); } } @@ -562,7 +562,7 @@ CXXUnresolvedMemberExpr::Create(ASTContext &C, SourceLocation MemberLoc, bool HasExplicitTemplateArgs, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc) { if (!HasExplicitTemplateArgs) @@ -573,7 +573,7 @@ CXXUnresolvedMemberExpr::Create(ASTContext &C, void *Mem = C.Allocate(sizeof(CXXUnresolvedMemberExpr) + sizeof(ExplicitTemplateArgumentList) + - sizeof(TemplateArgument) * NumTemplateArgs, + sizeof(TemplateArgumentLoc) * NumTemplateArgs, llvm::alignof<CXXUnresolvedMemberExpr>()); return new (Mem) CXXUnresolvedMemberExpr(C, Base, IsArrow, OperatorLoc, Qualifier, QualifierRange, diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 94d2299..7862c57 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -58,7 +58,8 @@ struct EvalInfo { static bool EvaluateLValue(const Expr *E, APValue &Result, EvalInfo &Info); static bool EvaluatePointer(const Expr *E, APValue &Result, EvalInfo &Info); static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info); -static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, EvalInfo &Info); +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, APValue &Result, EvalInfo &Info); @@ -151,6 +152,67 @@ static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType, return Result; } +namespace { +class VISIBILITY_HIDDEN HasSideEffect + : public StmtVisitor<HasSideEffect, bool> { + EvalInfo &Info; +public: + + HasSideEffect(EvalInfo &info) : Info(info) {} + + // Unhandled nodes conservatively default to having side effects. + bool VisitStmt(Stmt *S) { + return true; + } + + bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitDeclRefExpr(DeclRefExpr *E) { + if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified()) + return true; + return false; + } + // We don't want to evaluate BlockExprs multiple times, as they generate + // a ton of code. + bool VisitBlockExpr(BlockExpr *E) { return true; } + bool VisitPredefinedExpr(PredefinedExpr *E) { return false; } + bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E) + { return Visit(E->getInitializer()); } + bool VisitMemberExpr(MemberExpr *E) { return Visit(E->getBase()); } + bool VisitIntegerLiteral(IntegerLiteral *E) { return false; } + bool VisitFloatingLiteral(FloatingLiteral *E) { return false; } + bool VisitStringLiteral(StringLiteral *E) { return false; } + bool VisitCharacterLiteral(CharacterLiteral *E) { return false; } + bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { return false; } + bool VisitArraySubscriptExpr(ArraySubscriptExpr *E) + { return Visit(E->getLHS()) || Visit(E->getRHS()); } + bool VisitChooseExpr(ChooseExpr *E) + { return Visit(E->getChosenSubExpr(Info.Ctx)); } + bool VisitCastExpr(CastExpr *E) { return Visit(E->getSubExpr()); } + bool VisitBinAssign(BinaryOperator *E) { return true; } + bool VisitCompoundAssignOperator(BinaryOperator *E) { return true; } + bool VisitBinaryOperator(BinaryOperator *E) + { return Visit(E->getLHS()) || Visit(E->getRHS()); } + bool VisitUnaryPreInc(UnaryOperator *E) { return true; } + bool VisitUnaryPostInc(UnaryOperator *E) { return true; } + bool VisitUnaryPreDec(UnaryOperator *E) { return true; } + bool VisitUnaryPostDec(UnaryOperator *E) { return true; } + bool VisitUnaryDeref(UnaryOperator *E) { + if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified()) + return true; + return Visit(E->getSubExpr()); + } + bool VisitUnaryOperator(UnaryOperator *E) { return Visit(E->getSubExpr()); } +}; + +bool HasSideEffects(const Expr* E, ASTContext &Ctx) { + Expr::EvalResult Result; + EvalInfo Info(Ctx, Result); + + return HasSideEffect(Info).Visit(const_cast<Expr*>(E)); +} + +} // end anonymous namespace + //===----------------------------------------------------------------------===// // LValue Evaluation //===----------------------------------------------------------------------===// @@ -208,8 +270,9 @@ APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) { if (!VD->getType()->isReferenceType()) return APValue(E, 0); // FIXME: Check whether VD might be overridden! - if (VD->getInit()) - return Visit(VD->getInit()); + const VarDecl *Def = 0; + if (const Expr *Init = VD->getDefinition(Def)) + return Visit(const_cast<Expr *>(Init)); } return APValue(); @@ -793,11 +856,14 @@ bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { // In C++, const, non-volatile integers initialized with ICEs are ICEs. // In C, they can also be folded, although they are not ICEs. - if (E->getType().getCVRQualifiers() == Qualifiers::Const) { + if (Info.Ctx.getCanonicalType(E->getType()).getCVRQualifiers() + == Qualifiers::Const) { if (const VarDecl *D = dyn_cast<VarDecl>(E->getDecl())) { - if (APValue *V = D->getEvaluatedValue()) - return Success(V->getInt(), E); - if (const Expr *Init = D->getInit()) { + const VarDecl *Def = 0; + if (const Expr *Init = D->getDefinition(Def)) { + if (APValue *V = D->getEvaluatedValue()) + return Success(V->getInt(), E); + if (Visit(const_cast<Expr*>(Init))) { // Cache the evaluated value in the variable declaration. D->setEvaluatedValue(Info.Ctx, Result); @@ -873,6 +939,40 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { switch (E->isBuiltinCall(Info.Ctx)) { default: return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + + case Builtin::BI__builtin_object_size: { + const Expr *Arg = E->getArg(0)->IgnoreParens(); + Expr::EvalResult Base; + if (Arg->EvaluateAsAny(Base, Info.Ctx) + && Base.Val.getKind() == APValue::LValue + && !Base.HasSideEffects) + if (const Expr *LVBase = Base.Val.getLValueBase()) + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LVBase)) { + if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) { + if (!VD->getType()->isIncompleteType() + && VD->getType()->isObjectType() + && !VD->getType()->isVariablyModifiedType() + && !VD->getType()->isDependentType()) { + uint64_t Size = Info.Ctx.getTypeSize(VD->getType()) / 8; + uint64_t Offset = Base.Val.getLValueOffset(); + if (Offset <= Size) + Size -= Base.Val.getLValueOffset(); + else + Size = 0; + return Success(Size, E); + } + } + } + + if (HasSideEffects(E->getArg(0), Info.Ctx)) { + if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() < 2) + return Success(-1ULL, E); + return Success(0, E); + } + + return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + } + case Builtin::BI__builtin_classify_type: return Success(EvaluateBuiltinClassifyType(E), E); @@ -1801,6 +1901,33 @@ bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const { return true; } +bool Expr::EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const { + EvalInfo Info(Ctx, Result, true); + + if (getType()->isVectorType()) { + if (!EvaluateVector(this, Result.Val, Info)) + return false; + } else if (getType()->isIntegerType()) { + if (!IntExprEvaluator(Info, Result.Val).Visit(const_cast<Expr*>(this))) + return false; + } else if (getType()->hasPointerRepresentation()) { + if (!EvaluatePointer(this, Result.Val, Info)) + return false; + } else if (getType()->isRealFloatingType()) { + llvm::APFloat f(0.0); + if (!EvaluateFloat(this, f, Info)) + return false; + + Result.Val = APValue(f); + } else if (getType()->isAnyComplexType()) { + if (!EvaluateComplex(this, Result.Val, Info)) + return false; + } else + return false; + + return true; +} + bool Expr::EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const { EvalInfo Info(Ctx, Result); diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index c79cc3c..0b159c3 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -47,6 +47,8 @@ ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { if (!i->isVirtual()) { + assert(!i->getType()->isDependentType() && + "Cannot layout class with dependent bases."); const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); // Skip the PrimaryBase here, as it is laid down first. @@ -82,6 +84,8 @@ void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) { // Now traverse all bases and find primary bases for them. for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { + assert(!i->getType()->isDependentType() && + "Cannot layout class with dependent bases."); const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); @@ -97,6 +101,8 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD, const CXXRecordDecl *&FirstPrimary) { for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { + assert(!i->getType()->isDependentType() && + "Cannot layout class with dependent bases."); const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); if (!i->isVirtual()) { @@ -123,6 +129,8 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) { // indirect bases, and record all their primary virtual base classes. for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { + assert(!i->getType()->isDependentType() && + "Cannot layout class with dependent bases."); const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); IdentifyPrimaryBases(Base); @@ -173,6 +181,8 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) { for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { + assert(!i->getType()->isDependentType() && + "Cannot layout class with dependent bases."); const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); #if 0 @@ -235,6 +245,8 @@ bool ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD, // Check bases. for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { + assert(!I->getType()->isDependentType() && + "Cannot layout class with dependent bases."); if (I->isVirtual()) continue; @@ -305,6 +317,8 @@ void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD, // Update bases. for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { + assert(!I->getType()->isDependentType() && + "Cannot layout class with dependent bases."); if (I->isVirtual()) continue; diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h index 6e4cdd2..b57b37d 100644 --- a/lib/AST/RecordLayoutBuilder.h +++ b/lib/AST/RecordLayoutBuilder.h @@ -12,7 +12,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallSet.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" #include <map> namespace clang { diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 2af1976..4bd7f96 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -473,14 +473,14 @@ void StmtPrinter::VisitExpr(Expr *Node) { } void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { + if (NestedNameSpecifier *Qualifier = Node->getQualifier()) + Qualifier->print(OS, Policy); OS << Node->getDecl()->getNameAsString(); -} - -void StmtPrinter::VisitQualifiedDeclRefExpr(QualifiedDeclRefExpr *Node) { - NamedDecl *D = Node->getDecl(); - - Node->getQualifier()->print(OS, Policy); - OS << D->getNameAsString(); + if (Node->hasExplicitTemplateArgumentList()) + OS << TemplateSpecializationType::PrintTemplateArgumentList( + Node->getTemplateArgs(), + Node->getNumTemplateArgs(), + Policy); } void StmtPrinter::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *Node) { diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index c4d42f6..02e0c74 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -60,7 +60,10 @@ namespace { /// \brief Visit template arguments that occur within an expression or /// statement. - void VisitTemplateArguments(const TemplateArgument *Args, unsigned NumArgs); + void VisitTemplateArguments(const TemplateArgumentLoc *Args, unsigned NumArgs); + + /// \brief Visit a single template argument. + void VisitTemplateArgument(const TemplateArgument &Arg); }; } @@ -206,7 +209,9 @@ void StmtProfiler::VisitExpr(Expr *S) { void StmtProfiler::VisitDeclRefExpr(DeclRefExpr *S) { VisitExpr(S); + VisitNestedNameSpecifier(S->getQualifier()); VisitDecl(S->getDecl()); + VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); } void StmtProfiler::VisitPredefinedExpr(PredefinedExpr *S) { @@ -521,11 +526,6 @@ void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) { VisitType(S->getQueriedType()); } -void StmtProfiler::VisitQualifiedDeclRefExpr(QualifiedDeclRefExpr *S) { - VisitDeclRefExpr(S); - VisitNestedNameSpecifier(S->getQualifier()); -} - void StmtProfiler::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *S) { VisitExpr(S); VisitName(S->getDeclName()); @@ -677,39 +677,42 @@ void StmtProfiler::VisitTemplateName(TemplateName Name) { Name.Profile(ID); } -void StmtProfiler::VisitTemplateArguments(const TemplateArgument *Args, +void StmtProfiler::VisitTemplateArguments(const TemplateArgumentLoc *Args, unsigned NumArgs) { ID.AddInteger(NumArgs); - for (unsigned I = 0; I != NumArgs; ++I) { - const TemplateArgument &Arg = Args[I]; - - // Mostly repetitive with TemplateArgument::Profile! - ID.AddInteger(Arg.getKind()); - switch (Arg.getKind()) { - case TemplateArgument::Null: - break; - - case TemplateArgument::Type: - VisitType(Arg.getAsType()); - break; - - case TemplateArgument::Declaration: - VisitDecl(Arg.getAsDecl()); - break; - - case TemplateArgument::Integral: - Arg.getAsIntegral()->Profile(ID); - VisitType(Arg.getIntegralType()); - break; - - case TemplateArgument::Expression: - Visit(Arg.getAsExpr()); - break; - - case TemplateArgument::Pack: - VisitTemplateArguments(Arg.pack_begin(), Arg.pack_size()); - break; - } + for (unsigned I = 0; I != NumArgs; ++I) + VisitTemplateArgument(Args[I].getArgument()); +} + +void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { + // Mostly repetitive with TemplateArgument::Profile! + ID.AddInteger(Arg.getKind()); + switch (Arg.getKind()) { + case TemplateArgument::Null: + break; + + case TemplateArgument::Type: + VisitType(Arg.getAsType()); + break; + + case TemplateArgument::Declaration: + VisitDecl(Arg.getAsDecl()); + break; + + case TemplateArgument::Integral: + Arg.getAsIntegral()->Profile(ID); + VisitType(Arg.getIntegralType()); + break; + + case TemplateArgument::Expression: + Visit(Arg.getAsExpr()); + break; + + case TemplateArgument::Pack: + const TemplateArgument *Pack = Arg.pack_begin(); + for (unsigned i = 0, e = Arg.pack_size(); i != e; ++i) + VisitTemplateArgument(Pack[i]); + break; } } diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp new file mode 100644 index 0000000..94e1ca1 --- /dev/null +++ b/lib/AST/TemplateBase.cpp @@ -0,0 +1,97 @@ +//===--- TemplateBase.cpp - Common template AST class implementation ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements common classes used throughout C++ template +// representations. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/FoldingSet.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/Expr.h" +#include "clang/AST/TypeLoc.h" + +using namespace clang; + +//===----------------------------------------------------------------------===// +// TemplateArgument Implementation +//===----------------------------------------------------------------------===// + +/// \brief Construct a template argument pack. +void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs, + bool CopyArgs) { + assert(isNull() && "Must call setArgumentPack on a null argument"); + + Kind = Pack; + Args.NumArgs = NumArgs; + Args.CopyArgs = CopyArgs; + if (!Args.CopyArgs) { + Args.Args = args; + return; + } + + // FIXME: Allocate in ASTContext + Args.Args = new TemplateArgument[NumArgs]; + for (unsigned I = 0; I != Args.NumArgs; ++I) + Args.Args[I] = args[I]; +} + +void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, + ASTContext &Context) const { + ID.AddInteger(Kind); + switch (Kind) { + case Null: + break; + + case Type: + getAsType().Profile(ID); + break; + + case Declaration: + ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); + break; + + case Integral: + getAsIntegral()->Profile(ID); + getIntegralType().Profile(ID); + break; + + case Expression: + getAsExpr()->Profile(ID, Context, true); + break; + + case Pack: + ID.AddInteger(Args.NumArgs); + for (unsigned I = 0; I != Args.NumArgs; ++I) + Args.Args[I].Profile(ID, Context); + } +} + +//===----------------------------------------------------------------------===// +// TemplateArgumentLoc Implementation +//===----------------------------------------------------------------------===// + +SourceRange TemplateArgumentLoc::getSourceRange() const { + switch (Argument.getKind()) { + case TemplateArgument::Expression: + return getSourceExpression()->getSourceRange(); + case TemplateArgument::Declaration: + return getSourceDeclExpression()->getSourceRange(); + case TemplateArgument::Type: + return getSourceDeclaratorInfo()->getTypeLoc().getFullSourceRange(); + case TemplateArgument::Integral: + case TemplateArgument::Pack: + case TemplateArgument::Null: + return SourceRange(); + } + + // Silence bonus gcc warning. + return SourceRange(); +} diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp index 24588bc..5b4cf0a 100644 --- a/lib/AST/TemplateName.cpp +++ b/lib/AST/TemplateName.cpp @@ -56,7 +56,7 @@ void TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy, bool SuppressNNS) const { if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) - OS << Template->getIdentifier()->getName(); + OS << Template->getNameAsString(); else if (OverloadedFunctionDecl *Ovl = Storage.dyn_cast<OverloadedFunctionDecl *>()) OS << Ovl->getNameAsString(); @@ -70,8 +70,11 @@ TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy, if (!SuppressNNS && DTN->getQualifier()) DTN->getQualifier()->print(OS, Policy); OS << "template "; - // FIXME: Shouldn't we have a more general kind of name? - OS << DTN->getName()->getName(); + + if (DTN->isIdentifier()) + OS << DTN->getIdentifier()->getName(); + else + OS << "operator " << getOperatorSpelling(DTN->getOperator()); } } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 5fb0178..3608d34 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -224,6 +224,8 @@ QualType Type::getPointeeType() const { return OPT->getPointeeType(); if (const BlockPointerType *BPT = getAs<BlockPointerType>()) return BPT->getPointeeType(); + if (const ReferenceType *RT = getAs<ReferenceType>()) + return RT->getPointeeType(); return QualType(); } @@ -791,40 +793,48 @@ bool EnumType::classof(const TagType *TT) { return isa<EnumDecl>(TT->getDecl()); } -bool -TemplateSpecializationType:: -anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) { - for (unsigned Idx = 0; Idx < NumArgs; ++Idx) { - switch (Args[Idx].getKind()) { - case TemplateArgument::Null: - assert(false && "Should not have a NULL template argument"); - break; - - case TemplateArgument::Type: - if (Args[Idx].getAsType()->isDependentType()) - return true; - break; - - case TemplateArgument::Declaration: - case TemplateArgument::Integral: - // Never dependent - break; - - case TemplateArgument::Expression: - if (Args[Idx].getAsExpr()->isTypeDependent() || - Args[Idx].getAsExpr()->isValueDependent()) - return true; - break; - - case TemplateArgument::Pack: - assert(0 && "FIXME: Implement!"); - break; - } +static bool isDependent(const TemplateArgument &Arg) { + switch (Arg.getKind()) { + case TemplateArgument::Null: + assert(false && "Should not have a NULL template argument"); + return false; + + case TemplateArgument::Type: + return Arg.getAsType()->isDependentType(); + + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + // Never dependent + return false; + + case TemplateArgument::Expression: + return (Arg.getAsExpr()->isTypeDependent() || + Arg.getAsExpr()->isValueDependent()); + + case TemplateArgument::Pack: + assert(0 && "FIXME: Implement!"); + return false; } return false; } +bool TemplateSpecializationType:: +anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N) { + for (unsigned i = 0; i != N; ++i) + if (isDependent(Args[i].getArgument())) + return true; + return false; +} + +bool TemplateSpecializationType:: +anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N) { + for (unsigned i = 0; i != N; ++i) + if (isDependent(Args[i])) + return true; + return false; +} + TemplateSpecializationType:: TemplateSpecializationType(ASTContext &Context, TemplateName T, const TemplateArgument *Args, @@ -1260,6 +1270,38 @@ void SubstTemplateTypeParmType::getAsStringInternal(std::string &InnerString, co getReplacementType().getAsStringInternal(InnerString, Policy); } +static void PrintTemplateArgument(std::string &Buffer, + const TemplateArgument &Arg, + const PrintingPolicy &Policy) { + switch (Arg.getKind()) { + case TemplateArgument::Null: + assert(false && "Null template argument"); + break; + + case TemplateArgument::Type: + Arg.getAsType().getAsStringInternal(Buffer, Policy); + break; + + case TemplateArgument::Declaration: + Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString(); + break; + + case TemplateArgument::Integral: + Buffer = Arg.getAsIntegral()->toString(10, true); + break; + + case TemplateArgument::Expression: { + llvm::raw_string_ostream s(Buffer); + Arg.getAsExpr()->printPretty(s, 0, Policy); + break; + } + + case TemplateArgument::Pack: + assert(0 && "FIXME: Implement!"); + break; + } +} + std::string TemplateSpecializationType::PrintTemplateArgumentList( const TemplateArgument *Args, @@ -1273,32 +1315,41 @@ TemplateSpecializationType::PrintTemplateArgumentList( // Print the argument into a string. std::string ArgString; - switch (Args[Arg].getKind()) { - case TemplateArgument::Null: - assert(false && "Null template argument"); - break; - - case TemplateArgument::Type: - Args[Arg].getAsType().getAsStringInternal(ArgString, Policy); - break; - - case TemplateArgument::Declaration: - ArgString = cast<NamedDecl>(Args[Arg].getAsDecl())->getNameAsString(); - break; - - case TemplateArgument::Integral: - ArgString = Args[Arg].getAsIntegral()->toString(10, true); - break; - - case TemplateArgument::Expression: { - llvm::raw_string_ostream s(ArgString); - Args[Arg].getAsExpr()->printPretty(s, 0, Policy); - break; - } - case TemplateArgument::Pack: - assert(0 && "FIXME: Implement!"); - break; - } + PrintTemplateArgument(ArgString, Args[Arg], Policy); + + // If this is the first argument and its string representation + // begins with the global scope specifier ('::foo'), add a space + // to avoid printing the diagraph '<:'. + if (!Arg && !ArgString.empty() && ArgString[0] == ':') + SpecString += ' '; + + SpecString += ArgString; + } + + // If the last character of our string is '>', add another space to + // keep the two '>''s separate tokens. We don't *have* to do this in + // C++0x, but it's still good hygiene. + if (SpecString[SpecString.size() - 1] == '>') + SpecString += ' '; + + SpecString += '>'; + + return SpecString; +} + +// Sadly, repeat all that with TemplateArgLoc. +std::string TemplateSpecializationType:: +PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs, + const PrintingPolicy &Policy) { + std::string SpecString; + SpecString += '<'; + for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { + if (Arg) + SpecString += ", "; + + // Print the argument into a string. + std::string ArgString; + PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy); // If this is the first argument and its string representation // begins with the global scope specifier ('::foo'), add a space |