&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'.
+ // 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 &IntersectionOfProtocols) {
+
+ const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
+ const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
+
+ llvm::SmallPtrSet InheritedProtocolSet;
+ unsigned LHSNumProtocols = LHS->getNumProtocols();
+ if (LHSNumProtocols > 0)
+ InheritedProtocolSet.insert(LHS->qual_begin(), LHS->qual_end());
+ else {
+ llvm::SmallVector 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 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();
+ if (canAssignObjCInterfaces(LHS, RHS)) {
+ llvm::SmallVector 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(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(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(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()) {
+ if (!Context.getLangOptions().C99 || hasAttr()) {
// 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(*Op);
+ const CXXMethodDecl* Method = dyn_cast(*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 ConversionFunctions;
if (!inTopClass)
collectConversionFunctions(ConversionFunctions);
-
+
for (CXXRecordDecl::base_class_iterator VBase = vbases_begin(),
E = vbases_end(); VBase != E; ++VBase) {
- CXXRecordDecl *VBaseClassDecl
- = cast(VBase->getType()->getAs()->getDecl());
- VBaseClassDecl->getNestedVisibleConversionFunctions(RD,
- TopConversionsTypeSet,
- (inTopClass ? TopConversionsTypeSet : ConversionFunctions));
-
+ if (const RecordType *RT = VBase->getType()->getAs()) {
+ CXXRecordDecl *VBaseClassDecl
+ = cast(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(Base->getType()->getAs()->getDecl());
-
- BaseClassDecl->getNestedVisibleConversionFunctions(RD,
- TopConversionsTypeSet,
- (inTopClass ? TopConversionsTypeSet : ConversionFunctions));
-
+ if (const RecordType *RT = Base->getType()->getAs()) {
+ CXXRecordDecl *BaseClassDecl
+ = cast(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(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(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(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(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(D))
+ if (ParmVarDecl *Parm = dyn_cast(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(FirstParm))
+ return TTP->getDepth();
+ else if (const NonTypeTemplateParmDecl *NTTP
+ = dyn_cast(FirstParm))
+ return NTTP->getDepth();
+ else
+ return cast(FirstParm)->getDepth();
+}
+
//===----------------------------------------------------------------------===//
// TemplateDecl Implementation
//===----------------------------------------------------------------------===//
@@ -194,8 +210,7 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
Param != ParamEnd; ++Param) {
if (isa(*Param)) {
QualType ParamType = Context.getTypeDeclType(cast(*Param));
- TemplateArgs.push_back(TemplateArgument((*Param)->getLocation(),
- ParamType));
+ TemplateArgs.push_back(TemplateArgument(ParamType));
} else if (NonTypeTemplateParmDecl *NTTP =
dyn_cast(*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(*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()->getDepth();
+}
+
+unsigned TemplateTypeParmDecl::getIndex() const {
+ return TypeForDecl->getAs()->getIndex();
+}
+
//===----------------------------------------------------------------------===//
// NonTypeTemplateParmDecl Method Implementations
//===----------------------------------------------------------------------===//
@@ -264,34 +291,6 @@ SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
}
//===----------------------------------------------------------------------===//
-// TemplateArgument Implementation
-//===----------------------------------------------------------------------===//
-
-TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
- TypeOrValue = reinterpret_cast(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
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());
+ 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());
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(this)->getSubExpr()->
- isUnusedResultAWarning(Loc, R1, R2);
+ isUnusedResultAWarning(Loc, R1, R2, Ctx);
case UnaryOperatorClass: {
const UnaryOperator *UO = cast(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(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(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(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(this)->getRBracketLoc();
R1 = cast(this)->getLHS()->getSourceRange();
@@ -750,7 +839,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
const CompoundStmt *CS = cast(this)->getSubStmt();
if (!CS->body_empty())
if (const Expr *E = dyn_cast(CS->body_back()))
- return E->isUnusedResultAWarning(Loc, R1, R2);
+ return E->isUnusedResultAWarning(Loc, R1, R2, Ctx);
Loc = cast(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(this)->getSubExpr()
- ->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast(this)->getSubExpr()
+ ->isUnusedResultAWarning(Loc, R1, R2, Ctx));
Loc = cast(this)->getTypeBeginLoc();
R1 = cast(this)->getSubExpr()->getSourceRange();
return true;
case ImplicitCastExprClass:
// Check the operand, since implicit casts are inserted by Sema
- return cast(this)
- ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast(this)
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
case CXXDefaultArgExprClass:
- return cast(this)
- ->getExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast(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(this)
- ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast(this)
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
case CXXExprWithTemporariesClass:
- return cast(this)
- ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return (cast(this)
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
}
}
@@ -855,8 +944,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
if (cast(this)->getBase()->getType()->isVectorType())
return cast(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(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(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(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
case CStyleCastExprClass:
return cast(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
- case DeclRefExprClass:
- case QualifiedDeclRefExprClass: {
+ case DeclRefExprClass: {
const Decl *D = cast(this)->getDecl();
if (const VarDecl *VD = dyn_cast(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(cast(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(cast(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(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(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(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 (this+1);
+ TemplateArgumentLoc *StoredTemplateArgs
+ = reinterpret_cast (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());
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 {
+ 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(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(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(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(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(LVBase)) {
+ if (const VarDecl *VD = dyn_cast(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(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(i->getType()->getAs()->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