aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-11-04 15:04:32 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-11-04 15:04:32 +0000
commit51fb8b013e7734b795139f49d3b1f77c539be20a (patch)
tree59e0e47a9831dcf0e21e547927c8ebb7e113bfd1 /lib
parent73490b890977362d28dd6326843a1ecae413921d (diff)
downloadsrc-51fb8b013e7734b795139f49d3b1f77c539be20a.tar.gz
src-51fb8b013e7734b795139f49d3b1f77c539be20a.zip
Update clang to r86025.vendor/clang/clang-r86025
Notes
Notes: svn path=/vendor/clang/dist/; revision=198893 svn path=/vendor/clang/clang-r86025/; revision=198895; tag=vendor/clang/clang-r86025
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTContext.cpp223
-rw-r--r--lib/AST/CMakeLists.txt1
-rw-r--r--lib/AST/Decl.cpp125
-rw-r--r--lib/AST/DeclBase.cpp1
-rw-r--r--lib/AST/DeclCXX.cpp39
-rw-r--r--lib/AST/DeclObjC.cpp27
-rw-r--r--lib/AST/DeclPrinter.cpp9
-rw-r--r--lib/AST/DeclTemplate.cpp72
-rw-r--r--lib/AST/Expr.cpp201
-rw-r--r--lib/AST/ExprCXX.cpp26
-rw-r--r--lib/AST/ExprConstant.cpp141
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp14
-rw-r--r--lib/AST/RecordLayoutBuilder.h2
-rw-r--r--lib/AST/StmtPrinter.cpp14
-rw-r--r--lib/AST/StmtProfile.cpp77
-rw-r--r--lib/AST/TemplateBase.cpp97
-rw-r--r--lib/AST/TemplateName.cpp9
-rw-r--r--lib/AST/Type.cpp161
-rw-r--r--lib/Analysis/AttrNonNullChecker.cpp100
-rw-r--r--lib/Analysis/BadCallChecker.cpp44
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.cpp1
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.h1
-rw-r--r--lib/Analysis/BasicStore.cpp26
-rw-r--r--lib/Analysis/CFRefCount.cpp34
-rw-r--r--lib/Analysis/CMakeLists.txt10
-rw-r--r--lib/Analysis/CallGraph.cpp4
-rw-r--r--lib/Analysis/CheckObjCUnusedIVars.cpp35
-rw-r--r--lib/Analysis/DereferenceChecker.cpp112
-rw-r--r--lib/Analysis/DivZeroChecker.cpp70
-rw-r--r--lib/Analysis/GRExprEngine.cpp391
-rw-r--r--lib/Analysis/GRExprEngineInternalChecks.cpp390
-rw-r--r--lib/Analysis/NSAutoreleasePoolChecker.cpp84
-rw-r--r--lib/Analysis/NSErrorChecker.cpp (renamed from lib/Analysis/CheckNSError.cpp)31
-rw-r--r--lib/Analysis/RegionStore.cpp39
-rw-r--r--lib/Analysis/UndefinedArgChecker.cpp43
-rw-r--r--lib/Analysis/UndefinedAssignmentChecker.cpp61
-rw-r--r--lib/Analysis/VLASizeChecker.cpp102
-rw-r--r--lib/Basic/CMakeLists.txt2
-rw-r--r--lib/Basic/IdentifierTable.cpp14
-rw-r--r--lib/Basic/TargetInfo.cpp4
-rw-r--r--lib/Basic/Targets.cpp2
-rw-r--r--lib/CodeGen/CGBuiltin.cpp13
-rw-r--r--lib/CodeGen/CGCXX.cpp172
-rw-r--r--lib/CodeGen/CGCall.cpp2
-rw-r--r--lib/CodeGen/CGDecl.cpp44
-rw-r--r--lib/CodeGen/CGException.cpp105
-rw-r--r--lib/CodeGen/CGExpr.cpp224
-rw-r--r--lib/CodeGen/CGExprAgg.cpp5
-rw-r--r--lib/CodeGen/CGExprConstant.cpp17
-rw-r--r--lib/CodeGen/CGExprScalar.cpp33
-rw-r--r--lib/CodeGen/CGObjC.cpp22
-rw-r--r--lib/CodeGen/CGRecordLayoutBuilder.h2
-rw-r--r--lib/CodeGen/CGRtti.cpp21
-rw-r--r--lib/CodeGen/CGStmt.cpp5
-rw-r--r--lib/CodeGen/CGValue.h2
-rw-r--r--lib/CodeGen/CGVtable.cpp228
-rw-r--r--lib/CodeGen/CMakeLists.txt1
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp75
-rw-r--r--lib/CodeGen/CodeGenFunction.h27
-rw-r--r--lib/CodeGen/CodeGenModule.cpp36
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp2
-rw-r--r--lib/CodeGen/Mangle.cpp21
-rw-r--r--lib/CodeGen/Mangle.h4
-rw-r--r--lib/Driver/Tools.cpp217
-rw-r--r--lib/Driver/Types.cpp82
-rw-r--r--lib/Frontend/ASTConsumers.cpp7
-rw-r--r--lib/Frontend/AnalysisConsumer.cpp1
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp312
-rw-r--r--lib/Frontend/InitPreprocessor.cpp33
-rw-r--r--lib/Frontend/PCHReader.cpp28
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp20
-rw-r--r--lib/Frontend/PCHReaderStmt.cpp4
-rw-r--r--lib/Frontend/PCHWriter.cpp24
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp12
-rw-r--r--lib/Frontend/PCHWriterStmt.cpp4
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp2
-rw-r--r--lib/Frontend/RewriteObjC.cpp6
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp55
-rw-r--r--lib/Headers/CMakeLists.txt2
-rw-r--r--lib/Headers/stdint.h3
-rw-r--r--lib/Index/ResolveLocation.cpp79
-rw-r--r--lib/Lex/HeaderMap.cpp2
-rw-r--r--lib/Lex/PPDirectives.cpp14
-rw-r--r--lib/Lex/PPExpressions.cpp118
-rw-r--r--lib/Lex/PPMacroExpansion.cpp131
-rw-r--r--lib/Parse/AttributeList.cpp145
-rw-r--r--lib/Parse/DeclSpec.cpp25
-rw-r--r--lib/Parse/MinimalAction.cpp5
-rw-r--r--lib/Parse/ParseDecl.cpp359
-rw-r--r--lib/Parse/ParseDeclCXX.cpp60
-rw-r--r--lib/Parse/ParseExpr.cpp168
-rw-r--r--lib/Parse/ParseExprCXX.cpp623
-rw-r--r--lib/Parse/ParseObjc.cpp146
-rw-r--r--lib/Parse/ParseStmt.cpp3
-rw-r--r--lib/Parse/ParseTemplate.cpp32
-rw-r--r--lib/Parse/Parser.cpp84
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp11
-rw-r--r--lib/Sema/Sema.cpp40
-rw-r--r--lib/Sema/Sema.h217
-rw-r--r--lib/Sema/SemaCXXCast.cpp8
-rw-r--r--lib/Sema/SemaChecking.cpp10
-rw-r--r--lib/Sema/SemaCodeComplete.cpp95
-rw-r--r--lib/Sema/SemaDecl.cpp261
-rw-r--r--lib/Sema/SemaDeclAttr.cpp100
-rw-r--r--lib/Sema/SemaDeclCXX.cpp114
-rw-r--r--lib/Sema/SemaDeclObjC.cpp70
-rw-r--r--lib/Sema/SemaExpr.cpp490
-rw-r--r--lib/Sema/SemaExprCXX.cpp186
-rw-r--r--lib/Sema/SemaLookup.cpp22
-rw-r--r--lib/Sema/SemaOverload.cpp244
-rw-r--r--lib/Sema/SemaStmt.cpp2
-rw-r--r--lib/Sema/SemaTemplate.cpp439
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp161
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp381
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp395
-rw-r--r--lib/Sema/SemaType.cpp265
-rw-r--r--lib/Sema/TreeTransform.h896
117 files changed, 7108 insertions, 4005 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 7f5fa35842af..aef3d2989415 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 20e1150b22c2..e541406790a6 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 d270a958f0ae..a6996a4bfe5c 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 224bf877ad24..6cfdcdd3e50e 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 457f4c85a047..b4c0c59733e5 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 7f38ac1d9ad0..7b48b724c0eb 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 9d0d836cf62b..d9d195016bf3 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 9a1c65416f71..9ebc91afe142 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 a4de3e5b0f7a..a8ea752a4a7e 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 cba0e220952e..7c6fc41ef12b 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 94d22998ebbe..7862c57c2d47 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 c79cc3c1dbb1..0b159c3a7bd8 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 6e4cdd2fe2ee..b57b37d0df4d 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 2af19765dfaa..4bd7f964be6c 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 c4d42f6be228..02e0c74bb63a 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 000000000000..94e1ca1e06e7
--- /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 24588bc5f11f..5b4cf0ad94f6 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 5fb0178834ff..3608d34c691d 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
diff --git a/lib/Analysis/AttrNonNullChecker.cpp b/lib/Analysis/AttrNonNullChecker.cpp
new file mode 100644
index 000000000000..1cf5d0c4af2d
--- /dev/null
+++ b/lib/Analysis/AttrNonNullChecker.cpp
@@ -0,0 +1,100 @@
+//===--- AttrNonNullChecker.h - Undefined arguments checker ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines AttrNonNullChecker, a builtin check in GRExprEngine that
+// performs checks for arguments declared to have nonnull attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *AttrNonNullChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C,
+ const CallExpr *CE) {
+ const GRState *state = C.getState();
+ const GRState *originalState = state;
+
+ // Check if the callee has a 'nonnull' attribute.
+ SVal X = state->getSVal(CE->getCallee());
+
+ const FunctionDecl* FD = X.getAsFunctionDecl();
+ if (!FD)
+ return;
+
+ const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
+ if (!Att)
+ return;
+
+ // Iterate through the arguments of CE and check them for null.
+ unsigned idx = 0;
+
+ for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
+ ++I, ++idx) {
+
+ if (!Att->isNonNull(idx))
+ continue;
+
+ const SVal &V = state->getSVal(*I);
+ const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
+
+ if (!DV)
+ continue;
+
+ ConstraintManager &CM = C.getConstraintManager();
+ const GRState *stateNotNull, *stateNull;
+ llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
+
+ if (stateNull && !stateNotNull) {
+ // Generate an error node. Check for a null node in case
+ // we cache out.
+ if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
+
+ // Lazily allocate the BugType object if it hasn't already been
+ // created. Ownership is transferred to the BugReporter object once
+ // the BugReport is passed to 'EmitWarning'.
+ if (!BT)
+ BT = new BugType("Argument with 'nonnull' attribute passed null",
+ "API");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT,
+ "Null pointer passed as an argument to a "
+ "'nonnull' parameter", errorNode);
+
+ // Highlight the range of the argument that was null.
+ const Expr *arg = *I;
+ R->addRange(arg->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, arg);
+
+ // Emit the bug report.
+ C.EmitReport(R);
+ }
+
+ // Always return. Either we cached out or we just emitted an error.
+ return;
+ }
+
+ // If a pointer value passed the check we should assume that it is
+ // indeed not null from this point forward.
+ assert(stateNotNull);
+ state = stateNotNull;
+ }
+
+ // If we reach here all of the arguments passed the nonnull check.
+ // If 'state' has been updated generated a new node.
+ if (state != originalState)
+ C.addTransition(C.GenerateNode(CE, state));
+}
diff --git a/lib/Analysis/BadCallChecker.cpp b/lib/Analysis/BadCallChecker.cpp
new file mode 100644
index 000000000000..33bb5158d2b9
--- /dev/null
+++ b/lib/Analysis/BadCallChecker.cpp
@@ -0,0 +1,44 @@
+//===--- BadCallChecker.h - Bad call checker --------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines BadCallChecker, a builtin check in GRExprEngine that performs
+// checks for bad callee at call sites.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *BadCallChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+void BadCallChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+ const Expr *Callee = CE->getCallee()->IgnoreParens();
+ SVal L = C.getState()->getSVal(Callee);
+
+ if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
+ if (ExplodedNode *N = C.GenerateNode(CE, true)) {
+ if (!BT)
+ BT = new BuiltinBug(0, "Invalid function call",
+ "Called function pointer is a null or undefined pointer value");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetCalleeExpr(N));
+
+ C.EmitReport(R);
+ }
+ }
+}
diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp
index aa2d0ab5a763..4781d5ec243e 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.cpp
+++ b/lib/Analysis/BasicObjCFoundationChecks.cpp
@@ -535,4 +535,5 @@ void clang::RegisterAppleChecks(GRExprEngine& Eng, const Decl &D) {
Eng.AddCheck(CreateAuditCFRetainRelease(Ctx, BR), Stmt::CallExprClass);
RegisterNSErrorChecks(BR, Eng, D);
+ RegisterNSAutoreleasePoolChecks(Eng);
}
diff --git a/lib/Analysis/BasicObjCFoundationChecks.h b/lib/Analysis/BasicObjCFoundationChecks.h
index 1271ae4ab1c0..ea4d3ecfcaee 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.h
+++ b/lib/Analysis/BasicObjCFoundationChecks.h
@@ -42,6 +42,7 @@ GRSimpleAPICheck *CreateAuditCFRetainRelease(ASTContext& Ctx,
BugReporter& BR);
void RegisterNSErrorChecks(BugReporter& BR, GRExprEngine &Eng, const Decl &D);
+void RegisterNSAutoreleasePoolChecks(GRExprEngine &Eng);
} // end clang namespace
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index d81d83c7bfa2..888af9bd57a4 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -92,19 +92,17 @@ public:
void iterBindings(Store store, BindingsHandler& f);
- const GRState *BindDecl(const GRState *state, const VarDecl *VD,
- const LocationContext *LC, SVal InitVal) {
- return state->makeWithStore(BindDeclInternal(state->getStore(),VD, LC,
+ const GRState *BindDecl(const GRState *state, const VarRegion *VR,
+ SVal InitVal) {
+ return state->makeWithStore(BindDeclInternal(state->getStore(), VR,
&InitVal));
}
- const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl *VD,
- const LocationContext *LC) {
- return state->makeWithStore(BindDeclInternal(state->getStore(), VD, LC, 0));
+ const GRState *BindDeclWithNoInit(const GRState *state, const VarRegion *VR) {
+ return state->makeWithStore(BindDeclInternal(state->getStore(), VR, 0));
}
- Store BindDeclInternal(Store store, const VarDecl *VD,
- const LocationContext *LC, SVal *InitVal);
+ Store BindDeclInternal(Store store, const VarRegion *VR, SVal *InitVal);
static inline BindingsTy GetBindings(Store store) {
return BindingsTy(static_cast<const BindingsTy::TreeTy*>(store));
@@ -532,11 +530,11 @@ Store BasicStoreManager::getInitialStore(const LocationContext *InitLoc) {
return St;
}
-Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
- const LocationContext *LC,
+Store BasicStoreManager::BindDeclInternal(Store store, const VarRegion* VR,
SVal* InitVal) {
BasicValueFactory& BasicVals = StateMgr.getBasicVals();
+ const VarDecl *VD = VR->getDecl();
// BasicStore does not model arrays and structs.
if (VD->getType()->isArrayType() || VD->getType()->isStructureType())
@@ -564,16 +562,16 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
if (!InitVal) {
QualType T = VD->getType();
if (Loc::IsLocType(T))
- store = BindInternal(store, getLoc(VD, LC),
+ store = BindInternal(store, loc::MemRegionVal(VR),
loc::ConcreteInt(BasicVals.getValue(0, T)));
else if (T->isIntegerType())
- store = BindInternal(store, getLoc(VD, LC),
+ store = BindInternal(store, loc::MemRegionVal(VR),
nonloc::ConcreteInt(BasicVals.getValue(0, T)));
else {
// assert(0 && "ignore other types of variables");
}
} else {
- store = BindInternal(store, getLoc(VD, LC), *InitVal);
+ store = BindInternal(store, loc::MemRegionVal(VR), *InitVal);
}
}
} else {
@@ -581,7 +579,7 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
QualType T = VD->getType();
if (ValMgr.getSymbolManager().canSymbolicate(T)) {
SVal V = InitVal ? *InitVal : UndefinedVal();
- store = BindInternal(store, getLoc(VD, LC), V);
+ store = BindInternal(store, loc::MemRegionVal(VR), V);
}
}
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index c629ad1d9612..03614e83398f 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -193,20 +193,6 @@ public:
} // end anonymous namespace
//===----------------------------------------------------------------------===//
-// Selector creation functions.
-//===----------------------------------------------------------------------===//
-
-static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
- IdentifierInfo* II = &Ctx.Idents.get(name);
- return Ctx.Selectors.getSelector(0, &II);
-}
-
-static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
- IdentifierInfo* II = &Ctx.Idents.get(name);
- return Ctx.Selectors.getSelector(1, &II);
-}
-
-//===----------------------------------------------------------------------===//
// Type querying functions.
//===----------------------------------------------------------------------===//
@@ -1031,11 +1017,25 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// Eventually this can be improved by recognizing that the pixel
// buffer passed to CVPixelBufferCreateWithBytes is released via
// a callback and doing full IPA to make sure this is done correctly.
+ // FIXME: This function has an out parameter that returns an
+ // allocated object.
ScratchArgs = AF.Add(ScratchArgs, 7, StopTracking);
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,
DoNothing);
}
break;
+
+ case 29:
+ if (!memcmp(FName, "CGBitmapContextCreateWithData", 29)) {
+ // FIXES: <rdar://problem/7358899>
+ // Eventually this can be improved by recognizing that 'releaseInfo'
+ // passed to CGBitmapContextCreateWithData is released via
+ // a callback and doing full IPA to make sure this is done correctly.
+ ScratchArgs = AF.Add(ScratchArgs, 8, StopTracking);
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ DoNothing,DoNothing);
+ }
+ break;
case 32:
if (!memcmp(FName, "IOServiceAddMatchingNotification", 32)) {
@@ -1899,7 +1899,7 @@ public:
virtual ~CFRefCount() {}
- void RegisterChecks(BugReporter &BR);
+ void RegisterChecks(GRExprEngine &Eng);
virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {
Printers.push_back(new BindingsPrinter());
@@ -2193,7 +2193,9 @@ namespace {
};
} // end anonymous namespace
-void CFRefCount::RegisterChecks(BugReporter& BR) {
+void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
+ BugReporter &BR = Eng.getBugReporter();
+
useAfterRelease = new UseAfterRelease(this);
BR.Register(useAfterRelease);
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index 89c1783cc2f5..cd4697f2f324 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -3,6 +3,8 @@ set(LLVM_NO_RTTI 1)
add_clang_library(clangAnalysis
AnalysisContext.cpp
AnalysisManager.cpp
+ AttrNonNullChecker.cpp
+ BadCallChecker.cpp
BasicConstraintManager.cpp
BasicObjCFoundationChecks.cpp
BasicStore.cpp
@@ -14,11 +16,12 @@ add_clang_library(clangAnalysis
CallGraph.cpp
CallInliner.cpp
CheckDeadStores.cpp
- CheckNSError.cpp
CheckObjCDealloc.cpp
CheckObjCInstMethSignature.cpp
CheckObjCUnusedIVars.cpp
CheckSecuritySyntaxOnly.cpp
+ DereferenceChecker.cpp
+ DivZeroChecker.cpp
Environment.cpp
ExplodedGraph.cpp
GRBlockCounter.cpp
@@ -28,6 +31,8 @@ add_clang_library(clangAnalysis
GRState.cpp
LiveVariables.cpp
MemRegion.cpp
+ NSAutoreleasePoolChecker.cpp
+ NSErrorChecker.cpp
PathDiagnostic.cpp
RangeConstraintManager.cpp
RegionStore.cpp
@@ -37,8 +42,11 @@ add_clang_library(clangAnalysis
SimpleSValuator.cpp
Store.cpp
SymbolManager.cpp
+ UndefinedArgChecker.cpp
+ UndefinedAssignmentChecker.cpp
UninitializedValues.cpp
ValueManager.cpp
+ VLASizeChecker.cpp
)
add_dependencies(clangAnalysis ClangDiagnosticAnalysis)
diff --git a/lib/Analysis/CallGraph.cpp b/lib/Analysis/CallGraph.cpp
index ae8845db63ae..17dc0685f82f 100644
--- a/lib/Analysis/CallGraph.cpp
+++ b/lib/Analysis/CallGraph.cpp
@@ -68,10 +68,8 @@ CallGraph::~CallGraph() {
}
}
-void CallGraph::addTU(ASTUnit &AST) {
- ASTContext &Ctx = AST.getASTContext();
+void CallGraph::addTU(ASTContext& Ctx) {
DeclContext *DC = Ctx.getTranslationUnitDecl();
-
for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
I != E; ++I) {
diff --git a/lib/Analysis/CheckObjCUnusedIVars.cpp b/lib/Analysis/CheckObjCUnusedIVars.cpp
index 1a900f897678..2d9b53163f6a 100644
--- a/lib/Analysis/CheckObjCUnusedIVars.cpp
+++ b/lib/Analysis/CheckObjCUnusedIVars.cpp
@@ -62,6 +62,29 @@ static void Scan(IvarUsageMap& M, const ObjCPropertyImplDecl* D) {
I->second = Used;
}
+static void Scan(IvarUsageMap& M, const ObjCContainerDecl* D) {
+ // Scan the methods for accesses.
+ for (ObjCContainerDecl::instmeth_iterator I = D->instmeth_begin(),
+ E = D->instmeth_end(); I!=E; ++I)
+ Scan(M, (*I)->getBody());
+
+ if (const ObjCImplementationDecl *ID = dyn_cast<ObjCImplementationDecl>(D)) {
+ // Scan for @synthesized property methods that act as setters/getters
+ // to an ivar.
+ for (ObjCImplementationDecl::propimpl_iterator I = ID->propimpl_begin(),
+ E = ID->propimpl_end(); I!=E; ++I)
+ Scan(M, *I);
+
+ // Scan the associated categories as well.
+ for (const ObjCCategoryDecl *CD =
+ ID->getClassInterface()->getCategoryList(); CD ;
+ CD = CD->getNextClassCategory()) {
+ if (const ObjCCategoryImplDecl *CID = CD->getImplementation())
+ Scan(M, CID);
+ }
+ }
+}
+
void clang::CheckObjCUnusedIvar(const ObjCImplementationDecl *D,
BugReporter &BR) {
@@ -88,16 +111,8 @@ void clang::CheckObjCUnusedIvar(const ObjCImplementationDecl *D,
if (M.empty())
return;
- // Now scan the methods for accesses.
- for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(),
- E = D->instmeth_end(); I!=E; ++I)
- Scan(M, (*I)->getBody());
-
- // Scan for @synthesized property methods that act as setters/getters
- // to an ivar.
- for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(),
- E = D->propimpl_end(); I!=E; ++I)
- Scan(M, *I);
+ // Now scan the implementation declaration.
+ Scan(M, D);
// Find ivars that are unused.
for (IvarUsageMap::iterator I = M.begin(), E = M.end(); I!=E; ++I)
diff --git a/lib/Analysis/DereferenceChecker.cpp b/lib/Analysis/DereferenceChecker.cpp
new file mode 100644
index 000000000000..33c85d507463
--- /dev/null
+++ b/lib/Analysis/DereferenceChecker.cpp
@@ -0,0 +1,112 @@
+//== NullDerefChecker.cpp - Null dereference checker ------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines NullDerefChecker, a builtin check in GRExprEngine that performs
+// checks for null pointers at loads and stores.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *NullDerefChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+ExplodedNode *NullDerefChecker::CheckLocation(const Stmt *S, ExplodedNode *Pred,
+ const GRState *state, SVal V,
+ GRExprEngine &Eng) {
+ Loc *LV = dyn_cast<Loc>(&V);
+
+ // If the value is not a location, don't touch the node.
+ if (!LV)
+ return Pred;
+
+ const GRState *NotNullState = state->Assume(*LV, true);
+ const GRState *NullState = state->Assume(*LV, false);
+
+ GRStmtNodeBuilder &Builder = Eng.getBuilder();
+ BugReporter &BR = Eng.getBugReporter();
+
+ // The explicit NULL case.
+ if (NullState) {
+ // Use the GDM to mark in the state what lval was null.
+ const SVal *PersistentLV = Eng.getBasicVals().getPersistentSVal(*LV);
+ NullState = NullState->set<GRState::NullDerefTag>(PersistentLV);
+
+ ExplodedNode *N = Builder.generateNode(S, NullState, Pred,
+ ProgramPoint::PostNullCheckFailedKind);
+ if (N) {
+ N->markAsSink();
+
+ if (!NotNullState) { // Explicit null case.
+ if (!BT)
+ BT = new BuiltinBug(NULL, "Null dereference",
+ "Dereference of null pointer");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetDerefExpr(N));
+
+ BR.EmitReport(R);
+
+ return 0;
+ } else // Implicit null case.
+ ImplicitNullDerefNodes.push_back(N);
+ }
+ }
+
+ if (!NotNullState)
+ return 0;
+
+ return Builder.generateNode(S, NotNullState, Pred,
+ ProgramPoint::PostLocationChecksSucceedKind);
+}
+
+
+void *UndefDerefChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+ExplodedNode *UndefDerefChecker::CheckLocation(const Stmt *S,
+ ExplodedNode *Pred,
+ const GRState *state, SVal V,
+ GRExprEngine &Eng) {
+ GRStmtNodeBuilder &Builder = Eng.getBuilder();
+ BugReporter &BR = Eng.getBugReporter();
+
+ if (V.isUndef()) {
+ ExplodedNode *N = Builder.generateNode(S, state, Pred,
+ ProgramPoint::PostUndefLocationCheckFailedKind);
+ if (N) {
+ N->markAsSink();
+
+ if (!BT)
+ BT = new BuiltinBug(0, "Undefined dereference",
+ "Dereference of undefined pointer value");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetDerefExpr(N));
+ BR.EmitReport(R);
+ }
+ return 0;
+ }
+
+ return Pred;
+}
+
diff --git a/lib/Analysis/DivZeroChecker.cpp b/lib/Analysis/DivZeroChecker.cpp
new file mode 100644
index 000000000000..9c2359f3b075
--- /dev/null
+++ b/lib/Analysis/DivZeroChecker.cpp
@@ -0,0 +1,70 @@
+//== DivZeroChecker.cpp - Division by zero checker --------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines DivZeroChecker, a builtin check in GRExprEngine that performs
+// checks for division by zeros.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h"
+
+using namespace clang;
+
+void *DivZeroChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C,
+ const BinaryOperator *B) {
+ BinaryOperator::Opcode Op = B->getOpcode();
+ if (Op != BinaryOperator::Div &&
+ Op != BinaryOperator::Rem &&
+ Op != BinaryOperator::DivAssign &&
+ Op != BinaryOperator::RemAssign)
+ return;
+
+ if (!B->getRHS()->getType()->isIntegerType() ||
+ !B->getRHS()->getType()->isScalarType())
+ return;
+
+ SVal Denom = C.getState()->getSVal(B->getRHS());
+ const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
+
+ // Divide-by-undefined handled in the generic checking for uses of
+ // undefined values.
+ if (!DV)
+ return;
+
+ // Check for divide by zero.
+ ConstraintManager &CM = C.getConstraintManager();
+ const GRState *stateNotZero, *stateZero;
+ llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
+
+ if (stateZero && !stateNotZero) {
+ if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
+ if (!BT)
+ BT = new BuiltinBug(0, "Division by zero");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
+
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetDenomExpr(N));
+
+ C.EmitReport(R);
+ }
+ return;
+ }
+
+ // If we get here, then the denom should not be zero. We abandon the implicit
+ // zero denom case for now.
+ if (stateNotZero != C.getState())
+ C.addTransition(C.GenerateNode(B, stateNotZero));
+}
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index ea0255ded8a9..c71882e4d888 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -25,6 +25,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/StringSwitch.h"
#ifndef NDEBUG
#include "llvm/Support/GraphWriter.h"
@@ -117,17 +118,18 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
ExplodedNodeSet Tmp;
ExplodedNodeSet *PrevSet = &Src;
- for (std::vector<Checker*>::iterator I = Checkers.begin(), E = Checkers.end();
- I != E; ++I) {
-
- ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
+ {
+ ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst
: (PrevSet == &Tmp) ? &Src : &Tmp;
+
CurrSet->clear();
- Checker *checker = *I;
+ void *tag = I->first;
+ Checker *checker = I->second;
for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
NI != NE; ++NI)
- checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, isPrevisit);
+ checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, tag, isPrevisit);
// Update which NodeSet is the current one.
PrevSet = CurrSet;
@@ -137,6 +139,41 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
// automatically.
}
+// FIXME: This is largely copy-paste from CheckerVisit(). Need to
+// unify.
+void GRExprEngine::CheckerVisitBind(Stmt *S, ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Src,
+ SVal location, SVal val, bool isPrevisit) {
+
+ if (Checkers.empty()) {
+ Dst = Src;
+ return;
+ }
+
+ ExplodedNodeSet Tmp;
+ ExplodedNodeSet *PrevSet = &Src;
+
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
+ {
+ ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst
+ : (PrevSet == &Tmp) ? &Src : &Tmp;
+
+ CurrSet->clear();
+ void *tag = I->first;
+ Checker *checker = I->second;
+
+ for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
+ NI != NE; ++NI)
+ checker->GR_VisitBind(*CurrSet, *Builder, *this, S, *NI, tag, location,
+ val, isPrevisit);
+
+ // Update which NodeSet is the current one.
+ PrevSet = CurrSet;
+ }
+
+ // Don't autotransition. The CheckerContext objects should do this
+ // automatically.
+}
//===----------------------------------------------------------------------===//
// Engine construction and deletion.
//===----------------------------------------------------------------------===//
@@ -165,9 +202,8 @@ GRExprEngine::GRExprEngine(AnalysisManager &mgr)
GRExprEngine::~GRExprEngine() {
BR.FlushReports();
delete [] NSExceptionInstanceRaiseSelectors;
- for (std::vector<Checker*>::iterator I=Checkers.begin(), E=Checkers.end();
- I!=E; ++I)
- delete *I;
+ for (CheckersOrdered::iterator I=Checkers.begin(), E=Checkers.end(); I!=E;++I)
+ delete I->second;
}
//===----------------------------------------------------------------------===//
@@ -177,7 +213,7 @@ GRExprEngine::~GRExprEngine() {
void GRExprEngine::setTransferFunctions(GRTransferFuncs* tf) {
StateMgr.TF = tf;
- tf->RegisterChecks(getBugReporter());
+ tf->RegisterChecks(*this);
tf->RegisterPrinters(getStateManager().Printers);
}
@@ -369,11 +405,11 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
if (AMgr.shouldEagerlyAssume() && (B->isRelationalOp() || B->isEqualityOp())) {
ExplodedNodeSet Tmp;
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp, false);
EvalEagerlyAssume(Dst, Tmp, cast<Expr>(S));
}
else
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst, false);
break;
}
@@ -395,7 +431,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
}
case Stmt::CompoundAssignOperatorClass:
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst, false);
break;
case Stmt::CompoundLiteralExprClass:
@@ -409,7 +445,6 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
}
case Stmt::DeclRefExprClass:
- case Stmt::QualifiedDeclRefExprClass:
VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst, false);
break;
@@ -522,7 +557,6 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
return;
case Stmt::DeclRefExprClass:
- case Stmt::QualifiedDeclRefExprClass:
VisitDeclRefExpr(cast<DeclRefExpr>(Ex), Pred, Dst, true);
return;
@@ -565,6 +599,11 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
return;
}
+ case Stmt::BinaryOperatorClass:
+ case Stmt::CompoundAssignOperatorClass:
+ VisitBinaryOperator(cast<BinaryOperator>(Ex), Pred, Dst, true);
+ return;
+
default:
// Arbitrary subexpressions can return aggregate temporaries that
// can be used in a lvalue context. We need to enhance our support
@@ -1078,8 +1117,7 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred,
SVal L = state->getLValue(Field, state->getSVal(Base));
if (asLValue)
- MakeNode(Dst, M, *I, state->BindExpr(M, L),
- ProgramPoint::PostLValueKind);
+ MakeNode(Dst, M, *I, state->BindExpr(M, L), ProgramPoint::PostLValueKind);
else
EvalLoad(Dst, M, *I, state, L);
}
@@ -1087,30 +1125,52 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred,
/// EvalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by EvalStore and (soon) VisitDeclStmt, and others.
-void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
- const GRState* state, SVal location, SVal Val) {
+void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred,
+ const GRState* state, SVal location, SVal Val,
+ bool atDeclInit) {
+
+
+ // Do a previsit of the bind.
+ ExplodedNodeSet CheckedSet, Src;
+ Src.Add(Pred);
+ CheckerVisitBind(Ex, CheckedSet, Src, location, Val, true);
+
+ for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
+ I!=E; ++I) {
+
+ if (Pred != *I)
+ state = GetState(*I);
+
+ const GRState* newState = 0;
- const GRState* newState = 0;
+ if (atDeclInit) {
+ const VarRegion *VR =
+ cast<VarRegion>(cast<loc::MemRegionVal>(location).getRegion());
- if (location.isUnknown()) {
- // We know that the new state will be the same as the old state since
- // the location of the binding is "unknown". Consequently, there
- // is no reason to just create a new node.
- newState = state;
- }
- else {
- // We are binding to a value other than 'unknown'. Perform the binding
- // using the StoreManager.
- newState = state->bindLoc(cast<Loc>(location), Val);
- }
+ newState = state->bindDecl(VR, Val);
+ }
+ else {
+ if (location.isUnknown()) {
+ // We know that the new state will be the same as the old state since
+ // the location of the binding is "unknown". Consequently, there
+ // is no reason to just create a new node.
+ newState = state;
+ }
+ else {
+ // We are binding to a value other than 'unknown'. Perform the binding
+ // using the StoreManager.
+ newState = state->bindLoc(cast<Loc>(location), Val);
+ }
+ }
- // The next thing to do is check if the GRTransferFuncs object wants to
- // update the state based on the new binding. If the GRTransferFunc object
- // doesn't do anything, just auto-propagate the current state.
- GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, Pred, newState, Ex,
- newState != state);
+ // The next thing to do is check if the GRTransferFuncs object wants to
+ // update the state based on the new binding. If the GRTransferFunc object
+ // doesn't do anything, just auto-propagate the current state.
+ GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, Ex,
+ newState != state);
- getTF().EvalBind(BuilderRef, location, Val);
+ getTF().EvalBind(BuilderRef, location, Val);
+ }
}
/// EvalStore - Handle the semantics of a store via an assignment.
@@ -1189,58 +1249,18 @@ ExplodedNode* GRExprEngine::EvalLocation(Stmt* Ex, ExplodedNode* Pred,
SaveAndRestore<const void*> OldTag(Builder->Tag);
Builder->Tag = tag;
- // Check for loads/stores from/to undefined values.
- if (location.isUndef()) {
- ExplodedNode* N =
- Builder->generateNode(Ex, state, Pred,
- ProgramPoint::PostUndefLocationCheckFailedKind);
-
- if (N) {
- N->markAsSink();
- UndefDeref.insert(N);
- }
-
- return 0;
- }
-
- // Check for loads/stores from/to unknown locations. Treat as No-Ops.
- if (location.isUnknown())
+ if (location.isUnknown() || Checkers.empty())
return Pred;
- // During a load, one of two possible situations arise:
- // (1) A crash, because the location (pointer) was NULL.
- // (2) The location (pointer) is not NULL, and the dereference works.
- //
- // We add these assumptions.
-
- Loc LV = cast<Loc>(location);
-
- // "Assume" that the pointer is not NULL.
- const GRState *StNotNull = state->Assume(LV, true);
-
- // "Assume" that the pointer is NULL.
- const GRState *StNull = state->Assume(LV, false);
-
- if (StNull) {
- // Use the Generic Data Map to mark in the state what lval was null.
- const SVal* PersistentLV = getBasicVals().getPersistentSVal(LV);
- StNull = StNull->set<GRState::NullDerefTag>(PersistentLV);
-
- // We don't use "MakeNode" here because the node will be a sink
- // and we have no intention of processing it later.
- ExplodedNode* NullNode =
- Builder->generateNode(Ex, StNull, Pred,
- ProgramPoint::PostNullCheckFailedKind);
-
- if (NullNode) {
- NullNode->markAsSink();
- if (StNotNull) ImplicitNullDeref.insert(NullNode);
- else ExplicitNullDeref.insert(NullNode);
- }
+
+ for (CheckersOrdered::iterator I=Checkers.begin(), E=Checkers.end(); I!=E;++I)
+ {
+ Pred = I->second->CheckLocation(Ex, Pred, state, location, *this);
+ if (!Pred)
+ break;
}
-
- if (!StNotNull)
- return NULL;
+
+ return Pred;
// FIXME: Temporarily disable out-of-bounds checking until we make
// the logic reflect recent changes to CastRegion and friends.
@@ -1283,10 +1303,6 @@ ExplodedNode* GRExprEngine::EvalLocation(Stmt* Ex, ExplodedNode* Pred,
}
}
#endif
-
- // Generate a new node indicating the checks succeed.
- return Builder->generateNode(Ex, StNotNull, Pred,
- ProgramPoint::PostLocationChecksSucceedKind);
}
//===----------------------------------------------------------------------===//
@@ -1445,75 +1461,30 @@ static void MarkNoReturnFunction(const FunctionDecl *FD, CallExpr *CE,
// HACK: Some functions are not marked noreturn, and don't return.
// Here are a few hardwired ones. If this takes too long, we can
// potentially cache these results.
- const char* s = FD->getIdentifier()->getNameStart();
-
- switch (FD->getIdentifier()->getLength()) {
- default:
- break;
-
- case 4:
- if (!memcmp(s, "exit", 4)) Builder->BuildSinks = true;
- break;
-
- case 5:
- if (!memcmp(s, "panic", 5)) Builder->BuildSinks = true;
- else if (!memcmp(s, "error", 5)) {
- if (CE->getNumArgs() > 0) {
- SVal X = state->getSVal(*CE->arg_begin());
- // FIXME: use Assume to inspect the possible symbolic value of
- // X. Also check the specific signature of error().
- nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&X);
- if (CI && CI->getValue() != 0)
- Builder->BuildSinks = true;
- }
- }
- break;
-
- case 6:
- if (!memcmp(s, "Assert", 6)) {
- Builder->BuildSinks = true;
- break;
- }
-
- // FIXME: This is just a wrapper around throwing an exception.
- // Eventually inter-procedural analysis should handle this easily.
- if (!memcmp(s, "ziperr", 6)) Builder->BuildSinks = true;
-
- break;
-
- case 7:
- if (!memcmp(s, "assfail", 7)) Builder->BuildSinks = true;
- break;
-
- case 8:
- if (!memcmp(s ,"db_error", 8) ||
- !memcmp(s, "__assert", 8))
- Builder->BuildSinks = true;
- break;
-
- case 12:
- if (!memcmp(s, "__assert_rtn", 12)) Builder->BuildSinks = true;
- break;
-
- case 13:
- if (!memcmp(s, "__assert_fail", 13)) Builder->BuildSinks = true;
- break;
-
- case 14:
- if (!memcmp(s, "dtrace_assfail", 14) ||
- !memcmp(s, "yy_fatal_error", 14))
- Builder->BuildSinks = true;
- break;
-
- case 26:
- if (!memcmp(s, "_XCAssertionFailureHandler", 26) ||
- !memcmp(s, "_DTAssertionFailureHandler", 26) ||
- !memcmp(s, "_TSAssertionFailureHandler", 26))
- Builder->BuildSinks = true;
-
- break;
- }
-
+ using llvm::StringRef;
+ bool BuildSinks
+ = llvm::StringSwitch<bool>(StringRef(FD->getIdentifier()->getName()))
+ .Case("exit", true)
+ .Case("panic", true)
+ .Case("error", true)
+ .Case("Assert", true)
+ // FIXME: This is just a wrapper around throwing an exception.
+ // Eventually inter-procedural analysis should handle this easily.
+ .Case("ziperr", true)
+ .Case("assfail", true)
+ .Case("db_error", true)
+ .Case("__assert", true)
+ .Case("__assert_rtn", true)
+ .Case("__assert_fail", true)
+ .Case("dtrace_assfail", true)
+ .Case("yy_fatal_error", true)
+ .Case("_XCAssertionFailureHandler", true)
+ .Case("_DTAssertionFailureHandler", true)
+ .Case("_TSAssertionFailureHandler", true)
+ .Default(false);
+
+ if (BuildSinks)
+ Builder->BuildSinks = true;
}
}
@@ -2042,24 +2013,27 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
}
}
+ // Handle previsits checks.
+ ExplodedNodeSet Src, DstTmp;
+ Src.Add(Pred);
+ CheckerVisit(ME, DstTmp, Src, true);
+
// Check if we raise an exception. For now treat these as sinks. Eventually
// we will want to handle exceptions properly.
-
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-
if (RaisesException)
Builder->BuildSinks = true;
// Dispatch to plug-in transfer function.
-
unsigned size = Dst.size();
SaveOr OldHasGen(Builder->HasGeneratedNode);
-
- EvalObjCMessageExpr(Dst, ME, Pred);
+
+ for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end();
+ DI!=DE; ++DI)
+ EvalObjCMessageExpr(Dst, ME, *DI);
// Handle the case where no nodes where generated. Auto-generate that
// contains the updated state if we aren't generating sinks.
-
if (!Builder->BuildSinks && Dst.size() == size && !Builder->HasGeneratedNode)
MakeNode(Dst, ME, Pred, state);
}
@@ -2141,45 +2115,25 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
Tmp.Add(Pred);
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
- const GRState* state = GetState(*I);
- unsigned Count = Builder->getCurrentBlockCount();
-
- // Check if 'VD' is a VLA and if so check if has a non-zero size.
- QualType T = getContext().getCanonicalType(VD->getType());
- if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
- // FIXME: Handle multi-dimensional VLAs.
-
- Expr* SE = VLA->getSizeExpr();
- SVal Size_untested = state->getSVal(SE);
-
- if (Size_untested.isUndef()) {
- if (ExplodedNode* N = Builder->generateNode(DS, state, Pred)) {
- N->markAsSink();
- ExplicitBadSizedVLA.insert(N);
- }
- continue;
- }
-
- DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Size_untested);
- const GRState *zeroState = state->Assume(Size, false);
- state = state->Assume(Size, true);
+ ExplodedNode *N = *I;
+ const GRState *state;
+
+ for (CheckersOrdered::iterator CI = Checkers.begin(), CE = Checkers.end();
+ CI != CE; ++CI) {
+ state = GetState(N);
+ N = CI->second->CheckType(getContext().getCanonicalType(VD->getType()),
+ N, state, DS, *this);
+ if (!N)
+ break;
+ }
- if (zeroState) {
- if (ExplodedNode* N = Builder->generateNode(DS, zeroState, Pred)) {
- N->markAsSink();
- if (state)
- ImplicitBadSizedVLA.insert(N);
- else
- ExplicitBadSizedVLA.insert(N);
- }
- }
+ if (!N)
+ continue;
- if (!state)
- continue;
- }
+ state = GetState(N);
// Decls without InitExpr are not initialized explicitly.
- const LocationContext *LC = (*I)->getLocationContext();
+ const LocationContext *LC = N->getLocationContext();
if (InitEx) {
SVal InitVal = state->getSVal(InitEx);
@@ -2189,20 +2143,15 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
// UnknownVal.
if (InitVal.isUnknown() ||
!getConstraintManager().canReasonAbout(InitVal)) {
- InitVal = ValMgr.getConjuredSymbolVal(NULL, InitEx, Count);
+ InitVal = ValMgr.getConjuredSymbolVal(NULL, InitEx,
+ Builder->getCurrentBlockCount());
}
-
- state = state->bindDecl(VD, LC, InitVal);
-
- // The next thing to do is check if the GRTransferFuncs object wants to
- // update the state based on the new binding. If the GRTransferFunc
- // object doesn't do anything, just auto-propagate the current state.
- GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, state, DS,true);
- getTF().EvalBind(BuilderRef, loc::MemRegionVal(state->getRegion(VD, LC)),
- InitVal);
+
+ EvalBind(Dst, DS, *I, state, loc::MemRegionVal(state->getRegion(VD, LC)),
+ InitVal, true);
}
else {
- state = state->bindDeclWithNoInit(VD, LC);
+ state = state->bindDeclWithNoInit(state->getRegion(VD, LC));
MakeNode(Dst, DS, *I, state);
}
}
@@ -2752,7 +2701,7 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt* S, ExplodedNode* Pred,
void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
ExplodedNode* Pred,
- ExplodedNodeSet& Dst) {
+ ExplodedNodeSet& Dst, bool asLValue) {
ExplodedNodeSet Tmp1;
Expr* LHS = B->getLHS()->IgnoreParens();
@@ -2798,10 +2747,12 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
unsigned Count = Builder->getCurrentBlockCount();
RightV = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), Count);
}
-
+
+ SVal ExprVal = asLValue ? LeftV : RightV;
+
// Simulate the effects of a "store": bind the value of the RHS
// to the L-Value represented by the LHS.
- EvalStore(Dst, B, LHS, *I2, state->BindExpr(B, RightV), LeftV, RightV);
+ EvalStore(Dst, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV, RightV);
continue;
}
@@ -2930,6 +2881,15 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
}
//===----------------------------------------------------------------------===//
+// Checker registration/lookup.
+//===----------------------------------------------------------------------===//
+
+Checker *GRExprEngine::lookupChecker(void *tag) const {
+ CheckerMap::iterator I = CheckerM.find(tag);
+ return (I == CheckerM.end()) ? NULL : Checkers[I->second].second;
+}
+
+//===----------------------------------------------------------------------===//
// Visualization.
//===----------------------------------------------------------------------===//
@@ -2941,7 +2901,8 @@ namespace llvm {
template<>
struct VISIBILITY_HIDDEN DOTGraphTraits<ExplodedNode*> :
public DefaultDOTGraphTraits {
-
+ // FIXME: Since we do not cache error nodes in GRExprEngine now, this does not
+ // work.
static std::string getNodeAttributes(const ExplodedNode* N, void*) {
if (GraphPrintCheckerState->isImplicitNullDeref(N) ||
diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp
index da24192c9d5a..695f0b02e597 100644
--- a/lib/Analysis/GRExprEngineInternalChecks.cpp
+++ b/lib/Analysis/GRExprEngineInternalChecks.cpp
@@ -15,6 +15,13 @@
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h"
+#include "clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/Compiler.h"
@@ -40,10 +47,8 @@ ExplodedNode* GetNode(GRExprEngine::undef_arg_iterator I) {
//===----------------------------------------------------------------------===//
// Bug Descriptions.
//===----------------------------------------------------------------------===//
-
-namespace {
-
-class VISIBILITY_HIDDEN BuiltinBugReport : public RangedBugReport {
+namespace clang {
+class BuiltinBugReport : public RangedBugReport {
public:
BuiltinBugReport(BugType& bt, const char* desc,
ExplodedNode *n)
@@ -57,30 +62,10 @@ public:
const ExplodedNode* N);
};
-class VISIBILITY_HIDDEN BuiltinBug : public BugType {
- GRExprEngine &Eng;
-protected:
- const std::string desc;
-public:
- BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
- : BugType(n, "Logic errors"), Eng(*eng), desc(d) {}
-
- BuiltinBug(GRExprEngine *eng, const char* n)
- : BugType(n, "Logic errors"), Eng(*eng), desc(n) {}
-
- const std::string &getDescription() const { return desc; }
-
- virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {}
-
- void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
-
- virtual void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {}
-
- template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E);
-};
-
+void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
+ const ExplodedNode* N) {
+ static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
+}
template <typename ITER>
void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
@@ -88,27 +73,6 @@ void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
GetNode(I)));
}
-void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N) {
- static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
-}
-
-class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
-public:
- NullDeref(GRExprEngine* eng)
- : BuiltinBug(eng,"Null dereference", "Dereference of null pointer") {}
-
- void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
- Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
- }
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {
- registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
- }
-};
-
class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
public:
NilReceiverStructRet(GRExprEngine* eng) :
@@ -175,34 +139,6 @@ public:
}
};
-class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
-public:
- UndefinedDeref(GRExprEngine* eng)
- : BuiltinBug(eng,"Dereference of undefined pointer value") {}
-
- void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
- Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
- }
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {
- registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
- }
-};
-
-class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
-public:
- DivZero(GRExprEngine* eng = 0)
- : BuiltinBug(eng,"Division by zero") {}
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {
- registerTrackNullOrUndefValue(BRC, GetDenomExpr(N), N);
- }
-};
-
class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
public:
UndefResult(GRExprEngine* eng)
@@ -279,20 +215,6 @@ public:
}
};
-class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
-public:
- BadCall(GRExprEngine *eng = 0)
- : BuiltinBug(eng, "Invalid function call",
- "Called function pointer is a null or undefined pointer value") {}
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {
- registerTrackNullOrUndefValue(BRC, GetCalleeExpr(N), N);
- }
-};
-
-
class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
const Stmt *Arg;
public:
@@ -528,276 +450,8 @@ public:
}
};
-class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
-public:
- BadSizeVLA(GRExprEngine* eng) :
- BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
-
- void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
- for (GRExprEngine::ErrorNodes::iterator
- I = Eng.ExplicitBadSizedVLA.begin(),
- E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
-
- // Determine whether this was a 'zero-sized' VLA or a VLA with an
- // undefined size.
- ExplodedNode* N = *I;
- PostStmt PS = cast<PostStmt>(N->getLocation());
- const DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
- VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
- QualType T = Eng.getContext().getCanonicalType(VD->getType());
- VariableArrayType* VT = cast<VariableArrayType>(T);
- Expr* SizeExpr = VT->getSizeExpr();
-
- std::string buf;
- llvm::raw_string_ostream os(buf);
- os << "The expression used to specify the number of elements in the "
- "variable-length array (VLA) '"
- << VD->getNameAsString() << "' evaluates to ";
-
- bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
-
- if (isUndefined)
- os << "an undefined or garbage value.";
- else
- os << "0. VLAs with no elements have undefined behavior.";
-
- std::string shortBuf;
- llvm::raw_string_ostream os_short(shortBuf);
- os_short << "Variable-length array '" << VD->getNameAsString() << "' "
- << (isUndefined ? "garbage value for array size"
- : "has zero elements (undefined behavior)");
-
- ArgReport *report = new ArgReport(*this, os_short.str().c_str(),
- os.str().c_str(), N, SizeExpr);
-
- report->addRange(SizeExpr->getSourceRange());
- BR.EmitReport(report);
- }
- }
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {
- registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
- N);
- }
-};
-
-//===----------------------------------------------------------------------===//
-// __attribute__(nonnull) checking
-
-class VISIBILITY_HIDDEN CheckAttrNonNull :
- public CheckerVisitor<CheckAttrNonNull> {
-
- BugType *BT;
-
-public:
- CheckAttrNonNull() : BT(0) {}
- ~CheckAttrNonNull() {}
-
- const void *getTag() {
- static int x = 0;
- return &x;
- }
-
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
- const GRState *state = C.getState();
- const GRState *originalState = state;
-
- // Check if the callee has a 'nonnull' attribute.
- SVal X = state->getSVal(CE->getCallee());
-
- const FunctionDecl* FD = X.getAsFunctionDecl();
- if (!FD)
- return;
+} // end clang namespace
- const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
- if (!Att)
- return;
-
- // Iterate through the arguments of CE and check them for null.
- unsigned idx = 0;
-
- for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
- ++I, ++idx) {
-
- if (!Att->isNonNull(idx))
- continue;
-
- const SVal &V = state->getSVal(*I);
- const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
-
- if (!DV)
- continue;
-
- ConstraintManager &CM = C.getConstraintManager();
- const GRState *stateNotNull, *stateNull;
- llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
-
- if (stateNull && !stateNotNull) {
- // Generate an error node. Check for a null node in case
- // we cache out.
- if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
-
- // Lazily allocate the BugType object if it hasn't already been
- // created. Ownership is transferred to the BugReporter object once
- // the BugReport is passed to 'EmitWarning'.
- if (!BT)
- BT = new BugType("Argument with 'nonnull' attribute passed null",
- "API");
-
- EnhancedBugReport *R =
- new EnhancedBugReport(*BT,
- "Null pointer passed as an argument to a "
- "'nonnull' parameter", errorNode);
-
- // Highlight the range of the argument that was null.
- const Expr *arg = *I;
- R->addRange(arg->getSourceRange());
- R->addVisitorCreator(registerTrackNullOrUndefValue, arg);
-
- // Emit the bug report.
- C.EmitReport(R);
- }
-
- // Always return. Either we cached out or we just emitted an error.
- return;
- }
-
- // If a pointer value passed the check we should assume that it is
- // indeed not null from this point forward.
- assert(stateNotNull);
- state = stateNotNull;
- }
-
- // If we reach here all of the arguments passed the nonnull check.
- // If 'state' has been updated generated a new node.
- if (state != originalState)
- C.addTransition(C.GenerateNode(CE, state));
- }
-};
-} // end anonymous namespace
-
-// Undefined arguments checking.
-namespace {
-class VISIBILITY_HIDDEN CheckUndefinedArg
- : public CheckerVisitor<CheckUndefinedArg> {
-
- BadArg *BT;
-
-public:
- CheckUndefinedArg() : BT(0) {}
- ~CheckUndefinedArg() {}
-
- const void *getTag() {
- static int x = 0;
- return &x;
- }
-
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
-};
-
-void CheckUndefinedArg::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE){
- for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
- I != E; ++I) {
- if (C.getState()->getSVal(*I).isUndef()) {
- if (ExplodedNode *ErrorNode = C.GenerateNode(CE, true)) {
- if (!BT)
- BT = new BadArg();
- // Generate a report for this bug.
- ArgReport *Report = new ArgReport(*BT, BT->getDescription().c_str(),
- ErrorNode, *I);
- Report->addRange((*I)->getSourceRange());
- C.EmitReport(Report);
- }
- }
- }
-}
-
-class VISIBILITY_HIDDEN CheckBadCall : public CheckerVisitor<CheckBadCall> {
- BadCall *BT;
-
-public:
- CheckBadCall() : BT(0) {}
- ~CheckBadCall() {}
-
- const void *getTag() {
- static int x = 0;
- return &x;
- }
-
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
-};
-
-void CheckBadCall::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
- const Expr *Callee = CE->getCallee()->IgnoreParens();
- SVal L = C.getState()->getSVal(Callee);
-
- if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
- if (ExplodedNode *N = C.GenerateNode(CE, true)) {
- if (!BT)
- BT = new BadCall();
- C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
- }
- }
-}
-
-class VISIBILITY_HIDDEN CheckDivZero : public CheckerVisitor<CheckDivZero> {
- DivZero *BT;
-public:
- CheckDivZero() : BT(0) {}
- ~CheckDivZero() {}
-
- const void *getTag() {
- static int x;
- return &x;
- }
-
- void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
-};
-
-void CheckDivZero::PreVisitBinaryOperator(CheckerContext &C,
- const BinaryOperator *B) {
- BinaryOperator::Opcode Op = B->getOpcode();
- if (Op != BinaryOperator::Div &&
- Op != BinaryOperator::Rem &&
- Op != BinaryOperator::DivAssign &&
- Op != BinaryOperator::RemAssign)
- return;
-
- if (!B->getRHS()->getType()->isIntegerType() ||
- !B->getRHS()->getType()->isScalarType())
- return;
-
- SVal Denom = C.getState()->getSVal(B->getRHS());
- const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
-
- // Divide-by-undefined handled in the generic checking for uses of
- // undefined values.
- if (!DV)
- return;
-
- // Check for divide by zero.
- ConstraintManager &CM = C.getConstraintManager();
- const GRState *stateNotZero, *stateZero;
- llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
-
- if (stateZero && !stateNotZero) {
- if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
- if (!BT)
- BT = new DivZero();
-
- C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
- }
- return;
- }
-
- // If we get here, then the denom should not be zero. We abandon the implicit
- // zero denom case for now.
- if (stateNotZero != C.getState())
- C.addTransition(C.GenerateNode(B, stateNotZero));
-}
-}
//===----------------------------------------------------------------------===//
// Check registration.
//===----------------------------------------------------------------------===//
@@ -808,8 +462,6 @@ void GRExprEngine::RegisterInternalChecks() {
// create BugReports on-the-fly but instead wait until GRExprEngine finishes
// analyzing a function. Generation of BugReport objects is done via a call
// to 'FlushReports' from BugReporter.
- BR.Register(new NullDeref(this));
- BR.Register(new UndefinedDeref(this));
BR.Register(new UndefBranch(this));
BR.Register(new UndefResult(this));
BR.Register(new RetStack(this));
@@ -817,7 +469,6 @@ void GRExprEngine::RegisterInternalChecks() {
BR.Register(new BadMsgExprArg(this));
BR.Register(new BadReceiver(this));
BR.Register(new OutOfBoundMemoryAccess(this));
- BR.Register(new BadSizeVLA(this));
BR.Register(new NilReceiverStructRet(this));
BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
@@ -826,8 +477,13 @@ void GRExprEngine::RegisterInternalChecks() {
// their associated BugType will get registered with the BugReporter
// automatically. Note that the check itself is owned by the GRExprEngine
// object.
- registerCheck(new CheckAttrNonNull());
- registerCheck(new CheckUndefinedArg());
- registerCheck(new CheckBadCall());
- registerCheck(new CheckDivZero());
+ registerCheck(new AttrNonNullChecker());
+ registerCheck(new UndefinedArgChecker());
+ registerCheck(new UndefinedAssignmentChecker());
+ registerCheck(new BadCallChecker());
+ registerCheck(new DivZeroChecker());
+ registerCheck(new UndefDerefChecker());
+ registerCheck(new NullDerefChecker());
+ registerCheck(new UndefSizedVLAChecker());
+ registerCheck(new ZeroSizedVLAChecker());
}
diff --git a/lib/Analysis/NSAutoreleasePoolChecker.cpp b/lib/Analysis/NSAutoreleasePoolChecker.cpp
new file mode 100644
index 000000000000..e0a8d0dc5f73
--- /dev/null
+++ b/lib/Analysis/NSAutoreleasePoolChecker.cpp
@@ -0,0 +1,84 @@
+//=- NSAutoreleasePoolChecker.cpp --------------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a NSAutoreleasePoolChecker, a small checker that warns
+// about subpar uses of NSAutoreleasePool. Note that while the check itself
+// (in it's current form) could be written as a flow-insensitive check, in
+// can be potentially enhanced in the future with flow-sensitive information.
+// It is also a good example of the CheckerVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "BasicObjCFoundationChecks.h"
+#include "llvm/Support/Compiler.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Decl.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN NSAutoreleasePoolChecker
+ : public CheckerVisitor<NSAutoreleasePoolChecker> {
+
+ Selector releaseS;
+
+public:
+ NSAutoreleasePoolChecker(Selector release_s) : releaseS(release_s) {}
+
+ static void *getTag() {
+ static int x = 0;
+ return &x;
+ }
+
+ void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
+};
+
+} // end anonymous namespace
+
+
+void clang::RegisterNSAutoreleasePoolChecks(GRExprEngine &Eng) {
+ ASTContext &Ctx = Eng.getContext();
+ if (Ctx.getLangOptions().getGCMode() != LangOptions::NonGC) {
+ Eng.registerCheck(new NSAutoreleasePoolChecker(GetNullarySelector("release",
+ Ctx)));
+ }
+}
+
+void
+NSAutoreleasePoolChecker::PreVisitObjCMessageExpr(CheckerContext &C,
+ const ObjCMessageExpr *ME) {
+
+ const Expr *receiver = ME->getReceiver();
+ if (!receiver)
+ return;
+
+ // FIXME: Enhance with value-tracking information instead of consulting
+ // the type of the expression.
+ const ObjCObjectPointerType* PT =
+ receiver->getType()->getAs<ObjCObjectPointerType>();
+ const ObjCInterfaceDecl* OD = PT->getInterfaceDecl();
+ if (!OD)
+ return;
+ if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool"))
+ return;
+
+ // Sending 'release' message?
+ if (ME->getSelector() != releaseS)
+ return;
+
+ SourceRange R = ME->getSourceRange();
+
+ C.getBugReporter().EmitBasicReport("Use -drain instead of -release",
+ "API Upgrade (Apple)",
+ "Use -drain instead of -release when using NSAutoreleasePool "
+ "and garbage collection", ME->getLocStart(), &R, 1);
+}
diff --git a/lib/Analysis/CheckNSError.cpp b/lib/Analysis/NSErrorChecker.cpp
index 8086da588264..307686ff57b3 100644
--- a/lib/Analysis/CheckNSError.cpp
+++ b/lib/Analysis/NSErrorChecker.cpp
@@ -1,4 +1,4 @@
-//=- CheckNSError.cpp - Coding conventions for uses of NSError ---*- C++ -*-==//
+//=- NSErrorCheckerer.cpp - Coding conventions for uses of NSError -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@@ -18,6 +18,7 @@
#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
#include "BasicObjCFoundationChecks.h"
#include "llvm/Support/Compiler.h"
#include "clang/AST/DeclObjC.h"
@@ -27,7 +28,7 @@
using namespace clang;
namespace {
-class VISIBILITY_HIDDEN NSErrorCheck : public BugType {
+class VISIBILITY_HIDDEN NSErrorChecker : public BugType {
const Decl &CodeDecl;
const bool isNSErrorWarning;
IdentifierInfo * const II;
@@ -48,7 +49,7 @@ class VISIBILITY_HIDDEN NSErrorCheck : public BugType {
void EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl);
public:
- NSErrorCheck(const Decl &D, bool isNSError, GRExprEngine& eng)
+ NSErrorChecker(const Decl &D, bool isNSError, GRExprEngine& eng)
: BugType(isNSError ? "NSError** null dereference"
: "CFErrorRef* null dereference",
"Coding conventions (Apple)"),
@@ -64,11 +65,11 @@ public:
void clang::RegisterNSErrorChecks(BugReporter& BR, GRExprEngine &Eng,
const Decl &D) {
- BR.Register(new NSErrorCheck(D, true, Eng));
- BR.Register(new NSErrorCheck(D, false, Eng));
+ BR.Register(new NSErrorChecker(D, true, Eng));
+ BR.Register(new NSErrorChecker(D, false, Eng));
}
-void NSErrorCheck::FlushReports(BugReporter& BR) {
+void NSErrorChecker::FlushReports(BugReporter& BR) {
// Get the analysis engine and the exploded analysis graph.
ExplodedGraph& G = Eng.getGraph();
@@ -99,7 +100,7 @@ void NSErrorCheck::FlushReports(BugReporter& BR) {
}
}
-void NSErrorCheck::EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl) {
+void NSErrorChecker::EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl) {
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
@@ -121,7 +122,7 @@ void NSErrorCheck::EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl) {
}
void
-NSErrorCheck::CheckSignature(const ObjCMethodDecl& M, QualType& ResultTy,
+NSErrorChecker::CheckSignature(const ObjCMethodDecl& M, QualType& ResultTy,
llvm::SmallVectorImpl<VarDecl*>& ErrorParams) {
ResultTy = M.getResultType();
@@ -140,7 +141,7 @@ NSErrorCheck::CheckSignature(const ObjCMethodDecl& M, QualType& ResultTy,
}
void
-NSErrorCheck::CheckSignature(const FunctionDecl& F, QualType& ResultTy,
+NSErrorChecker::CheckSignature(const FunctionDecl& F, QualType& ResultTy,
llvm::SmallVectorImpl<VarDecl*>& ErrorParams) {
ResultTy = F.getResultType();
@@ -159,7 +160,7 @@ NSErrorCheck::CheckSignature(const FunctionDecl& F, QualType& ResultTy,
}
-bool NSErrorCheck::CheckNSErrorArgument(QualType ArgTy) {
+bool NSErrorChecker::CheckNSErrorArgument(QualType ArgTy) {
const PointerType* PPT = ArgTy->getAs<PointerType>();
if (!PPT)
@@ -180,7 +181,7 @@ bool NSErrorCheck::CheckNSErrorArgument(QualType ArgTy) {
return false;
}
-bool NSErrorCheck::CheckCFErrorArgument(QualType ArgTy) {
+bool NSErrorChecker::CheckCFErrorArgument(QualType ArgTy) {
const PointerType* PPT = ArgTy->getAs<PointerType>();
if (!PPT) return false;
@@ -191,7 +192,7 @@ bool NSErrorCheck::CheckCFErrorArgument(QualType ArgTy) {
return TT->getDecl()->getIdentifier() == II;
}
-void NSErrorCheck::CheckParamDeref(const VarDecl *Param,
+void NSErrorChecker::CheckParamDeref(const VarDecl *Param,
const LocationContext *LC,
const GRState *rootState,
BugReporter& BR) {
@@ -208,8 +209,10 @@ void NSErrorCheck::CheckParamDeref(const VarDecl *Param,
return;
// Iterate over the implicit-null dereferences.
- for (GRExprEngine::null_deref_iterator I=Eng.implicit_null_derefs_begin(),
- E=Eng.implicit_null_derefs_end(); I!=E; ++I) {
+ NullDerefChecker *Checker = Eng.getChecker<NullDerefChecker>();
+ assert(Checker && "NullDerefChecker not exist.");
+ for (NullDerefChecker::iterator I = Checker->implicit_nodes_begin(),
+ E = Checker->implicit_nodes_end(); I != E; ++I) {
const GRState *state = (*I)->getState();
const SVal* X = state->get<GRState::NullDerefTag>();
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 780772a6f129..dbf8c42d273e 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -275,11 +275,11 @@ public:
const GRState *BindCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* CL, SVal V);
- const GRState *BindDecl(const GRState *ST, const VarDecl *VD,
- const LocationContext *LC, SVal InitVal);
+ const GRState *BindDecl(const GRState *ST, const VarRegion *VR,
+ SVal InitVal);
- const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl*,
- const LocationContext *) {
+ const GRState *BindDeclWithNoInit(const GRState *state,
+ const VarRegion *) {
return state;
}
@@ -1409,12 +1409,10 @@ const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) {
}
const GRState *RegionStoreManager::BindDecl(const GRState *ST,
- const VarDecl *VD,
- const LocationContext *LC,
+ const VarRegion *VR,
SVal InitVal) {
- QualType T = VD->getType();
- VarRegion* VR = MRMgr.getVarRegion(VD, LC);
+ QualType T = VR->getDecl()->getType();
if (T->isArrayType())
return BindArray(ST, VR, InitVal);
@@ -1630,6 +1628,8 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
// Process the "intermediate" roots to find if they are referenced by
// real roots.
llvm::SmallVector<RBDNode, 10> WorkList;
+ llvm::SmallVector<RBDNode, 10> Postponed;
+
llvm::DenseSet<const MemRegion*> IntermediateVisited;
while (!IntermediateRoots.empty()) {
@@ -1647,8 +1647,11 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
}
if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) {
- if (SymReaper.isLive(SR->getSymbol()))
- WorkList.push_back(std::make_pair(&state, SR));
+ llvm::SmallVectorImpl<RBDNode> &Q =
+ SymReaper.isLive(SR->getSymbol()) ? WorkList : Postponed;
+
+ Q.push_back(std::make_pair(&state, SR));
+
continue;
}
@@ -1667,6 +1670,7 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
llvm::DenseSet<RBDNode> Visited;
+tryAgain:
while (!WorkList.empty()) {
RBDNode N = WorkList.back();
WorkList.pop_back();
@@ -1740,6 +1744,21 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
}
}
+ // See if any postponed SymbolicRegions are actually live now, after
+ // having done a scan.
+ for (llvm::SmallVectorImpl<RBDNode>::iterator I = Postponed.begin(),
+ E = Postponed.end() ; I != E ; ++I) {
+ if (const SymbolicRegion *SR = cast_or_null<SymbolicRegion>(I->second)) {
+ if (SymReaper.isLive(SR->getSymbol())) {
+ WorkList.push_back(*I);
+ I->second = NULL;
+ }
+ }
+ }
+
+ if (!WorkList.empty())
+ goto tryAgain;
+
// We have now scanned the store, marking reachable regions and symbols
// as live. We now remove all the regions that are dead from the store
// as well as update DSymbols with the set symbols that are now dead.
diff --git a/lib/Analysis/UndefinedArgChecker.cpp b/lib/Analysis/UndefinedArgChecker.cpp
new file mode 100644
index 000000000000..a229f55ff6d9
--- /dev/null
+++ b/lib/Analysis/UndefinedArgChecker.cpp
@@ -0,0 +1,43 @@
+//===--- UndefinedArgChecker.h - Undefined arguments checker ----*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines BadCallChecker, a builtin check in GRExprEngine that performs
+// checks for undefined arguments.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *UndefinedArgChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+void UndefinedArgChecker::PreVisitCallExpr(CheckerContext &C,
+ const CallExpr *CE){
+ for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
+ I != E; ++I) {
+ if (C.getState()->getSVal(*I).isUndef()) {
+ if (ExplodedNode *N = C.GenerateNode(CE, true)) {
+ if (!BT)
+ BT = new BugType("Pass-by-value argument in function call is "
+ "undefined", "Logic error");
+ // Generate a report for this bug.
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName().c_str(),
+ N);
+ R->addRange((*I)->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I);
+ C.EmitReport(R);
+ }
+ }
+ }
+}
diff --git a/lib/Analysis/UndefinedAssignmentChecker.cpp b/lib/Analysis/UndefinedAssignmentChecker.cpp
new file mode 100644
index 000000000000..c5b2401f47ce
--- /dev/null
+++ b/lib/Analysis/UndefinedAssignmentChecker.cpp
@@ -0,0 +1,61 @@
+//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefinedAssginmentChecker, a builtin check in GRExprEngine that
+// checks for assigning undefined values.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *UndefinedAssignmentChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
+ const Stmt *S,
+ SVal location,
+ SVal val) {
+ if (!val.isUndef())
+ return;
+
+ ExplodedNode *N = C.GenerateNode(S, true);
+
+ if (!N)
+ return;
+
+ if (!BT)
+ BT = new BugType("Assigned value is garbage or undefined",
+ "Logic error");
+
+ // Generate a report for this bug.
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName().c_str(), N);
+ const Expr *ex = 0;
+
+ // FIXME: This check needs to be done on the expression doing the
+ // assignment, not the "store" expression.
+ if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
+ ex = B->getRHS();
+ else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
+ const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+ ex = VD->getInit();
+ }
+
+ if (ex) {
+ R->addRange(ex->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex);
+ }
+
+ C.EmitReport(R);
+}
+
diff --git a/lib/Analysis/VLASizeChecker.cpp b/lib/Analysis/VLASizeChecker.cpp
new file mode 100644
index 000000000000..76e4477449ed
--- /dev/null
+++ b/lib/Analysis/VLASizeChecker.cpp
@@ -0,0 +1,102 @@
+//=== VLASizeChecker.cpp - Undefined dereference checker --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines two VLASizeCheckers, a builtin check in GRExprEngine that
+// performs checks for declaration of VLA of undefined or zero size.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+
+using namespace clang;
+
+void *UndefSizedVLAChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+ExplodedNode *UndefSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
+ const GRState *state,
+ Stmt *S, GRExprEngine &Eng) {
+ GRStmtNodeBuilder &Builder = Eng.getBuilder();
+ BugReporter &BR = Eng.getBugReporter();
+
+ if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
+ // FIXME: Handle multi-dimensional VLAs.
+ Expr* SE = VLA->getSizeExpr();
+ SVal Size_untested = state->getSVal(SE);
+
+ if (Size_untested.isUndef()) {
+ if (ExplodedNode* N = Builder.generateNode(S, state, Pred)) {
+ N->markAsSink();
+ if (!BT)
+ BT = new BugType("Declare variable-length array (VLA) of undefined "
+ "size", "Logic error");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT, BT->getName().c_str(), N);
+ R->addRange(SE->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+ BR.EmitReport(R);
+ }
+ return 0;
+ }
+ }
+ return Pred;
+}
+
+void *ZeroSizedVLAChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+ExplodedNode *ZeroSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
+ const GRState *state, Stmt *S,
+ GRExprEngine &Eng) {
+ GRStmtNodeBuilder &Builder = Eng.getBuilder();
+ BugReporter &BR = Eng.getBugReporter();
+
+ if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
+ // FIXME: Handle multi-dimensional VLAs.
+ Expr* SE = VLA->getSizeExpr();
+ SVal Size_untested = state->getSVal(SE);
+
+ DefinedOrUnknownSVal *Size = dyn_cast<DefinedOrUnknownSVal>(&Size_untested);
+ // Undefined size is checked in another checker.
+ if (!Size)
+ return Pred;
+
+ const GRState *zeroState = state->Assume(*Size, false);
+ state = state->Assume(*Size, true);
+
+ if (zeroState && !state) {
+ if (ExplodedNode* N = Builder.generateNode(S, zeroState, Pred)) {
+ N->markAsSink();
+ if (!BT)
+ BT = new BugType("Declare variable-length array (VLA) of zero size",
+ "Logic error");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT, BT->getName().c_str(), N);
+ R->addRange(SE->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+ BR.EmitReport(R);
+ }
+ }
+ if (!state)
+ return 0;
+
+ return Builder.generateNode(S, state, Pred);
+ }
+ else
+ return Pred;
+}
+
diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index 527ebf965934..1a89acc65af3 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -18,7 +18,7 @@ add_clang_library(clangBasic
# FIXME: This only gets updated when CMake is run, so this revision number
# may be out-of-date!
find_package(Subversion)
-if (Subversion_FOUND)
+if (Subversion_FOUND AND EXISTS "${CLANG_SOURCE_DIR}/.svn")
Subversion_WC_INFO(${CLANG_SOURCE_DIR} CLANG)
set_source_files_properties(Version.cpp
PROPERTIES COMPILE_DEFINITIONS "SVN_REVISION=\"${CLANG_WC_REVISION}\"")
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 16aa0c54846a..401e6cba0692 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -381,3 +381,17 @@ SelectorTable::~SelectorTable() {
delete &getSelectorTableImpl(Impl);
}
+const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) {
+ switch (Operator) {
+ case OO_None:
+ case NUM_OVERLOADED_OPERATORS:
+ return 0;
+
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ case OO_##Name: return Spelling;
+#include "clang/Basic/OperatorKinds.def"
+ }
+
+ return 0;
+}
+
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 8f3c777c2004..12caf0c8e512 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -106,9 +106,9 @@ unsigned TargetInfo::getTypeWidth(IntType T) const {
};
}
-/// getTypeSigned - Return whether an integer types is signed. Returns true if
+/// isTypeSigned - Return whether an integer types is signed. Returns true if
/// the type is signed; false otherwise.
-bool TargetInfo::getTypeSigned(IntType T) const {
+bool TargetInfo::isTypeSigned(IntType T) const {
switch (T) {
default: assert(0 && "not an integer!");
case SignedShort:
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 66d6824b6f29..f418c5a81c12 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -1533,6 +1533,8 @@ namespace {
Define(Defines, "ram", "__attribute__((address_space(0)))");
Define(Defines, "_section(SectName)",
"__attribute__((section(SectName)))");
+ Define(Defines, "near",
+ "__attribute__((section(\"Address=NEAR\")))");
Define(Defines, "_address(Addr)",
"__attribute__((section(\"Address=\"#Addr)))");
Define(Defines, "_CONFIG(conf)", "asm(\"CONFIG \"#conf)");
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 987cd24e2c8b..c26921969a88 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -199,6 +199,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateCall(F, ArgValue, "tmp"));
}
case Builtin::BI__builtin_object_size: {
+ // FIXME: We're awaiting the llvm intrincis.
+#if 0
+ // We pass this builtin onto the optimizer so that it can
+ // figure out the object size in more complex cases.
+ const llvm::Type *ResType[] = {
+ ConvertType(E->getType())
+ };
+ Value *F = CGM.getIntrinsic(Intrinsic::objectsize, ResType, 1);
+ return RValue::get(Builder.CreateCall2(F,
+ EmitScalarExpr(E->getArg(0)),
+ EmitScalarExpr(E->getArg(1))));
+#else
// FIXME: Implement. For now we just always fail and pretend we
// don't know the object size.
llvm::APSInt TypeArg = E->getArg(1)->EvaluateAsInt(CGM.getContext());
@@ -207,6 +219,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
bool UseMinimum = TypeArg.getZExtValue() & 2;
return RValue::get(
llvm::ConstantInt::get(ResType, UseMinimum ? 0 : -1LL));
+#endif
}
case Builtin::BI__builtin_prefetch: {
Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0));
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index cfa669dc4b6e..3e854ca279b6 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -71,16 +71,17 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
const Expr *Init = D.getInit();
QualType T = D.getType();
+ bool isVolatile = getContext().getCanonicalType(T).isVolatileQualified();
if (T->isReferenceType()) {
ErrorUnsupported(Init, "global variable that binds to a reference");
} else if (!hasAggregateLLVMType(T)) {
llvm::Value *V = EmitScalarExpr(Init);
- EmitStoreOfScalar(V, DeclPtr, T.isVolatileQualified(), T);
+ EmitStoreOfScalar(V, DeclPtr, isVolatile, T);
} else if (T->isAnyComplexType()) {
- EmitComplexExprIntoAddr(Init, DeclPtr, T.isVolatileQualified());
+ EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
} else {
- EmitAggExpr(Init, DeclPtr, T.isVolatileQualified());
+ EmitAggExpr(Init, DeclPtr, isVolatile);
if (const RecordType *RT = T->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
@@ -95,8 +96,9 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
if (CXXGlobalInits.empty())
return;
- const llvm::FunctionType *FTy = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
- false);
+ const llvm::FunctionType *FTy
+ = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+ false);
// Create our global initialization function.
// FIXME: Should this be tweakable by targets?
@@ -139,18 +141,20 @@ CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
// Create the guard variable.
llvm::GlobalValue *GuardV =
- new llvm::GlobalVariable(CGM.getModule(), llvm::Type::getInt64Ty(VMContext), false,
- GV->getLinkage(),
- llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)),
+ new llvm::GlobalVariable(CGM.getModule(), llvm::Type::getInt64Ty(VMContext),
+ false, GV->getLinkage(),
+ llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)),
GuardVName.str());
// Load the first byte of the guard variable.
- const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
+ const llvm::Type *PtrTy
+ = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy),
"tmp");
// Compare it against 0.
- llvm::Value *nullValue = llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext));
+ llvm::Value *nullValue
+ = llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext));
llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool");
llvm::BasicBlock *InitBlock = createBasicBlock("init");
@@ -163,7 +167,8 @@ CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
EmitCXXGlobalVarDeclInit(D, GV);
- Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1),
+ Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext),
+ 1),
Builder.CreateBitCast(GuardV, PtrTy));
EmitBlock(EndBlock);
@@ -591,11 +596,16 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
const CXXConstructExpr *E) {
assert(Dest && "Must have a destination!");
const CXXConstructorDecl *CD = E->getConstructor();
+ const ConstantArrayType *Array =
+ getContext().getAsConstantArrayType(E->getType());
// For a copy constructor, even if it is trivial, must fall thru so
// its argument is code-gen'ed.
if (!CD->isCopyConstructor(getContext())) {
+ QualType InitType = E->getType();
+ if (Array)
+ InitType = getContext().getBaseElementType(Array);
const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(InitType->getAs<RecordType>()->getDecl());
if (RD->hasTrivialConstructor())
return;
}
@@ -606,9 +616,18 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
EmitAggExpr((*i), Dest, false);
return;
}
- // Call the constructor.
- EmitCXXConstructorCall(CD, Ctor_Complete, Dest,
- E->arg_begin(), E->arg_end());
+ if (Array) {
+ QualType BaseElementTy = getContext().getBaseElementType(Array);
+ const llvm::Type *BasePtr = ConvertType(BaseElementTy);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr =
+ Builder.CreateBitCast(Dest, BasePtr);
+ EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr);
+ }
+ else
+ // Call the constructor.
+ EmitCXXConstructorCall(CD, Ctor_Complete, Dest,
+ E->arg_begin(), E->arg_end());
}
void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) {
@@ -688,32 +707,39 @@ llvm::Constant *CodeGenFunction::GenerateThunk(llvm::Function *Fn,
const CXXMethodDecl *MD,
bool Extern, int64_t nv,
int64_t v) {
- QualType R = MD->getType()->getAs<FunctionType>()->getResultType();
+ return GenerateCovariantThunk(Fn, MD, Extern, nv, v, 0, 0);
+}
- FunctionArgList Args;
- ImplicitParamDecl *ThisDecl =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
- MD->getThisType(getContext()));
- Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType()));
- for (FunctionDecl::param_const_iterator i = MD->param_begin(),
- e = MD->param_end();
- i != e; ++i) {
- ParmVarDecl *D = *i;
- Args.push_back(std::make_pair(D, D->getType()));
+llvm::Value *CodeGenFunction::DynamicTypeAdjust(llvm::Value *V, int64_t nv,
+ int64_t v) {
+ llvm::Type *Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),
+ 0);
+ const llvm::Type *OrigTy = V->getType();
+ if (nv) {
+ // Do the non-virtual adjustment
+ V = Builder.CreateBitCast(V, Ptr8Ty);
+ V = Builder.CreateConstInBoundsGEP1_64(V, nv);
+ V = Builder.CreateBitCast(V, OrigTy);
}
- IdentifierInfo *II
- = &CGM.getContext().Idents.get("__thunk_named_foo_");
- FunctionDecl *FD = FunctionDecl::Create(getContext(),
- getContext().getTranslationUnitDecl(),
- SourceLocation(), II, R, 0,
- Extern
- ? FunctionDecl::Extern
- : FunctionDecl::Static,
- false, true);
- StartFunction(FD, R, Fn, Args, SourceLocation());
- // FIXME: generate body
- FinishFunction();
- return Fn;
+ if (v) {
+ // Do the virtual this adjustment
+ const llvm::Type *PtrDiffTy =
+ ConvertType(getContext().getPointerDiffType());
+ llvm::Type *PtrPtr8Ty, *PtrPtrDiffTy;
+ PtrPtr8Ty = llvm::PointerType::get(Ptr8Ty, 0);
+ PtrPtrDiffTy = llvm::PointerType::get(PtrDiffTy, 0);
+ llvm::Value *ThisVal = Builder.CreateBitCast(V, Ptr8Ty);
+ V = Builder.CreateBitCast(V, PtrPtrDiffTy->getPointerTo());
+ V = Builder.CreateLoad(V, "vtable");
+ llvm::Value *VTablePtr = V;
+ assert(v % (LLVMPointerWidth/8) == 0 && "vtable entry unaligned");
+ v /= LLVMPointerWidth/8;
+ V = Builder.CreateConstInBoundsGEP1_64(VTablePtr, v);
+ V = Builder.CreateLoad(V);
+ V = Builder.CreateGEP(ThisVal, V);
+ V = Builder.CreateBitCast(V, OrigTy);
+ }
+ return V;
}
llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
@@ -723,7 +749,7 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
int64_t v_t,
int64_t nv_r,
int64_t v_r) {
- QualType R = MD->getType()->getAs<FunctionType>()->getResultType();
+ QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType();
FunctionArgList Args;
ImplicitParamDecl *ThisDecl =
@@ -740,13 +766,57 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
= &CGM.getContext().Idents.get("__thunk_named_foo_");
FunctionDecl *FD = FunctionDecl::Create(getContext(),
getContext().getTranslationUnitDecl(),
- SourceLocation(), II, R, 0,
+ SourceLocation(), II, ResultType, 0,
Extern
? FunctionDecl::Extern
: FunctionDecl::Static,
false, true);
- StartFunction(FD, R, Fn, Args, SourceLocation());
- // FIXME: generate body
+ StartFunction(FD, ResultType, Fn, Args, SourceLocation());
+
+ // generate body
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+ const llvm::Type *Ty =
+ CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
+ FPT->isVariadic());
+ llvm::Value *Callee = CGM.GetAddrOfFunction(MD, Ty);
+ CallArgList CallArgs;
+
+ QualType ArgType = MD->getThisType(getContext());
+ llvm::Value *Arg = Builder.CreateLoad(LocalDeclMap[ThisDecl], "this");
+ if (nv_t || v_t) {
+ // Do the this adjustment.
+ const llvm::Type *OrigTy = Callee->getType();
+ Arg = DynamicTypeAdjust(Arg, nv_t, v_t);
+ if (nv_r || v_r) {
+ Callee = CGM.BuildCovariantThunk(MD, Extern, 0, 0, nv_r, v_r);
+ Callee = Builder.CreateBitCast(Callee, OrigTy);
+ nv_r = v_r = 0;
+ }
+ }
+
+ CallArgs.push_back(std::make_pair(RValue::get(Arg), ArgType));
+
+ for (FunctionDecl::param_const_iterator i = MD->param_begin(),
+ e = MD->param_end();
+ i != e; ++i) {
+ ParmVarDecl *D = *i;
+ QualType ArgType = D->getType();
+
+ // llvm::Value *Arg = CGF.GetAddrOfLocalVar(Dst);
+ Expr *Arg = new (getContext()) DeclRefExpr(D, ArgType, SourceLocation());
+ CallArgs.push_back(std::make_pair(EmitCallArg(Arg, ArgType), ArgType));
+ }
+
+ RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
+ Callee, CallArgs, MD);
+ if (nv_r || v_r) {
+ // Do the return result adjustment.
+ RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r));
+ }
+
+ if (!ResultType->isVoidType())
+ EmitReturnOfRValue(RV, ResultType);
+
FinishFunction();
return Fn;
}
@@ -769,7 +839,6 @@ llvm::Constant *CodeGenModule::BuildThunk(const CXXMethodDecl *MD, bool Extern,
llvm::Function *Fn = llvm::Function::Create(FTy, linktype, Out.str(),
&getModule());
CodeGenFunction(*this).GenerateThunk(Fn, MD, Extern, nv, v);
- // Fn = Builder.CreateBitCast(Fn, Ptr8Ty);
llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
return m;
}
@@ -795,7 +864,6 @@ llvm::Constant *CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD,
&getModule());
CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, nv_t, v_t, nv_r,
v_r);
- // Fn = Builder.CreateBitCast(Fn, Ptr8Ty);
llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
return m;
}
@@ -815,7 +883,7 @@ CodeGenFunction::GetVirtualCXXBaseClassOffset(llvm::Value *This,
CGM.getVtableInfo().getVirtualBaseOffsetIndex(ClassDecl, BaseClassDecl);
llvm::Value *VBaseOffsetPtr =
- Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetIndex, "vbase.offset.ptr");
+ Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetIndex, "vbase.offset.ptr");
const llvm::Type *PtrDiffTy =
ConvertType(getContext().getPointerDiffType());
@@ -899,7 +967,7 @@ void CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest,
// Push the Src ptr.
CallArgs.push_back(std::make_pair(RValue::get(Src),
- BaseCopyCtor->getParamDecl(0)->getType()));
+ BaseCopyCtor->getParamDecl(0)->getType()));
QualType ResultType =
BaseCopyCtor->getType()->getAs<FunctionType>()->getResultType();
EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
@@ -1099,11 +1167,11 @@ CodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor,
FinishFunction();
}
-/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a copy
-/// constructor, in accordance with section 12.8 (p7 and p8) of C++03
+/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a
+/// copy constructor, in accordance with section 12.8 (p7 and p8) of C++03
/// The implicitly-defined copy constructor for class X performs a memberwise
-/// copy of its subobjects. The order of copying is the same as the order
-/// of initialization of bases and members in a user-defined constructor
+/// copy of its subobjects. The order of copying is the same as the order of
+/// initialization of bases and members in a user-defined constructor
/// Each subobject is copied in the manner appropriate to its type:
/// if the subobject is of class type, the copy constructor for the class is
/// used;
@@ -1121,7 +1189,7 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,
const FunctionArgList &Args) {
const CXXRecordDecl *ClassDecl = Ctor->getParent();
assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
- "SynthesizeCXXCopyConstructor - copy constructor has definition already");
+ "SynthesizeCXXCopyConstructor - copy constructor has definition already");
StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args,
SourceLocation());
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 78655168e857..06cd05cc75a8 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -441,6 +441,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
RetAttrs |= llvm::Attribute::NoAlias;
}
+ if (CompileOpts.OptimizeSize)
+ FuncAttrs |= llvm::Attribute::OptimizeForSize;
if (CompileOpts.DisableRedZone)
FuncAttrs |= llvm::Attribute::NoRedZone;
if (CompileOpts.NoImplicitFloat)
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 1728c67292b7..b1ceb4627712 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/CompileOptions.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Intrinsics.h"
#include "llvm/Target/TargetData.h"
@@ -316,6 +317,20 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
llvm::Value *DeclPtr;
if (Ty->isConstantSizeType()) {
if (!Target.useGlobalsForAutomaticVariables()) {
+
+ // All constant structs and arrays should be global if
+ // their initializer is constant and if the element type is POD.
+ if (CGM.getCompileOpts().MergeAllConstants) {
+ if (Ty.isConstant(getContext())
+ && (Ty->isArrayType() || Ty->isRecordType())
+ && (D.getInit()
+ && D.getInit()->isConstantInitializer(getContext()))
+ && Ty->isPODType()) {
+ EmitStaticBlockVarDecl(D);
+ return;
+ }
+ }
+
// A normal fixed sized variable becomes an alloca in the entry block.
const llvm::Type *LTy = ConvertTypeForMem(Ty);
Align = getContext().getDeclAlignInBytes(&D);
@@ -417,17 +432,18 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
D.getNameAsString());
+ bool isVolatile = (getContext().getCanonicalType(D.getType())
+ .isVolatileQualified());
if (Ty->isReferenceType()) {
RValue RV = EmitReferenceBindingToExpr(Init, Ty, /*IsInitializer=*/true);
EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Ty);
} else if (!hasAggregateLLVMType(Init->getType())) {
llvm::Value *V = EmitScalarExpr(Init);
- EmitStoreOfScalar(V, Loc, D.getType().isVolatileQualified(),
- D.getType());
+ EmitStoreOfScalar(V, Loc, isVolatile, D.getType());
} else if (Init->getType()->isAnyComplexType()) {
- EmitComplexExprIntoAddr(Init, Loc, D.getType().isVolatileQualified());
+ EmitComplexExprIntoAddr(Init, Loc, isVolatile);
} else {
- EmitAggExpr(Init, Loc, D.getType().isVolatileQualified());
+ EmitAggExpr(Init, Loc, isVolatile);
}
}
@@ -492,16 +508,25 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
// Handle CXX destruction of variables.
QualType DtorTy(Ty);
if (const ArrayType *Array = DtorTy->getAs<ArrayType>())
- DtorTy = Array->getElementType();
+ DtorTy = getContext().getBaseElementType(Array);
if (const RecordType *RT = DtorTy->getAs<RecordType>())
if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
if (!ClassDecl->hasTrivialDestructor()) {
const CXXDestructorDecl *D = ClassDecl->getDestructor(getContext());
assert(D && "EmitLocalBlockVarDecl - destructor is nul");
- assert(!Ty->getAs<ArrayType>() && "FIXME - destruction of arrays NYI");
-
+
CleanupScope scope(*this);
- EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
+ if (const ConstantArrayType *Array =
+ getContext().getAsConstantArrayType(Ty)) {
+ QualType BaseElementTy = getContext().getBaseElementType(Array);
+ const llvm::Type *BasePtr = ConvertType(BaseElementTy);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr =
+ Builder.CreateBitCast(DeclPtr, BasePtr);
+ EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
+ }
+ else
+ EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
}
}
@@ -547,6 +572,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
"Invalid argument to EmitParmDecl");
QualType Ty = D.getType();
+ CanQualType CTy = getContext().getCanonicalType(Ty);
llvm::Value *DeclPtr;
if (!Ty->isConstantSizeType()) {
@@ -563,7 +589,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
DeclPtr->setName(Name.c_str());
// Store the initial value into the alloca.
- EmitStoreOfScalar(Arg, DeclPtr, Ty.isVolatileQualified(), Ty);
+ EmitStoreOfScalar(Arg, DeclPtr, CTy.isVolatileQualified(), Ty);
} else {
// Otherwise, if this is an aggregate, just use the input pointer.
DeclPtr = Arg;
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
new file mode 100644
index 000000000000..adfd0055f936
--- /dev/null
+++ b/lib/CodeGen/CGException.cpp
@@ -0,0 +1,105 @@
+//===--- CGException.cpp - Emit LLVM Code for C++ exceptions --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ exception related code generation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenFunction.h"
+using namespace clang;
+using namespace CodeGen;
+
+static llvm::Constant *getAllocateExceptionFn(CodeGenFunction &CGF) {
+ // void *__cxa_allocate_exception(size_t thrown_size);
+ const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
+ std::vector<const llvm::Type*> Args(1, SizeTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getInt8PtrTy(CGF.getLLVMContext()),
+ Args, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception");
+}
+
+static llvm::Constant *getThrowFn(CodeGenFunction &CGF) {
+ // void __cxa_throw (void *thrown_exception, std::type_info *tinfo,
+ // void (*dest) (void *) );
+
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ std::vector<const llvm::Type*> Args(3, Int8PtrTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
+ Args, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_throw");
+}
+
+void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) {
+ // FIXME: Handle rethrows.
+ if (!E->getSubExpr()) {
+ ErrorUnsupported(E, "rethrow expression");
+ return;
+ }
+
+ QualType ThrowType = E->getSubExpr()->getType();
+ // FIXME: We only handle non-class types for now.
+ if (ThrowType->isRecordType()) {
+ ErrorUnsupported(E, "throw expression");
+ return;
+ }
+
+ // FIXME: Handle cleanup.
+ if (!CleanupEntries.empty()){
+ ErrorUnsupported(E, "throw expression");
+ return;
+ }
+
+ // Now allocate the exception object.
+ const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
+ uint64_t TypeSize = getContext().getTypeSize(ThrowType) / 8;
+
+ llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(*this);
+ llvm::Value *ExceptionPtr =
+ Builder.CreateCall(AllocExceptionFn,
+ llvm::ConstantInt::get(SizeTy, TypeSize),
+ "exception");
+
+ // Store the throw exception in the exception object.
+ if (!hasAggregateLLVMType(ThrowType)) {
+ llvm::Value *Value = EmitScalarExpr(E->getSubExpr());
+ const llvm::Type *ValuePtrTy = Value->getType()->getPointerTo(0);
+
+ Builder.CreateStore(Value, Builder.CreateBitCast(ExceptionPtr, ValuePtrTy));
+ } else {
+ // FIXME: Handle complex and aggregate expressions.
+ ErrorUnsupported(E, "throw expression");
+ }
+
+ // Now throw the exception.
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
+
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ mangleCXXRtti(CGM.getMangleContext(), ThrowType, Out);
+
+ // FIXME: Is it OK to use CreateRuntimeVariable for this?
+ llvm::Constant *TypeInfo =
+ CGM.CreateRuntimeVariable(llvm::Type::getInt8Ty(getLLVMContext()),
+ OutName.c_str());
+ llvm::Constant *Dtor = llvm::Constant::getNullValue(Int8PtrTy);
+
+ llvm::CallInst *ThrowCall =
+ Builder.CreateCall3(getThrowFn(*this), ExceptionPtr, TypeInfo, Dtor);
+ ThrowCall->setDoesNotReturn();
+ Builder.CreateUnreachable();
+
+ // Clear the insertion point to indicate we are in unreachable code.
+ Builder.ClearInsertionPoint();
+}
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index bb487f6e3fdf..d9dd70ac9e49 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -84,10 +84,9 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) {
ShouldDestroyTemporaries = TE->shouldDestroyTemporaries();
- if (ShouldDestroyTemporaries) {
- // Keep track of the current cleanup stack depth.
+ // Keep track of the current cleanup stack depth.
+ if (ShouldDestroyTemporaries)
OldNumLiveTemporaries = LiveTemporaries.size();
- }
E = TE->getSubExpr();
}
@@ -148,7 +147,6 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
// Check if need to perform the derived-to-base cast.
if (BaseClassDecl) {
llvm::Value *Derived = Val.getAggregateAddr();
-
llvm::Value *Base =
GetAddressCXXOfBaseClass(Derived, DerivedClassDecl, BaseClassDecl,
/*NullCheckValue=*/false);
@@ -189,18 +187,21 @@ unsigned CodeGenFunction::getAccessedFieldNo(unsigned Idx,
//===----------------------------------------------------------------------===//
RValue CodeGenFunction::GetUndefRValue(QualType Ty) {
- if (Ty->isVoidType()) {
+ if (Ty->isVoidType())
return RValue::get(0);
- } else if (const ComplexType *CTy = Ty->getAs<ComplexType>()) {
+
+ if (const ComplexType *CTy = Ty->getAs<ComplexType>()) {
const llvm::Type *EltTy = ConvertType(CTy->getElementType());
llvm::Value *U = llvm::UndefValue::get(EltTy);
return RValue::getComplex(std::make_pair(U, U));
- } else if (hasAggregateLLVMType(Ty)) {
+ }
+
+ if (hasAggregateLLVMType(Ty)) {
const llvm::Type *LTy = llvm::PointerType::getUnqual(ConvertType(Ty));
return RValue::getAggregate(llvm::UndefValue::get(LTy));
- } else {
- return RValue::get(llvm::UndefValue::get(ConvertType(Ty)));
}
+
+ return RValue::get(llvm::UndefValue::get(ConvertType(Ty)));
}
RValue CodeGenFunction::EmitUnsupportedRValue(const Expr *E,
@@ -245,7 +246,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
case Expr::VAArgExprClass:
return EmitVAArgExprLValue(cast<VAArgExpr>(E));
case Expr::DeclRefExprClass:
- case Expr::QualifiedDeclRefExprClass:
return EmitDeclRefLValue(cast<DeclRefExpr>(E));
case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr());
case Expr::PredefinedExprClass:
@@ -343,9 +343,8 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) {
if (LV.isObjCWeak()) {
// load of a __weak object.
llvm::Value *AddrWeakObj = LV.getAddress();
- llvm::Value *read_weak = CGM.getObjCRuntime().EmitObjCWeakRead(*this,
- AddrWeakObj);
- return RValue::get(read_weak);
+ return RValue::get(CGM.getObjCRuntime().EmitObjCWeakRead(*this,
+ AddrWeakObj));
}
if (LV.isSimple()) {
@@ -522,10 +521,8 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
if (Dst.isPropertyRef())
return EmitStoreThroughPropertyRefLValue(Src, Dst, Ty);
- if (Dst.isKVCRef())
- return EmitStoreThroughKVCRefLValue(Src, Dst, Ty);
-
- assert(0 && "Unknown LValue type");
+ assert(Dst.isKVCRef() && "Unknown LValue type");
+ return EmitStoreThroughKVCRefLValue(Src, Dst, Ty);
}
if (Dst.isObjCWeak() && !Dst.isNonGC()) {
@@ -551,8 +548,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset");
CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst,
BytesBetween);
- }
- else if (Dst.isGlobalObjCRef())
+ } else if (Dst.isGlobalObjCRef())
CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst);
else
CGM.getObjCRuntime().EmitObjCStrongCastAssign(*this, src, LvalueDst);
@@ -702,13 +698,12 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
// FIXME: since we're shuffling with undef, can we just use the indices
// into that? This could be simpler.
llvm::SmallVector<llvm::Constant*, 4> ExtMask;
+ const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
unsigned i;
for (i = 0; i != NumSrcElts; ++i)
- ExtMask.push_back(llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(VMContext), i));
+ ExtMask.push_back(llvm::ConstantInt::get(Int32Ty, i));
for (; i != NumDstElts; ++i)
- ExtMask.push_back(llvm::UndefValue::get(
- llvm::Type::getInt32Ty(VMContext)));
+ ExtMask.push_back(llvm::UndefValue::get(Int32Ty));
llvm::Value *ExtMaskV = llvm::ConstantVector::get(&ExtMask[0],
ExtMask.size());
llvm::Value *ExtSrcVal =
@@ -717,15 +712,13 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
ExtMaskV, "tmp");
// build identity
llvm::SmallVector<llvm::Constant*, 4> Mask;
- for (unsigned i = 0; i != NumDstElts; ++i) {
- Mask.push_back(llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(VMContext), i));
- }
+ for (unsigned i = 0; i != NumDstElts; ++i)
+ Mask.push_back(llvm::ConstantInt::get(Int32Ty, i));
+
// modify when what gets shuffled in
for (unsigned i = 0; i != NumSrcElts; ++i) {
unsigned Idx = getAccessedFieldNo(i, Elts);
- Mask[Idx] = llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(VMContext), i+NumDstElts);
+ Mask[Idx] = llvm::ConstantInt::get(Int32Ty, i+NumDstElts);
}
llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
Vec = Builder.CreateShuffleVector(Vec, ExtSrcVal, MaskV, "tmp");
@@ -736,8 +729,8 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
} else {
// If the Src is a scalar (not a vector) it must be updating one element.
unsigned InIdx = getAccessedFieldNo(0, Elts);
- llvm::Value *Elt = llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(VMContext), InIdx);
+ const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
+ llvm::Value *Elt = llvm::ConstantInt::get(Int32Ty, InIdx);
Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt, "tmp");
}
@@ -747,8 +740,8 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
// setObjCGCLValueClass - sets class of he lvalue for the purpose of
// generating write-barries API. It is currently a global, ivar,
// or neither.
-static
-void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) {
+static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
+ LValue &LV) {
if (Ctx.getLangOptions().getGCMode() == LangOptions::NonGC)
return;
@@ -759,6 +752,7 @@ void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) {
LV.SetObjCArray(LV, E->getType()->isArrayType());
return;
}
+
if (const DeclRefExpr *Exp = dyn_cast<DeclRefExpr>(E)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
if ((VD->isBlockVarDecl() && !VD->hasLocalStorage()) ||
@@ -766,10 +760,15 @@ void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) {
LV.SetGlobalObjCRef(LV, true);
}
LV.SetObjCArray(LV, E->getType()->isArrayType());
+ return;
}
- else if (const UnaryOperator *Exp = dyn_cast<UnaryOperator>(E))
+
+ if (const UnaryOperator *Exp = dyn_cast<UnaryOperator>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
- else if (const ParenExpr *Exp = dyn_cast<ParenExpr>(E)) {
+ return;
+ }
+
+ if (const ParenExpr *Exp = dyn_cast<ParenExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
if (LV.isObjCIvar()) {
// If cast is to a structure pointer, follow gcc's behavior and make it
@@ -779,13 +778,20 @@ void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) {
ExpTy = ExpTy->getAs<PointerType>()->getPointeeType();
if (ExpTy->isRecordType())
LV.SetObjCIvar(LV, false);
- }
+ }
+ return;
}
- else if (const ImplicitCastExpr *Exp = dyn_cast<ImplicitCastExpr>(E))
+ if (const ImplicitCastExpr *Exp = dyn_cast<ImplicitCastExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
- else if (const CStyleCastExpr *Exp = dyn_cast<CStyleCastExpr>(E))
+ return;
+ }
+
+ if (const CStyleCastExpr *Exp = dyn_cast<CStyleCastExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
- else if (const ArraySubscriptExpr *Exp = dyn_cast<ArraySubscriptExpr>(E)) {
+ return;
+ }
+
+ if (const ArraySubscriptExpr *Exp = dyn_cast<ArraySubscriptExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
if (LV.isObjCIvar() && !LV.isObjCArray())
// Using array syntax to assigning to what an ivar points to is not
@@ -795,12 +801,15 @@ void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) {
// Using array syntax to assigning to what global points to is not
// same as assigning to the global itself. {id *G;} G[i] = 0;
LV.SetGlobalObjCRef(LV, false);
+ return;
}
- else if (const MemberExpr *Exp = dyn_cast<MemberExpr>(E)) {
+
+ if (const MemberExpr *Exp = dyn_cast<MemberExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
// We don't know if member is an 'ivar', but this flag is looked at
// only in the context of LV.isObjCIvar().
LV.SetObjCArray(LV, E->getType()->isArrayType());
+ return;
}
}
@@ -839,14 +848,18 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
LValue::SetObjCNonGC(LV, NonGCable);
setObjCGCLValueClass(getContext(), E, LV);
return LV;
- } else if (VD && VD->isFileVarDecl()) {
+ }
+
+ if (VD && VD->isFileVarDecl()) {
llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
if (VD->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
setObjCGCLValueClass(getContext(), E, LV);
return LV;
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) {
+ }
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) {
llvm::Value* V = CGM.GetAddrOfFunction(FD);
if (!FD->hasPrototype()) {
if (const FunctionProtoType *Proto =
@@ -861,15 +874,19 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
}
return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
- } else if (const ImplicitParamDecl *IPD =
- dyn_cast<ImplicitParamDecl>(E->getDecl())) {
+ }
+
+ if (const ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(E->getDecl())){
llvm::Value *V = LocalDeclMap[IPD];
assert(V && "BlockVarDecl not entered in LocalDeclMap?");
return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
- } else if (const QualifiedDeclRefExpr *QDRExpr =
- dyn_cast<QualifiedDeclRefExpr>(E)) {
- return EmitPointerToDataMemberLValue(QDRExpr);
}
+
+ if (E->getQualifier()) {
+ // FIXME: the qualifier check does not seem sufficient here
+ return EmitPointerToDataMemberLValue(E);
+ }
+
assert(0 && "Unimp declref");
//an invalid LValue, but the assert will
//ensure that this point is never reached.
@@ -888,25 +905,24 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
QualType ExprTy = getContext().getCanonicalType(E->getSubExpr()->getType());
switch (E->getOpcode()) {
default: assert(0 && "Unknown unary operator lvalue!");
- case UnaryOperator::Deref:
- {
- QualType T = E->getSubExpr()->getType()->getPointeeType();
- assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
-
- Qualifiers Quals = MakeQualifiers(T);
- Quals.setAddressSpace(ExprTy.getAddressSpace());
-
- LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()), Quals);
- // We should not generate __weak write barrier on indirect reference
- // of a pointer to object; as in void foo (__weak id *param); *param = 0;
- // But, we continue to generate __strong write barrier on indirect write
- // into a pointer to object.
- if (getContext().getLangOptions().ObjC1 &&
- getContext().getLangOptions().getGCMode() != LangOptions::NonGC &&
- LV.isObjCWeak())
- LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext()));
- return LV;
- }
+ case UnaryOperator::Deref: {
+ QualType T = E->getSubExpr()->getType()->getPointeeType();
+ assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
+
+ Qualifiers Quals = MakeQualifiers(T);
+ Quals.setAddressSpace(ExprTy.getAddressSpace());
+
+ LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()), Quals);
+ // We should not generate __weak write barrier on indirect reference
+ // of a pointer to object; as in void foo (__weak id *param); *param = 0;
+ // But, we continue to generate __strong write barrier on indirect write
+ // into a pointer to object.
+ if (getContext().getLangOptions().ObjC1 &&
+ getContext().getLangOptions().getGCMode() != LangOptions::NonGC &&
+ LV.isObjCWeak())
+ LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext()));
+ return LV;
+ }
case UnaryOperator::Real:
case UnaryOperator::Imag:
LValue LV = EmitLValue(E->getSubExpr());
@@ -932,8 +948,7 @@ LValue CodeGenFunction::EmitPredefinedFunctionName(unsigned Type) {
std::string GlobalVarName;
switch (Type) {
- default:
- assert(0 && "Invalid type");
+ default: assert(0 && "Invalid type");
case PredefinedExpr::Func:
GlobalVarName = "__func__.";
break;
@@ -1089,12 +1104,12 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
llvm::Constant *BaseElts = Base.getExtVectorElts();
llvm::SmallVector<llvm::Constant *, 4> CElts;
+ const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
for (unsigned i = 0, e = Indices.size(); i != e; ++i) {
if (isa<llvm::ConstantAggregateZero>(BaseElts))
- CElts.push_back(llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(VMContext), 0));
+ CElts.push_back(llvm::ConstantInt::get(Int32Ty, 0));
else
- CElts.push_back(BaseElts->getOperand(Indices[i]));
+ CElts.push_back(cast<llvm::Constant>(BaseElts->getOperand(Indices[i])));
}
llvm::Constant *CV = llvm::ConstantVector::get(&CElts[0], CElts.size());
return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), CV,
@@ -1211,13 +1226,12 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){
const Expr* InitExpr = E->getInitializer();
LValue Result = LValue::MakeAddr(DeclPtr, MakeQualifiers(E->getType()));
- if (E->getType()->isComplexType()) {
+ if (E->getType()->isComplexType())
EmitComplexExprIntoAddr(InitExpr, DeclPtr, false);
- } else if (hasAggregateLLVMType(E->getType())) {
+ else if (hasAggregateLLVMType(E->getType()))
EmitAnyExpr(InitExpr, DeclPtr, false);
- } else {
+ else
EmitStoreThroughLValue(EmitAnyExpr(InitExpr), Result, E->getType());
- }
return Result;
}
@@ -1238,9 +1252,7 @@ CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) {
if (!LHS.isSimple())
return EmitUnsupportedLValue(E, "conditional operator");
- llvm::Value *Temp = CreateTempAlloca(LHS.getAddress()->getType(),
- "condtmp");
-
+ llvm::Value *Temp = CreateTempAlloca(LHS.getAddress()->getType(),"condtmp");
Builder.CreateStore(LHS.getAddress(), Temp);
EmitBranch(ContBlock);
@@ -1379,7 +1391,8 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
return EmitLValue(E->getRHS());
}
- if (E->getOpcode() == BinaryOperator::PtrMemD)
+ if (E->getOpcode() == BinaryOperator::PtrMemD ||
+ E->getOpcode() == BinaryOperator::PtrMemI)
return EmitPointerToDataMemberBinaryExpr(E);
// Can only get l-value for binary operator expressions which are a
@@ -1406,15 +1419,14 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
RValue RV = EmitCallExpr(E);
- if (RV.isScalar()) {
- assert(E->getCallReturnType()->isReferenceType() &&
- "Can't have a scalar return unless the return type is a "
- "reference type!");
-
- return LValue::MakeAddr(RV.getScalarVal(), MakeQualifiers(E->getType()));
- }
+ if (!RV.isScalar())
+ return LValue::MakeAddr(RV.getAggregateAddr(),MakeQualifiers(E->getType()));
+
+ assert(E->getCallReturnType()->isReferenceType() &&
+ "Can't have a scalar return unless the return type is a "
+ "reference type!");
- return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType()));
+ return LValue::MakeAddr(RV.getScalarVal(), MakeQualifiers(E->getType()));
}
LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) {
@@ -1439,9 +1451,7 @@ LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) {
LValue
CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) {
LValue LV = EmitLValue(E->getSubExpr());
-
PushCXXTemporary(E->getTemporary(), LV.getAddress());
-
return LV;
}
@@ -1497,21 +1507,18 @@ CodeGenFunction::EmitObjCPropertyRefLValue(const ObjCPropertyRefExpr *E) {
return LValue::MakePropertyRef(E, E->getType().getCVRQualifiers());
}
-LValue
-CodeGenFunction::EmitObjCKVCRefLValue(
+LValue CodeGenFunction::EmitObjCKVCRefLValue(
const ObjCImplicitSetterGetterRefExpr *E) {
// This is a special l-value that just issues sends when we load or store
// through it.
return LValue::MakeKVCRef(E, E->getType().getCVRQualifiers());
}
-LValue
-CodeGenFunction::EmitObjCSuperExprLValue(const ObjCSuperExpr *E) {
+LValue CodeGenFunction::EmitObjCSuperExprLValue(const ObjCSuperExpr *E) {
return EmitUnsupportedLValue(E, "use of super");
}
LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
-
// Can only get l-value for message expression returning aggregate type
RValue RV = EmitAnyExprToTemp(E);
// FIXME: can this be volatile?
@@ -1519,8 +1526,7 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
}
-LValue CodeGenFunction::EmitPointerToDataMemberLValue(
- const QualifiedDeclRefExpr *E) {
+LValue CodeGenFunction::EmitPointerToDataMemberLValue(const DeclRefExpr *E) {
const FieldDecl *Field = cast<FieldDecl>(E->getDecl());
const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Field->getDeclContext());
QualType NNSpecTy =
@@ -1530,12 +1536,9 @@ LValue CodeGenFunction::EmitPointerToDataMemberLValue(
llvm::Value *V = llvm::Constant::getNullValue(ConvertType(NNSpecTy));
LValue MemExpLV = EmitLValueForField(V, const_cast<FieldDecl*>(Field),
/*isUnion*/false, /*Qualifiers*/0);
- const llvm::Type* ResultType = ConvertType(
- getContext().getPointerDiffType());
- V = Builder.CreatePtrToInt(MemExpLV.getAddress(), ResultType,
- "datamember");
- LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
- return LV;
+ const llvm::Type *ResultType = ConvertType(getContext().getPointerDiffType());
+ V = Builder.CreatePtrToInt(MemExpLV.getAddress(), ResultType, "datamember");
+ return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
}
RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
@@ -1566,9 +1569,11 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
Callee, Args, TargetDecl);
}
-LValue CodeGenFunction::EmitPointerToDataMemberBinaryExpr(
- const BinaryOperator *E) {
+LValue CodeGenFunction::
+EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
llvm::Value *BaseV = EmitLValue(E->getLHS()).getAddress();
+ if (E->getOpcode() == BinaryOperator::PtrMemI)
+ BaseV = Builder.CreateLoad(BaseV, "indir.ptr");
const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(getLLVMContext());
BaseV = Builder.CreateBitCast(BaseV, i8Ty);
LValue RHSLV = EmitLValue(E->getRHS());
@@ -1577,13 +1582,12 @@ LValue CodeGenFunction::EmitPointerToDataMemberBinaryExpr(
const llvm::Type* ResultType = ConvertType(getContext().getPointerDiffType());
OffsetV = Builder.CreateBitCast(OffsetV, ResultType);
llvm::Value *AddV = Builder.CreateInBoundsGEP(BaseV, OffsetV, "add.ptr");
+
QualType Ty = E->getRHS()->getType();
- const MemberPointerType *MemPtrType = Ty->getAs<MemberPointerType>();
- Ty = MemPtrType->getPointeeType();
- const llvm::Type* PType =
- ConvertType(getContext().getPointerType(Ty));
+ Ty = Ty->getAs<MemberPointerType>()->getPointeeType();
+
+ const llvm::Type *PType = ConvertType(getContext().getPointerType(Ty));
AddV = Builder.CreateBitCast(AddV, PType);
- LValue LV = LValue::MakeAddr(AddV, MakeQualifiers(Ty));
- return LV;
+ return LValue::MakeAddr(AddV, MakeQualifiers(Ty));
}
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index f47b6ab3c8cc..901f867a5913 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -297,7 +297,7 @@ void AggExprEmitter::VisitUnaryAddrOf(const UnaryOperator *E) {
assert(MPT->getPointeeType()->isFunctionProtoType() &&
"Unexpected member pointer type!");
- const QualifiedDeclRefExpr *DRE = cast<QualifiedDeclRefExpr>(E->getSubExpr());
+ const DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr());
const CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl());
const llvm::Type *PtrDiffTy =
@@ -329,7 +329,8 @@ void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) {
}
void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) {
- if (E->getOpcode() == BinaryOperator::PtrMemD)
+ if (E->getOpcode() == BinaryOperator::PtrMemD ||
+ E->getOpcode() == BinaryOperator::PtrMemI)
VisitPointerToDataMemberBinaryOperator(E);
else
CGF.ErrorUnsupported(E, "aggregate binary expression");
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index fc3748c8e3c8..9145d92128a1 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -228,7 +228,7 @@ class VISIBILITY_HIDDEN ConstStructBuilder {
if (NumBytes > 1)
Ty = llvm::ArrayType::get(Ty, NumBytes);
- llvm::Constant *C = llvm::Constant::getNullValue(Ty);
+ llvm::Constant *C = llvm::UndefValue::get(Ty);
Elements.push_back(C);
assert(getAlignment(C) == 1 && "Padding must have 1 byte alignment!");
@@ -266,7 +266,7 @@ class VISIBILITY_HIDDEN ConstStructBuilder {
if (NumBytes > 1)
Ty = llvm::ArrayType::get(Ty, NumBytes);
- llvm::Constant *Padding = llvm::Constant::getNullValue(Ty);
+ llvm::Constant *Padding = llvm::UndefValue::get(Ty);
PackedElements.push_back(Padding);
ElementOffsetInBytes += getSizeInBytes(Padding);
}
@@ -434,7 +434,7 @@ public:
E->getType()->getAs<MemberPointerType>()) {
QualType T = MPT->getPointeeType();
if (T->isFunctionProtoType()) {
- QualifiedDeclRefExpr *DRE = cast<QualifiedDeclRefExpr>(E->getSubExpr());
+ DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr());
return EmitMemberFunctionPointer(cast<CXXMethodDecl>(DRE->getDecl()));
}
@@ -496,7 +496,7 @@ public:
if (NumPadBytes > 1)
Ty = llvm::ArrayType::get(Ty, NumPadBytes);
- Elts.push_back(llvm::Constant::getNullValue(Ty));
+ Elts.push_back(llvm::UndefValue::get(Ty));
Types.push_back(Ty);
}
@@ -739,8 +739,7 @@ public:
E->getType().getAddressSpace());
return C;
}
- case Expr::DeclRefExprClass:
- case Expr::QualifiedDeclRefExprClass: {
+ case Expr::DeclRefExprClass: {
NamedDecl *Decl = cast<DeclRefExpr>(E)->getDecl();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
return CGM.GetAddrOfFunction(FD);
@@ -777,11 +776,17 @@ public:
}
case Expr::AddrLabelExprClass: {
assert(CGF && "Invalid address of label expression outside function.");
+#ifndef USEINDIRECTBRANCH
unsigned id =
CGF->GetIDForAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
llvm::Constant *C =
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), id);
return llvm::ConstantExpr::getIntToPtr(C, ConvertType(E->getType()));
+#else
+ llvm::Constant *Ptr =
+ CGF->GetAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
+ return llvm::ConstantExpr::getBitCast(Ptr, ConvertType(E->getType()));
+#endif
}
case Expr::CallExprClass: {
CallExpr* CE = cast<CallExpr>(E);
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 69604f9aaaee..96b58d8995ae 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -135,11 +135,16 @@ public:
}
Value *VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E);
Value *VisitAddrLabelExpr(const AddrLabelExpr *E) {
+#ifndef USEINDIRECTBRANCH
llvm::Value *V =
llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()),
CGF.GetIDForAddrOfLabel(E->getLabel()));
return Builder.CreateIntToPtr(V, ConvertType(E->getType()));
+#else
+ llvm::Value *V = CGF.GetAddrOfLabel(E->getLabel());
+ return Builder.CreateBitCast(V, ConvertType(E->getType()));
+#endif
}
// l-values.
@@ -272,7 +277,12 @@ public:
Value *VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) {
return llvm::Constant::getNullValue(ConvertType(E->getType()));
}
-
+
+ Value *VisitCXXThrowExpr(const CXXThrowExpr *E) {
+ CGF.EmitCXXThrowExpr(E);
+ return 0;
+ }
+
// Binary Operators.
Value *EmitMul(const BinOpInfo &Ops) {
if (CGF.getContext().getLangOptions().OverflowChecking
@@ -678,14 +688,13 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
// If the initializer is an ExtVecEltExpr (a swizzle), and the swizzle's
// input is the same width as the vector being constructed, generate an
// optimized shuffle of the swizzle input into the result.
+ unsigned Offset = (CurIdx == 0) ? 0 : ResElts;
if (isa<ExtVectorElementExpr>(IE)) {
llvm::ShuffleVectorInst *SVI = cast<llvm::ShuffleVectorInst>(Init);
Value *SVOp = SVI->getOperand(0);
const llvm::VectorType *OpTy = cast<llvm::VectorType>(SVOp->getType());
if (OpTy->getNumElements() == ResElts) {
- unsigned Offset = (CurIdx == 0) ? 0 : ResElts;
-
for (unsigned j = 0; j != CurIdx; ++j) {
// If the current vector initializer is a shuffle with undef, merge
// this shuffle directly into it.
@@ -717,13 +726,13 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
Args.push_back(llvm::UndefValue::get(I32Ty));
llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts);
Init = Builder.CreateShuffleVector(Init, llvm::UndefValue::get(VVT),
- Mask, "vecext");
+ Mask, "vext");
Args.clear();
for (unsigned j = 0; j != CurIdx; ++j)
Args.push_back(llvm::ConstantInt::get(I32Ty, j));
for (unsigned j = 0; j != InitElts; ++j)
- Args.push_back(llvm::ConstantInt::get(I32Ty, j+ResElts));
+ Args.push_back(llvm::ConstantInt::get(I32Ty, j+Offset));
for (unsigned j = CurIdx + InitElts; j != ResElts; ++j)
Args.push_back(llvm::UndefValue::get(I32Ty));
}
@@ -1639,9 +1648,10 @@ Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) {
/// expression is cheap enough and side-effect-free enough to evaluate
/// unconditionally instead of conditionally. This is used to convert control
/// flow into selects in some cases.
-static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E) {
+static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E,
+ CodeGenFunction &CGF) {
if (const ParenExpr *PE = dyn_cast<ParenExpr>(E))
- return isCheapEnoughToEvaluateUnconditionally(PE->getSubExpr());
+ return isCheapEnoughToEvaluateUnconditionally(PE->getSubExpr(), CGF);
// TODO: Allow anything we can constant fold to an integer or fp constant.
if (isa<IntegerLiteral>(E) || isa<CharacterLiteral>(E) ||
@@ -1652,7 +1662,9 @@ static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E) {
// X and Y are local variables.
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
- if (VD->hasLocalStorage() && !VD->getType().isVolatileQualified())
+ if (VD->hasLocalStorage() && !(CGF.getContext()
+ .getCanonicalType(VD->getType())
+ .isVolatileQualified()))
return true;
return false;
@@ -1681,8 +1693,9 @@ VisitConditionalOperator(const ConditionalOperator *E) {
// If this is a really simple expression (like x ? 4 : 5), emit this as a
// select instead of as control flow. We can only do this if it is cheap and
// safe to evaluate the LHS and RHS unconditionally.
- if (E->getLHS() && isCheapEnoughToEvaluateUnconditionally(E->getLHS()) &&
- isCheapEnoughToEvaluateUnconditionally(E->getRHS())) {
+ if (E->getLHS() && isCheapEnoughToEvaluateUnconditionally(E->getLHS(),
+ CGF) &&
+ isCheapEnoughToEvaluateUnconditionally(E->getRHS(), CGF)) {
llvm::Value *CondV = CGF.EvaluateExprAsBool(E->getCond());
llvm::Value *LHS = Visit(E->getLHS());
llvm::Value *RHS = Visit(E->getRHS());
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index cadba328bf12..2fe3f5b1b443 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -280,17 +280,29 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args),
SetPropertyFn, Args);
} else {
+ // FIXME: Find a clean way to avoid AST node creation.
SourceLocation Loc = PD->getLocation();
ValueDecl *Self = OMD->getSelfDecl();
ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
DeclRefExpr Base(Self, Self->getType(), Loc);
ParmVarDecl *ArgDecl = *OMD->param_begin();
DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), Loc);
- ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base,
- true, true);
- BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign,
- Ivar->getType(), Loc);
- EmitStmt(&Assign);
+ ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true);
+
+ // The property type can differ from the ivar type in some situations with
+ // Objective-C pointer types, we can always bit cast the RHS in these cases.
+ if (getContext().getCanonicalType(Ivar->getType()) !=
+ getContext().getCanonicalType(ArgDecl->getType())) {
+ ImplicitCastExpr ArgCasted(Ivar->getType(), CastExpr::CK_BitCast, &Arg,
+ false);
+ BinaryOperator Assign(&IvarRef, &ArgCasted, BinaryOperator::Assign,
+ Ivar->getType(), Loc);
+ EmitStmt(&Assign);
+ } else {
+ BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign,
+ Ivar->getType(), Loc);
+ EmitStmt(&Assign);
+ }
}
FinishFunction();
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.h b/lib/CodeGen/CGRecordLayoutBuilder.h
index d1a13aa29711..4ebf4e88decb 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.h
+++ b/lib/CodeGen/CGRecordLayoutBuilder.h
@@ -15,7 +15,7 @@
#define CLANG_CODEGEN_CGRECORDLAYOUTBUILDER_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include <vector>
namespace llvm {
diff --git a/lib/CodeGen/CGRtti.cpp b/lib/CodeGen/CGRtti.cpp
index 7bc774fce75b..7af15f0a8ca4 100644
--- a/lib/CodeGen/CGRtti.cpp
+++ b/lib/CodeGen/CGRtti.cpp
@@ -16,32 +16,31 @@ using namespace clang;
using namespace CodeGen;
llvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) {
- llvm::Type *Ptr8Ty;
- Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
- llvm::Constant *Rtti = llvm::Constant::getNullValue(Ptr8Ty);
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
if (!getContext().getLangOptions().Rtti)
- return Rtti;
+ return llvm::Constant::getNullValue(Int8PtrTy);
llvm::SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
- mangleCXXRtti(getMangleContext(), RD, Out);
+ mangleCXXRtti(getMangleContext(), Context.getTagDeclType(RD), Out);
llvm::GlobalVariable::LinkageTypes linktype;
linktype = llvm::GlobalValue::WeakAnyLinkage;
std::vector<llvm::Constant *> info;
// assert(0 && "FIXME: implement rtti descriptor");
// FIXME: descriptor
- info.push_back(llvm::Constant::getNullValue(Ptr8Ty));
+ info.push_back(llvm::Constant::getNullValue(Int8PtrTy));
// assert(0 && "FIXME: implement rtti ts");
// FIXME: TS
- info.push_back(llvm::Constant::getNullValue(Ptr8Ty));
+ info.push_back(llvm::Constant::getNullValue(Int8PtrTy));
llvm::Constant *C;
- llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, info.size());
+ llvm::ArrayType *type = llvm::ArrayType::get(Int8PtrTy, info.size());
C = llvm::ConstantArray::get(type, info);
- Rtti = new llvm::GlobalVariable(getModule(), type, true, linktype, C,
- Out.str());
- Rtti = llvm::ConstantExpr::getBitCast(Rtti, Ptr8Ty);
+ llvm::Constant *Rtti =
+ new llvm::GlobalVariable(getModule(), type, true, linktype, C,
+ Out.str());
+ Rtti = llvm::ConstantExpr::getBitCast(Rtti, Int8PtrTy);
return Rtti;
}
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index f58b57926787..9126c2c99cdf 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -287,8 +287,13 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
// Emit initial switch which will be patched up later by
// EmitIndirectSwitches(). We need a default dest, so we use the
// current BB, but this is overwritten.
+#ifndef USEINDIRECTBRANCH
llvm::Value *V = Builder.CreatePtrToInt(EmitScalarExpr(S.getTarget()),
llvm::Type::getInt32Ty(VMContext),
+#else
+ llvm::Value *V = Builder.CreateBitCast(EmitScalarExpr(S.getTarget()),
+ llvm::Type::getInt8PtrTy(VMContext),
+#endif
"addr");
llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index 2a06f51f6685..fa77471bce0e 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -47,7 +47,7 @@ public:
bool isVolatileQualified() const { return Volatile; }
- /// getScalar() - Return the Value* of this scalar value.
+ /// getScalarVal() - Return the Value* of this scalar value.
llvm::Value *getScalarVal() const {
assert(isScalar() && "Not a scalar!");
return V1;
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 9df0e1abd547..e2e11478de26 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -43,6 +43,9 @@ private:
llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall;
llvm::DenseMap<const CXXMethodDecl *, Index_t> VCallOffset;
llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex;
+
+ typedef llvm::DenseMap<const CXXMethodDecl *, int> Pures_t;
+ Pures_t Pures;
typedef std::pair<Index_t, Index_t> CallOffset;
typedef llvm::DenseMap<const CXXMethodDecl *, CallOffset> Thunks_t;
Thunks_t Thunks;
@@ -58,6 +61,7 @@ private:
Index_t extra;
int CurrentVBaseOffset;
typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t;
+ llvm::Constant *cxa_pure;
public:
VtableBuilder(std::vector<llvm::Constant *> &meth,
const CXXRecordDecl *c,
@@ -68,6 +72,13 @@ public:
LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)),
CurrentVBaseOffset(0) {
Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
+
+ // Calculate pointer for ___cxa_pure_virtual.
+ const llvm::FunctionType *FTy;
+ std::vector<const llvm::Type*> ArgTys;
+ const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
+ FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
+ cxa_pure = wrap(CGM.CreateRuntimeFunction(FTy, "__cxa_pure_virtual"));
}
llvm::DenseMap<const CXXMethodDecl *, Index_t> &getIndex() { return Index; }
@@ -84,8 +95,10 @@ public:
return llvm::ConstantExpr::getBitCast(m, Ptr8Ty);
}
- void GenerateVBaseOffsets(std::vector<llvm::Constant *> &offsets,
- const CXXRecordDecl *RD, uint64_t Offset,
+#define D1(x)
+//#define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
+
+ void GenerateVBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
bool updateVBIndex, Index_t current_vbindex) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
@@ -94,22 +107,24 @@ public:
Index_t next_vbindex = current_vbindex;
if (i->isVirtual() && !SeenVBase.count(Base)) {
SeenVBase.insert(Base);
- int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
- llvm::Constant *m = wrap(BaseOffset);
- m = wrap((0?700:0) + BaseOffset);
if (updateVBIndex) {
- next_vbindex = (ssize_t)(-(offsets.size()*LLVMPointerWidth/8)
+ next_vbindex = (ssize_t)(-(VCalls.size()*LLVMPointerWidth/8)
- 3*LLVMPointerWidth/8);
VBIndex[Base] = next_vbindex;
}
- offsets.push_back(m);
+ int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
+ VCalls.push_back((0?700:0) + BaseOffset);
+ D1(printf(" vbase for %s at %d delta %d most derived %s\n",
+ Base->getNameAsCString(),
+ (int)-VCalls.size()-3, (int)BaseOffset,
+ Class->getNameAsCString()));
}
// We also record offsets for non-virtual bases to closest enclosing
// virtual base. We do this so that we don't have to search
// for the nearst virtual base class when generating thunks.
if (updateVBIndex && VBIndex.count(Base) == 0)
VBIndex[Base] = next_vbindex;
- GenerateVBaseOffsets(offsets, Base, Offset, updateVBIndex, next_vbindex);
+ GenerateVBaseOffsets(Base, Offset, updateVBIndex, next_vbindex);
}
}
@@ -144,8 +159,8 @@ public:
/// getNVOffset - Returns the non-virtual offset for the given (B) base of the
/// derived class D.
Index_t getNVOffset(QualType qB, QualType qD) {
- qD = qD->getAs<PointerType>()->getPointeeType();
- qB = qB->getAs<PointerType>()->getPointeeType();
+ qD = qD->getPointeeType();
+ qB = qB->getPointeeType();
CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
int64_t o = getNVOffset_1(D, B);
@@ -159,8 +174,8 @@ public:
/// getVbaseOffset - Returns the index into the vtable for the virtual base
/// offset for the given (B) virtual base of the derived class D.
Index_t getVbaseOffset(QualType qB, QualType qD) {
- qD = qD->getAs<PointerType>()->getPointeeType();
- qB = qB->getAs<PointerType>()->getPointeeType();
+ qD = qD->getPointeeType();
+ qB = qB->getPointeeType();
CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
if (D != Class)
@@ -177,6 +192,7 @@ public:
bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m,
bool MorallyVirtual, Index_t OverrideOffset,
Index_t Offset) {
+ const bool isPure = MD->isPure();
typedef CXXMethodDecl::method_iterator meth_iter;
// FIXME: Should OverrideOffset's be Offset?
@@ -215,7 +231,9 @@ public:
}
Index[MD] = i;
submethods[i] = m;
-
+ if (isPure)
+ Pures[MD] = 1;
+ Pures.erase(OMD);
Thunks.erase(OMD);
if (MorallyVirtual) {
Index_t &idx = VCall[OMD];
@@ -223,9 +241,17 @@ public:
VCallOffset[MD] = OverrideOffset/8;
idx = VCalls.size()+1;
VCalls.push_back(0);
+ D1(printf(" vcall for %s at %d with delta %d most derived %s\n",
+ MD->getNameAsCString(),
+ (int)-VCalls.size()-3, (int)VCallOffset[MD],
+ Class->getNameAsCString()));
} else {
VCallOffset[MD] = VCallOffset[OMD];
VCalls[idx-1] = -VCallOffset[OMD] + OverrideOffset/8;
+ D1(printf(" vcall patch for %s at %d with delta %d most derived %s\n",
+ MD->getNameAsCString(),
+ (int)-VCalls.size()-3, (int)VCallOffset[MD],
+ Class->getNameAsCString()));
}
VCall[MD] = idx;
CallOffset ThisOffset;
@@ -237,7 +263,7 @@ public:
CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset,
ReturnOffset),
oret);
- else
+ else if (!isPure)
Thunks[MD] = ThisOffset;
return true;
}
@@ -252,7 +278,7 @@ public:
CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset,
ReturnOffset),
oret);
- else
+ else if (!isPure)
Thunks[MD] = ThisOffset;
}
return true;
@@ -266,6 +292,7 @@ public:
for (Thunks_t::iterator i = Thunks.begin(), e = Thunks.end();
i != e; ++i) {
const CXXMethodDecl *MD = i->first;
+ assert(!MD->isPure() && "Trying to thunk a pure");
Index_t idx = Index[MD];
Index_t nv_O = i->second.first;
Index_t v_O = i->second.second;
@@ -276,6 +303,8 @@ public:
e = CovariantThunks.end();
i != e; ++i) {
const CXXMethodDecl *MD = i->first;
+ if (MD->isPure())
+ continue;
Index_t idx = Index[MD];
Index_t nv_t = i->second.first.first.first;
Index_t v_t = i->second.first.first.second;
@@ -285,6 +314,25 @@ public:
v_r);
}
CovariantThunks.clear();
+ for (Pures_t::iterator i = Pures.begin(), e = Pures.end();
+ i != e; ++i) {
+ const CXXMethodDecl *MD = i->first;
+ Index_t idx = Index[MD];
+ submethods[idx] = cxa_pure;
+ }
+ Pures.clear();
+ }
+
+ llvm::Constant *WrapAddrOf(const CXXMethodDecl *MD) {
+ if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD))
+ return wrap(CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete));
+
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+ const llvm::Type *Ty =
+ CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
+ FPT->isVariadic());
+
+ return wrap(CGM.GetAddrOfFunction(MD, Ty));
}
void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset) {
@@ -298,37 +346,16 @@ public:
continue;
const CXXMethodDecl *MD = *mi;
- llvm::Constant *m = 0;
- if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD))
- m = wrap(CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete));
- else {
- const FunctionProtoType *FPT =
- MD->getType()->getAs<FunctionProtoType>();
- const llvm::Type *Ty =
- CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
- FPT->isVariadic());
-
- m = wrap(CGM.GetAddrOfFunction(MD, Ty));
- }
-
+ llvm::Constant *m = WrapAddrOf(MD);
OverrideMethod(MD, m, MorallyVirtual, OverrideOffset, Offset);
}
}
}
- void AddMethod(const CXXMethodDecl *MD, bool MorallyVirtual, Index_t Offset) {
- llvm::Constant *m = 0;
- if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD))
- m = wrap(CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete));
- else {
- const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
- const llvm::Type *Ty =
- CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
- FPT->isVariadic());
-
- m = wrap(CGM.GetAddrOfFunction(MD, Ty));
- }
-
+ void AddMethod(const CXXMethodDecl *MD, bool MorallyVirtual, Index_t Offset,
+ bool ForVirtualBase) {
+ llvm::Constant *m = WrapAddrOf(MD);
+
// If we can find a previously allocated slot for this, reuse it.
if (OverrideMethod(MD, m, MorallyVirtual, Offset, Offset))
return;
@@ -336,6 +363,9 @@ public:
// else allocate a new slot.
Index[MD] = submethods.size();
submethods.push_back(m);
+ D1(printf(" vfn for %s at %d\n", MD->getNameAsCString(), (int)Index[MD]));
+ if (MD->isPure())
+ Pures[MD] = 1;
if (MorallyVirtual) {
VCallOffset[MD] = Offset/8;
Index_t &idx = VCall[MD];
@@ -343,16 +373,19 @@ public:
if (idx == 0) {
idx = VCalls.size()+1;
VCalls.push_back(0);
+ D1(printf(" vcall for %s at %d with delta %d\n",
+ MD->getNameAsCString(), (int)-VCalls.size()-3,
+ (int)VCallOffset[MD]));
}
}
}
void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual,
- Index_t Offset) {
+ Index_t Offset, bool RDisVirtualBase) {
for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
++mi)
if (mi->isVirtual())
- AddMethod(*mi, MorallyVirtual, Offset);
+ AddMethod(*mi, MorallyVirtual, Offset, RDisVirtualBase);
}
void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
@@ -381,6 +414,7 @@ public:
void insertVCalls(int InsertionPoint) {
llvm::Constant *e = 0;
+ D1(printf("============= combining vbase/vcall\n"));
D(VCalls.insert(VCalls.begin(), 673));
D(VCalls.push_back(672));
methods.insert(methods.begin() + InsertionPoint, VCalls.size(), e);
@@ -392,11 +426,10 @@ public:
VCalls.clear();
}
- Index_t end(const CXXRecordDecl *RD, std::vector<llvm::Constant *> &offsets,
- const ASTRecordLayout &Layout,
- const CXXRecordDecl *PrimaryBase,
- bool PrimaryBaseWasVirtual, bool MorallyVirtual,
- int64_t Offset, bool ForVirtualBase, Path_t *Path) {
+ Index_t end(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
+ const CXXRecordDecl *PrimaryBase, bool PrimaryBaseWasVirtual,
+ bool MorallyVirtual, int64_t Offset, bool ForVirtualBase,
+ Path_t *Path) {
bool alloc = false;
if (Path == 0) {
alloc = true;
@@ -405,16 +438,6 @@ public:
StartNewTable();
extra = 0;
- // FIXME: Cleanup.
- if (!ForVirtualBase) {
- D(methods.push_back(wrap(666)));
- // then virtual base offsets...
- for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(),
- e = offsets.rend(); i != e; ++i)
- methods.push_back(*i);
- D(methods.push_back(wrap(667)));
- }
-
bool DeferVCalls = MorallyVirtual || ForVirtualBase;
int VCallInsertionPoint = methods.size();
if (!DeferVCalls) {
@@ -423,20 +446,12 @@ public:
// FIXME: just for extra, or for all uses of VCalls.size post this?
extra = -VCalls.size();
- if (ForVirtualBase) {
- D(methods.push_back(wrap(668)));
- // then virtual base offsets...
- for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(),
- e = offsets.rend(); i != e; ++i)
- methods.push_back(*i);
- D(methods.push_back(wrap(669)));
- }
-
methods.push_back(wrap(-(Offset/8)));
methods.push_back(rtti);
Index_t AddressPoint = methods.size();
InstallThunks();
+ D1(printf("============= combining methods\n"));
methods.insert(methods.end(), submethods.begin(), submethods.end());
submethods.clear();
@@ -445,10 +460,8 @@ public:
MorallyVirtual, Offset, Path);
if (ForVirtualBase) {
- D(methods.push_back(wrap(670)));
insertVCalls(VCallInsertionPoint);
AddressPoint += VCalls.size();
- D(methods.push_back(wrap(671)));
}
if (alloc) {
@@ -457,7 +470,36 @@ public:
return AddressPoint;
}
- void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset) {
+ void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
+ bool updateVBIndex, Index_t current_vbindex,
+ bool RDisVirtualBase) {
+ if (!RD->isDynamicClass())
+ return;
+
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+ const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
+
+ // vtables are composed from the chain of primaries.
+ if (PrimaryBase) {
+ D1(printf(" doing primaries for %s most derived %s\n",
+ RD->getNameAsCString(), Class->getNameAsCString()));
+
+ if (!PrimaryBaseWasVirtual)
+ Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
+ updateVBIndex, current_vbindex, PrimaryBaseWasVirtual);
+ }
+
+ D1(printf(" doing vcall entries for %s most derived %s\n",
+ RD->getNameAsCString(), Class->getNameAsCString()));
+
+ // And add the virtuals for the class to the primary vtable.
+ AddMethods(RD, MorallyVirtual, Offset, RDisVirtualBase);
+ }
+
+ void VBPrimaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
+ bool updateVBIndex, Index_t current_vbindex,
+ bool RDisVirtualBase, bool bottom=false) {
if (!RD->isDynamicClass())
return;
@@ -469,11 +511,22 @@ public:
if (PrimaryBase) {
if (PrimaryBaseWasVirtual)
IndirectPrimary.insert(PrimaryBase);
- Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset);
+
+ D1(printf(" doing primaries for %s most derived %s\n",
+ RD->getNameAsCString(), Class->getNameAsCString()));
+
+ VBPrimaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
+ updateVBIndex, current_vbindex, PrimaryBaseWasVirtual);
}
- // And add the virtuals for the class to the primary vtable.
- AddMethods(RD, MorallyVirtual, Offset);
+ D1(printf(" doing vbase entries for %s most derived %s\n",
+ RD->getNameAsCString(), Class->getNameAsCString()));
+ GenerateVBaseOffsets(RD, Offset, updateVBIndex, current_vbindex);
+
+ if (RDisVirtualBase || bottom) {
+ Primaries(RD, MorallyVirtual, Offset, updateVBIndex, current_vbindex,
+ RDisVirtualBase);
+ }
}
int64_t GenerateVtableForBase(const CXXRecordDecl *RD,
@@ -487,27 +540,21 @@ public:
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
- std::vector<llvm::Constant *> offsets;
extra = 0;
- GenerateVBaseOffsets(offsets, RD, Offset, !ForVirtualBase, 0);
- if (ForVirtualBase)
- extra = offsets.size();
+ D1(printf("building entries for base %s most derived %s\n",
+ RD->getNameAsCString(), Class->getNameAsCString()));
- // vtables are composed from the chain of primaries.
- if (PrimaryBase) {
- if (PrimaryBaseWasVirtual)
- IndirectPrimary.insert(PrimaryBase);
- Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset);
- }
+ if (ForVirtualBase)
+ extra = VCalls.size();
- // And add the virtuals for the class to the primary vtable.
- AddMethods(RD, MorallyVirtual, Offset);
+ VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0, ForVirtualBase,
+ true);
if (Path)
OverrideMethods(Path, MorallyVirtual, Offset);
- return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual,
- MorallyVirtual, Offset, ForVirtualBase, Path);
+ return end(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, MorallyVirtual,
+ Offset, ForVirtualBase, Path);
}
void GenerateVtableForVBases(const CXXRecordDecl *RD,
@@ -532,6 +579,8 @@ public:
VCall.clear();
int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
CurrentVBaseOffset = BaseOffset;
+ D1(printf("vtable %s virtual base %s\n",
+ Class->getNameAsCString(), Base->getNameAsCString()));
GenerateVtableForBase(Base, true, BaseOffset, true, Path);
}
int64_t BaseOffset = Offset;
@@ -567,6 +616,7 @@ int64_t CGVtableInfo::getMethodVtableIndex(const CXXMethodDecl *MD) {
// FIXME: This seems expensive. Can we do a partial job to get
// just this data.
VtableBuilder b(methods, RD, CGM);
+ D1(printf("vtable %s\n", RD->getNameAsCString()));
b.GenerateVtableForBase(RD);
b.GenerateVtableForVBases(RD);
@@ -591,6 +641,7 @@ int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
// FIXME: This seems expensive. Can we do a partial job to get
// just this data.
VtableBuilder b(methods, RD, CGM);
+ D1(printf("vtable %s\n", RD->getNameAsCString()));
b.GenerateVtableForBase(RD);
b.GenerateVtableForVBases(RD);
@@ -614,13 +665,14 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) {
mangleCXXVtable(CGM.getMangleContext(), RD, Out);
llvm::GlobalVariable::LinkageTypes linktype;
- linktype = llvm::GlobalValue::WeakAnyLinkage;
+ linktype = llvm::GlobalValue::LinkOnceODRLinkage;
std::vector<llvm::Constant *> methods;
llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
int64_t AddressPoint;
VtableBuilder b(methods, RD, CGM);
+ D1(printf("vtable %s\n", RD->getNameAsCString()));
// First comes the vtables for all the non-virtual bases...
AddressPoint = b.GenerateVtableForBase(RD);
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 2f46313c9c20..10884a7560f5 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -10,6 +10,7 @@ add_clang_library(clangCodeGen
CGCall.cpp
CGDebugInfo.cpp
CGDecl.cpp
+ CGException.cpp
CGExpr.cpp
CGExprAgg.cpp
CGExprComplex.cpp
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index ba93e5d0ebc8..88beadf33140 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -27,7 +27,11 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
: BlockFunction(cgm, *this, Builder), CGM(cgm),
Target(CGM.getContext().Target),
Builder(cgm.getModule().getContext()),
+#ifndef USEINDIRECTBRANCH
DebugInfo(0), IndirectGotoSwitch(0),
+#else
+ DebugInfo(0), IndirectBranch(0),
+#endif
SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0),
CXXThisDecl(0) {
LLVMIntTy = ConvertType(getContext().IntTy);
@@ -130,10 +134,33 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
EmitFunctionEpilog(*CurFnInfo, ReturnValue);
+#ifdef USEINDIRECTBRANCH
+ // If someone did an indirect goto, emit the indirect goto block at the end of
+ // the function.
+ if (IndirectBranch) {
+ EmitBlock(IndirectBranch->getParent());
+ Builder.ClearInsertionPoint();
+ }
+
+
+#endif
// Remove the AllocaInsertPt instruction, which is just a convenience for us.
llvm::Instruction *Ptr = AllocaInsertPt;
AllocaInsertPt = 0;
Ptr->eraseFromParent();
+#ifdef USEINDIRECTBRANCH
+
+ // If someone took the address of a label but never did an indirect goto, we
+ // made a zero entry PHI node, which is illegal, zap it now.
+ if (IndirectBranch) {
+ llvm::PHINode *PN = cast<llvm::PHINode>(IndirectBranch->getAddress());
+ if (PN->getNumIncomingValues() == 0) {
+ PN->replaceAllUsesWith(llvm::UndefValue::get(PN->getType()));
+ PN->eraseFromParent();
+ }
+ }
+
+#endif
}
void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
@@ -466,13 +493,26 @@ void CodeGenFunction::EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty) {
TypeInfo.second/8));
}
+#ifndef USEINDIRECTBRANCH
unsigned CodeGenFunction::GetIDForAddrOfLabel(const LabelStmt *L) {
// Use LabelIDs.size()+1 as the new ID if one hasn't been assigned.
unsigned &Entry = LabelIDs[L];
if (Entry) return Entry;
+#else
+
+llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelStmt *L) {
+ // Make sure that there is a block for the indirect goto.
+ if (IndirectBranch == 0)
+ GetIndirectGotoBlock();
+#endif
+#ifndef USEINDIRECTBRANCH
Entry = LabelIDs.size();
+#else
+ llvm::BasicBlock *BB = getBasicBlockForLabel(L);
+#endif
+#ifndef USEINDIRECTBRANCH
// If this is the first "address taken" of a label and the indirect goto has
// already been seen, add this to it.
if (IndirectGotoSwitch) {
@@ -488,18 +528,42 @@ unsigned CodeGenFunction::GetIDForAddrOfLabel(const LabelStmt *L) {
}
return Entry;
+#else
+ // Make sure the indirect branch includes all of the address-taken blocks.
+ IndirectBranch->addDestination(BB);
+ return llvm::BlockAddress::get(CurFn, BB);
+#endif
}
llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
+#ifndef USEINDIRECTBRANCH
// If we already made the switch stmt for indirect goto, return its block.
if (IndirectGotoSwitch) return IndirectGotoSwitch->getParent();
+#else
+ // If we already made the indirect branch for indirect goto, return its block.
+ if (IndirectBranch) return IndirectBranch->getParent();
+#endif
+#ifndef USEINDIRECTBRANCH
EmitBlock(createBasicBlock("indirectgoto"));
+#else
+ CGBuilderTy TmpBuilder(createBasicBlock("indirectgoto"));
+#endif
+#ifndef USEINDIRECTBRANCH
+ const llvm::IntegerType *Int32Ty = llvm::Type::getInt32Ty(VMContext);
+#else
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
+#endif
+
// Create the PHI node that indirect gotos will add entries to.
- llvm::Value *DestVal =
- Builder.CreatePHI(llvm::Type::getInt32Ty(VMContext), "indirect.goto.dest");
+#ifndef USEINDIRECTBRANCH
+ llvm::Value *DestVal = Builder.CreatePHI(Int32Ty, "indirect.goto.dest");
+#else
+ llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, "indirect.goto.dest");
+#endif
+#ifndef USEINDIRECTBRANCH
// Create the switch instruction. For now, set the insert block to this block
// which will be fixed as labels are added.
IndirectGotoSwitch = Builder.CreateSwitch(DestVal, Builder.GetInsertBlock());
@@ -524,8 +588,6 @@ llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
IndirectGotoSwitch->setSuccessor(0,
getBasicBlockForLabel(AddrTakenLabelsByID[0]));
- const llvm::IntegerType *Int32Ty = llvm::Type::getInt32Ty(VMContext);
-
// FIXME: The iteration order of this is nondeterminstic!
for (unsigned i = 1, e = AddrTakenLabelsByID.size(); i != e; ++i)
IndirectGotoSwitch->addCase(llvm::ConstantInt::get(Int32Ty, i+1),
@@ -541,6 +603,11 @@ llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
}
return IndirectGotoSwitch->getParent();
+#else
+ // Create the indirect branch instruction.
+ IndirectBranch = TmpBuilder.CreateIndirectBr(DestVal);
+ return IndirectBranch->getParent();
+#endif
}
llvm::Value *CodeGenFunction::GetVLASize(const VariableArrayType *VAT) {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 639e683f0369..9bb219642ab4 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -183,13 +183,22 @@ public:
void PopConditionalTempDestruction();
private:
- CGDebugInfo* DebugInfo;
+ CGDebugInfo *DebugInfo;
+#ifndef USEINDIRECTBRANCH
/// LabelIDs - Track arbitrary ids assigned to labels for use in implementing
/// the GCC address-of-label extension and indirect goto. IDs are assigned to
/// labels inside getIDForAddrOfLabel().
std::map<const LabelStmt*, unsigned> LabelIDs;
+#else
+ /// IndirectBranch - The first time an indirect goto is seen we create a
+ /// block with an indirect branch. Every time we see the address of a label
+ /// taken, we add the label to the indirect goto. Every subsequent indirect
+ /// goto is codegen'd as a jump to the IndirectBranch's basic block.
+ llvm::IndirectBrInst *IndirectBranch;
+#endif
+#ifndef USEINDIRECTBRANCH
/// IndirectGotoSwitch - The first time an indirect goto is seen we create a
/// block with the switch for the indirect gotos. Every time we see the
/// address of a label taken, we add the label to the indirect goto. Every
@@ -197,6 +206,7 @@ private:
/// IndirectGotoSwitch's basic block.
llvm::SwitchInst *IndirectGotoSwitch;
+#endif
/// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C
/// decls.
llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
@@ -377,6 +387,11 @@ public:
/// GenerateVtable - Generate the vtable for the given type.
llvm::Value *GenerateVtable(const CXXRecordDecl *RD);
+ /// DynamicTypeAdjust - Do the non-virtual and virtual adjustments on an
+ /// object pointer to alter the dynamic type of the pointer. Used by
+ /// GenerateCovariantThunk for building thunks.
+ llvm::Value *DynamicTypeAdjust(llvm::Value *V, int64_t nv, int64_t v);
+
/// GenerateThunk - Generate a thunk for the given method
llvm::Constant *GenerateThunk(llvm::Function *Fn, const CXXMethodDecl *MD,
bool Extern, int64_t nv, int64_t v);
@@ -502,7 +517,7 @@ public:
//===--------------------------------------------------------------------===//
Qualifiers MakeQualifiers(QualType T) {
- Qualifiers Quals = T.getQualifiers();
+ Qualifiers Quals = getContext().getCanonicalType(T).getQualifiers();
Quals.setObjCGCAttr(getContext().getObjCGCAttrKind(T));
return Quals;
}
@@ -558,7 +573,11 @@ public:
/// the input field number being accessed.
static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts);
+#ifndef USEINDIRECTBRANCH
unsigned GetIDForAddrOfLabel(const LabelStmt *L);
+#else
+ llvm::BlockAddress *GetAddrOfLabel(const LabelStmt *L);
+#endif
llvm::BasicBlock *GetIndirectGotoBlock();
/// EmitMemSetToZero - Generate code to memset a value of the given type to 0.
@@ -819,7 +838,7 @@ public:
LValue EmitConditionalOperatorLValue(const ConditionalOperator *E);
LValue EmitCastLValue(const CastExpr *E);
LValue EmitNullInitializationLValue(const CXXZeroInitValueExpr *E);
- LValue EmitPointerToDataMemberLValue(const QualifiedDeclRefExpr *E);
+ LValue EmitPointerToDataMemberLValue(const DeclRefExpr *E);
llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar);
@@ -1000,6 +1019,8 @@ public:
bool IsAggLocVolatile = false,
bool IsInitializer = false);
+ void EmitCXXThrowExpr(const CXXThrowExpr *E);
+
//===--------------------------------------------------------------------===//
// Internal Helpers
//===--------------------------------------------------------------------===//
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index ea84829b78a5..db609f62453c 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -253,6 +253,10 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
if (FD->isInAnonymousNamespace())
return CodeGenModule::GVA_Internal;
+ // "static" functions get internal linkage.
+ if (FD->getStorageClass() == FunctionDecl::Static && !isa<CXXMethodDecl>(FD))
+ return CodeGenModule::GVA_Internal;
+
// The kind of external linkage this function will have, if it is not
// inline or static.
CodeGenModule::GVALinkage External = CodeGenModule::GVA_StrongExternal;
@@ -260,19 +264,7 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
External = CodeGenModule::GVA_TemplateInstantiation;
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
- // C++ member functions defined inside the class are always inline.
- if (MD->isInline() || !MD->isOutOfLine())
- return CodeGenModule::GVA_CXXInline;
-
- return External;
- }
-
- // "static" functions get internal linkage.
- if (FD->getStorageClass() == FunctionDecl::Static)
- return CodeGenModule::GVA_Internal;
-
- if (!FD->isInline())
+ if (!FD->isInlined())
return External;
if (!Features.CPlusPlus || FD->hasAttr<GNUInlineAttr>()) {
@@ -285,8 +277,16 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
return CodeGenModule::GVA_C99Inline;
}
- // C++ inline semantics
- assert(Features.CPlusPlus && "Must be in C++ mode");
+ // C++0x [temp.explicit]p9:
+ // [ Note: The intent is that an inline function that is the subject of
+ // an explicit instantiation declaration will still be implicitly
+ // instantiated when used so that the body can be considered for
+ // inlining, but that no out-of-line copy of the inline function would be
+ // generated in the translation unit. -- end note ]
+ if (FD->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDeclaration)
+ return CodeGenModule::GVA_C99Inline;
+
return CodeGenModule::GVA_CXXInline;
}
@@ -601,6 +601,10 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
+ PrettyStackTraceDecl CrashInfo((ValueDecl *)D, D->getLocation(),
+ Context.getSourceManager(),
+ "Generating code for declaration");
+
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
EmitCXXConstructor(CD, GD.getCtorType());
else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D))
@@ -949,7 +953,7 @@ GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
return CodeGenModule::GVA_StrongExternal;
case TSK_ExplicitInstantiationDeclaration:
- assert(false && "Variable should not be instantiated");
+ llvm::llvm_unreachable("Variable should not be instantiated");
// Fall through to treat this like any other instantiation.
case TSK_ImplicitInstantiation:
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index dedf824ef9fd..d43d13e26bbb 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -180,7 +180,7 @@ static const llvm::Type* getTypeForFormat(llvm::LLVMContext &VMContext,
}
const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
- const clang::Type &Ty = *Context.getCanonicalType(T);
+ const clang::Type &Ty = *Context.getCanonicalType(T).getTypePtr();
switch (Ty.getTypeClass()) {
#define TYPE(Class, Base)
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 2e6034bbcd97..a5b34527969b 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -52,7 +52,8 @@ namespace {
void mangleGuardVariable(const VarDecl *D);
void mangleCXXVtable(const CXXRecordDecl *RD);
- void mangleCXXRtti(const CXXRecordDecl *RD);
+ void mangleCXXVTT(const CXXRecordDecl *RD);
+ void mangleCXXRtti(QualType Ty);
void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type);
void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type);
@@ -114,6 +115,7 @@ namespace {
}
static bool isInCLinkageSpecification(const Decl *D) {
+ D = D->getCanonicalDecl();
for (const DeclContext *DC = D->getDeclContext();
!DC->isTranslationUnit(); DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))
@@ -204,10 +206,17 @@ void CXXNameMangler::mangleCXXVtable(const CXXRecordDecl *RD) {
mangleName(RD);
}
-void CXXNameMangler::mangleCXXRtti(const CXXRecordDecl *RD) {
+void CXXNameMangler::mangleCXXVTT(const CXXRecordDecl *RD) {
+ // <special-name> ::= TT <type> # VTT structure
+ Out << "_ZTT";
+ mangleName(RD);
+}
+
+void CXXNameMangler::mangleCXXRtti(QualType Ty) {
// <special-name> ::= TI <type> # typeinfo structure
Out << "_ZTI";
- mangleName(RD);
+
+ mangleType(Ty);
}
void CXXNameMangler::mangleGuardVariable(const VarDecl *D) {
@@ -1355,7 +1364,7 @@ namespace clang {
"Mangling declaration");
CXXNameMangler Mangler(Context, os);
- if (!Mangler.mangle(cast<NamedDecl>(D->getCanonicalDecl())))
+ if (!Mangler.mangle(D))
return false;
os.flush();
@@ -1424,10 +1433,10 @@ namespace clang {
os.flush();
}
- void mangleCXXRtti(MangleContext &Context, const CXXRecordDecl *RD,
+ void mangleCXXRtti(MangleContext &Context, QualType Ty,
llvm::raw_ostream &os) {
CXXNameMangler Mangler(Context, os);
- Mangler.mangleCXXRtti(RD);
+ Mangler.mangleCXXRtti(Ty);
os.flush();
}
diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h
index 2cdb4e23919d..7f46a106f32a 100644
--- a/lib/CodeGen/Mangle.h
+++ b/lib/CodeGen/Mangle.h
@@ -65,7 +65,9 @@ namespace clang {
llvm::raw_ostream &os);
void mangleCXXVtable(MangleContext &Context, const CXXRecordDecl *RD,
llvm::raw_ostream &os);
- void mangleCXXRtti(MangleContext &Context, const CXXRecordDecl *RD,
+ void mangleCXXVTT(MangleContext &Context, const CXXRecordDecl *RD,
+ llvm::raw_ostream &os);
+ void mangleCXXRtti(MangleContext &Context, QualType T,
llvm::raw_ostream &os);
void mangleCXXCtor(MangleContext &Context, const CXXConstructorDecl *D,
CXXCtorType Type, llvm::raw_ostream &os);
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index c9d0b266d1cc..808c31c64828 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -12,8 +12,8 @@
#include "clang/Driver/Action.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
-#include "clang/Driver/Driver.h" // FIXME: Remove?
-#include "clang/Driver/DriverDiagnostic.h" // FIXME: Remove?
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/HostInfo.h"
@@ -22,9 +22,11 @@
#include "clang/Driver/Util.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Process.h"
#include "InputInfo.h"
#include "ToolChains.h"
@@ -32,13 +34,6 @@
using namespace clang::driver;
using namespace clang::driver::tools;
-static const char *MakeFormattedString(const ArgList &Args,
- const llvm::format_object_base &Fmt) {
- llvm::SmallString<256> Str;
- llvm::raw_svector_ostream(Str) << Fmt;
- return Args.MakeArgString(Str.str());
-}
-
/// CheckPreprocessingOptions - Perform some validation of preprocessing
/// arguments that is shared with gcc.
static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
@@ -203,6 +198,10 @@ void Clang::AddPreprocessingOptions(const Driver &D,
// those options. :(
Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
options::OPT_Xpreprocessor);
+
+ // -I- is a deprecated GCC feature, reject it.
+ if (Arg *A = Args.getLastArg(options::OPT_I_))
+ D.Diag(clang::diag::err_drv_I_dash_not_supported) << A->getAsString(Args);
}
/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting.
@@ -417,8 +416,6 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
void Clang::AddX86TargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- // FIXME: This needs to change to use a clang-cc option, and set the attribute
- // on functions.
if (!Args.hasFlag(options::OPT_mred_zone,
options::OPT_mno_red_zone,
true) ||
@@ -426,8 +423,6 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
Args.hasArg(options::OPT_fapple_kext))
CmdArgs.push_back("--disable-red-zone");
- // FIXME: This needs to change to use a clang-cc option, and set the attribute
- // on functions.
if (Args.hasFlag(options::OPT_msoft_float,
options::OPT_mno_soft_float,
false))
@@ -507,6 +502,57 @@ static bool needsExceptions(const ArgList &Args, types::ID InputType,
}
}
+/// getEffectiveClangTriple - Get the "effective" target triple, which is the
+/// triple for the target but with the OS version potentially modified for
+/// Darwin's -mmacosx-version-min.
+static std::string getEffectiveClangTriple(const Driver &D,
+ const ToolChain &TC,
+ const ArgList &Args) {
+ llvm::Triple Triple(getLLVMTriple(TC, Args));
+
+ if (Triple.getOS() != llvm::Triple::Darwin) {
+ // Diagnose use of -mmacosx-version-min and -miphoneos-version-min on
+ // non-Darwin.
+ if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ,
+ options::OPT_miphoneos_version_min_EQ))
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ return Triple.getTriple();
+ }
+
+ // If -mmacosx-version-min=10.3.9 is specified, change the effective triple
+ // from being something like powerpc-apple-darwin9 to powerpc-apple-darwin7.
+ if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ)) {
+ unsigned Major, Minor, Micro;
+ bool HadExtra;
+ if (!Driver::GetReleaseVersion(A->getValue(Args), Major, Minor, Micro,
+ HadExtra) || HadExtra ||
+ Major != 10)
+ D.Diag(clang::diag::err_drv_invalid_version_number)
+ << A->getAsString(Args);
+
+ // Mangle the MacOS version min number into the Darwin number: e.g. 10.3.9
+ // is darwin7.9.
+ llvm::SmallString<16> Str;
+ llvm::raw_svector_ostream(Str) << "darwin" << Minor + 4 << "." << Micro;
+ Triple.setOSName(Str.str());
+ } else if (Arg *A = Args.getLastArg(options::OPT_miphoneos_version_min_EQ)) {
+ unsigned Major, Minor, Micro;
+ bool HadExtra;
+ if (!Driver::GetReleaseVersion(A->getValue(Args), Major, Minor, Micro,
+ HadExtra) || HadExtra)
+ D.Diag(clang::diag::err_drv_invalid_version_number)
+ << A->getAsString(Args);
+
+ // Mangle the iPhoneOS version number into the Darwin number: e.g. 2.0 is 2
+ // -> 9.2.0.
+ llvm::SmallString<16> Str;
+ llvm::raw_svector_ostream(Str) << "darwin9." << Major << "." << Minor;
+ Triple.setOSName(Str.str());
+ }
+
+ return Triple.getTriple();
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
const InputInfo &Output,
@@ -518,12 +564,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
+ // Add the "effective" target triple.
CmdArgs.push_back("-triple");
+ std::string TripleStr = getEffectiveClangTriple(D, getToolChain(), Args);
+ CmdArgs.push_back(Args.MakeArgString(TripleStr));
- const char *TripleStr =
- Args.MakeArgString(getLLVMTriple(getToolChain(), Args));
- CmdArgs.push_back(TripleStr);
-
+ // Select the appropriate action.
if (isa<AnalyzeJobAction>(JA)) {
assert(JA.getType() == types::TY_Plist && "Invalid output type.");
CmdArgs.push_back("-analyze");
@@ -606,9 +652,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// issue is that llvm-gcc translates these options based on
// the values in cc1, whereas we are processing based on
// the driver arguments.
- //
- // FIXME: This is currently broken for -f flags when -fno
- // variants are present.
// This comes from the default translation the driver + cc1
// would do to enable flag_pic.
@@ -661,8 +704,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--debug-pass=Structure");
if (Args.hasArg(options::OPT_fdebug_pass_arguments))
CmdArgs.push_back("--debug-pass=Arguments");
- // FIXME: set --inline-threshhold=50 if (optimize_size || optimize
- // < 3)
+ if (!Args.hasFlag(options::OPT_fmerge_all_constants,
+ options::OPT_fno_merge_all_constants))
+ CmdArgs.push_back("--no-merge-all-constants");
// This is a coarse approximation of what llvm-gcc actually does, both
// -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
@@ -714,9 +758,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue(Args));
}
- // FIXME: Add --stack-protector-buffer-size=<xxx> on
- // -fstack-protect.
-
Arg *Unsupported;
if ((Unsupported = Args.getLastArg(options::OPT_MG)) ||
(Unsupported = Args.getLastArg(options::OPT_MQ)) ||
@@ -726,8 +767,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_v);
Args.AddLastArg(CmdArgs, options::OPT_P);
- Args.AddLastArg(CmdArgs, options::OPT_mmacosx_version_min_EQ);
- Args.AddLastArg(CmdArgs, options::OPT_miphoneos_version_min_EQ);
Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
// Special case debug options to only pass -g to clang. This is
@@ -736,7 +775,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-g");
Args.AddLastArg(CmdArgs, options::OPT_nostdinc);
- Args.AddLastArg(CmdArgs, options::OPT_nostdclanginc);
+ Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
Args.AddLastArg(CmdArgs, options::OPT_isysroot);
@@ -759,7 +798,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->render(Args, CmdArgs);
}
- Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
+ Args.AddLastArg(CmdArgs, options::OPT_pedantic);
+ Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
Args.AddLastArg(CmdArgs, options::OPT_w);
// Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
@@ -770,9 +811,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
if (Std->getOption().matches(options::OPT_ansi))
if (types::isCXX(InputType))
- CmdArgs.push_back("-std=c++98");
+ CmdArgs.push_back("-std=c++98");
else
- CmdArgs.push_back("-std=c89");
+ CmdArgs.push_back("-std=c89");
else
Std->render(Args, CmdArgs);
@@ -794,10 +835,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT__relocatable_pch, true))
CmdArgs.push_back("--relocatable-pch");
- if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
- CmdArgs.push_back("-fconstant-string-class");
- CmdArgs.push_back(A->getValue(Args));
- }
+ if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
+ CmdArgs.push_back("-fconstant-string-class");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ // Pass -fmessage-length=.
+ if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) {
+ A->render(Args, CmdArgs);
+ } else {
+ // If -fmessage-length=N was not specified, determine whether this is a
+ // terminal and, if so, implicitly define -fmessage-length appropriately.
+ unsigned N = llvm::sys::Process::StandardErrColumns();
+ CmdArgs.push_back("-fmessage-length");
+ CmdArgs.push_back(Args.MakeArgString(llvm::Twine(N)));
+ }
// Forward -f options which we can pass directly.
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
@@ -805,7 +857,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
Args.AddLastArg(CmdArgs, options::OPT_fgnu_runtime);
Args.AddLastArg(CmdArgs, options::OPT_flax_vector_conversions);
- Args.AddLastArg(CmdArgs, options::OPT_fmessage_length_EQ);
Args.AddLastArg(CmdArgs, options::OPT_fms_extensions);
Args.AddLastArg(CmdArgs, options::OPT_fnext_runtime);
Args.AddLastArg(CmdArgs, options::OPT_fno_caret_diagnostics);
@@ -871,9 +922,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fsigned-char=0");
}
- // -fno-pascal-strings is default, only pass non-default. If the
- // -tool chain happened to translate to -mpascal-strings, we want to
- // -back translate here.
+ // -fno-pascal-strings is default, only pass non-default. If the tool chain
+ // happened to translate to -mpascal-strings, we want to back translate here.
//
// FIXME: This is gross; that translation should be pulled from the
// tool chain.
@@ -905,9 +955,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
options::OPT_fno_diagnostics_show_option))
CmdArgs.push_back("-fdiagnostics-show-option");
- if (!Args.hasFlag(options::OPT_fcolor_diagnostics,
- options::OPT_fno_color_diagnostics))
- CmdArgs.push_back("-fno-color-diagnostics");
+
+ // Color diagnostics are the default, unless the terminal doesn't support
+ // them.
+ if (Args.hasFlag(options::OPT_fcolor_diagnostics,
+ options::OPT_fno_color_diagnostics) &&
+ llvm::sys::Process::StandardErrHasColors())
+ CmdArgs.push_back("-fcolor-diagnostics");
+
if (!Args.hasFlag(options::OPT_fshow_source_location,
options::OPT_fno_show_source_location))
CmdArgs.push_back("-fno-show-source-location");
@@ -979,6 +1034,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
II.getInputArg().renderAsInput(Args, CmdArgs);
}
+ Args.AddAllArgs(CmdArgs, options::OPT_undef);
+
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath(C, "clang-cc"));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
@@ -1667,23 +1724,18 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
static bool isSourceSuffix(const char *Str) {
// match: 'C', 'CPP', 'c', 'cc', 'cp', 'c++', 'cpp', 'cxx', 'm',
// 'mm'.
- switch (strlen(Str)) {
- default:
- return false;
- case 1:
- return (memcmp(Str, "C", 1) == 0 ||
- memcmp(Str, "c", 1) == 0 ||
- memcmp(Str, "m", 1) == 0);
- case 2:
- return (memcmp(Str, "cc", 2) == 0 ||
- memcmp(Str, "cp", 2) == 0 ||
- memcmp(Str, "mm", 2) == 0);
- case 3:
- return (memcmp(Str, "CPP", 3) == 0 ||
- memcmp(Str, "c++", 3) == 0 ||
- memcmp(Str, "cpp", 3) == 0 ||
- memcmp(Str, "cxx", 3) == 0);
- }
+ return llvm::StringSwitch<bool>(Str)
+ .Case("C", true)
+ .Case("c", true)
+ .Case("m", true)
+ .Case("cc", true)
+ .Case("cp", true)
+ .Case("mm", true)
+ .Case("CPP", true)
+ .Case("c++", true)
+ .Case("cpp", true)
+ .Case("cxx", true)
+ .Default(false);
}
// FIXME: Can we tablegen this?
@@ -1861,7 +1913,7 @@ void darwin::Link::AddLinkArgs(const ArgList &Args,
// Adding all arguments doesn't make sense here but this is what
// gcc does.
Args.AddAllArgsTranslated(CmdArgs, options::OPT_mmacosx_version_min_EQ,
- "-macosx_version_min");
+ "-macosx_version_min");
Args.AddAllArgsTranslated(CmdArgs, options::OPT_miphoneos_version_min_EQ,
"-iphoneos_version_min");
Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
@@ -2137,10 +2189,10 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
}
void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+ Job &Dest, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
ArgStringList CmdArgs;
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
@@ -2167,15 +2219,15 @@ void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
}
void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+ Job &Dest, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
const Driver &D = getToolChain().getHost().getDriver();
ArgStringList CmdArgs;
if ((!Args.hasArg(options::OPT_nostdlib)) &&
- (!Args.hasArg(options::OPT_shared))) {
+ (!Args.hasArg(options::OPT_shared))) {
CmdArgs.push_back("-e");
CmdArgs.push_back("_start");
}
@@ -2212,14 +2264,13 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
} else {
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
-// CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
}
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
}
- CmdArgs.push_back(MakeFormattedString(Args,
- llvm::format("-L/opt/gcc4/lib/gcc/%s/4.2.4",
- getToolChain().getTripleString().c_str())));
+ CmdArgs.push_back(Args.MakeArgString("-L/opt/gcc4/lib/gcc/"
+ + getToolChain().getTripleString()
+ + "/4.2.4"));
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
@@ -2307,7 +2358,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
ArgStringList CmdArgs;
if ((!Args.hasArg(options::OPT_nostdlib)) &&
- (!Args.hasArg(options::OPT_shared))) {
+ (!Args.hasArg(options::OPT_shared))) {
CmdArgs.push_back("-e");
CmdArgs.push_back("__start");
}
@@ -2345,9 +2396,11 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- CmdArgs.push_back(MakeFormattedString(Args,
- llvm::format("-L/usr/lib/gcc-lib/%s/3.3.5",
- getToolChain().getTripleString().c_str())));
+ std::string Triple = getToolChain().getTripleString();
+ if (Triple.substr(0, 6) == "x86_64")
+ Triple.replace(0, 6, "amd64");
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple +
+ "/3.3.5"));
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
@@ -2547,10 +2600,10 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
// For now, DragonFly Assemble does just about the same as for
// FreeBSD, but this may change soon.
void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+ Job &Dest, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
ArgStringList CmdArgs;
// When building 32-bit code on DragonFly/pc64, we have to explicitly
@@ -2678,7 +2731,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_pthread))
- CmdArgs.push_back("-lthread_xu");
+ CmdArgs.push_back("-lpthread");
if (!Args.hasArg(options::OPT_nolibc)) {
CmdArgs.push_back("-lc");
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index eee8c19c2776..c616c6a5bf4b 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -9,6 +9,7 @@
#include "clang/Driver/Types.h"
+#include "llvm/ADT/StringSwitch.h"
#include <string.h>
#include <cassert>
@@ -102,51 +103,42 @@ bool types::isCXX(ID Id) {
}
types::ID types::lookupTypeForExtension(const char *Ext) {
- unsigned N = strlen(Ext);
-
- switch (N) {
- case 1:
- if (memcmp(Ext, "c", 1) == 0) return TY_C;
- if (memcmp(Ext, "i", 1) == 0) return TY_PP_C;
- if (memcmp(Ext, "m", 1) == 0) return TY_ObjC;
- if (memcmp(Ext, "M", 1) == 0) return TY_ObjCXX;
- if (memcmp(Ext, "h", 1) == 0) return TY_CHeader;
- if (memcmp(Ext, "C", 1) == 0) return TY_CXX;
- if (memcmp(Ext, "H", 1) == 0) return TY_CXXHeader;
- if (memcmp(Ext, "f", 1) == 0) return TY_PP_Fortran;
- if (memcmp(Ext, "F", 1) == 0) return TY_Fortran;
- if (memcmp(Ext, "s", 1) == 0) return TY_PP_Asm;
- if (memcmp(Ext, "S", 1) == 0) return TY_Asm;
- case 2:
- if (memcmp(Ext, "ii", 2) == 0) return TY_PP_CXX;
- if (memcmp(Ext, "mi", 2) == 0) return TY_PP_ObjC;
- if (memcmp(Ext, "mm", 2) == 0) return TY_ObjCXX;
- if (memcmp(Ext, "cc", 2) == 0) return TY_CXX;
- if (memcmp(Ext, "cc", 2) == 0) return TY_CXX;
- if (memcmp(Ext, "cp", 2) == 0) return TY_CXX;
- if (memcmp(Ext, "hh", 2) == 0) return TY_CXXHeader;
- break;
- case 3:
- if (memcmp(Ext, "ads", 3) == 0) return TY_Ada;
- if (memcmp(Ext, "adb", 3) == 0) return TY_Ada;
- if (memcmp(Ext, "ast", 3) == 0) return TY_AST;
- if (memcmp(Ext, "cxx", 3) == 0) return TY_CXX;
- if (memcmp(Ext, "cpp", 3) == 0) return TY_CXX;
- if (memcmp(Ext, "CPP", 3) == 0) return TY_CXX;
- if (memcmp(Ext, "cXX", 3) == 0) return TY_CXX;
- if (memcmp(Ext, "for", 3) == 0) return TY_PP_Fortran;
- if (memcmp(Ext, "FOR", 3) == 0) return TY_PP_Fortran;
- if (memcmp(Ext, "fpp", 3) == 0) return TY_Fortran;
- if (memcmp(Ext, "FPP", 3) == 0) return TY_Fortran;
- if (memcmp(Ext, "f90", 3) == 0) return TY_PP_Fortran;
- if (memcmp(Ext, "f95", 3) == 0) return TY_PP_Fortran;
- if (memcmp(Ext, "F90", 3) == 0) return TY_Fortran;
- if (memcmp(Ext, "F95", 3) == 0) return TY_Fortran;
- if (memcmp(Ext, "mii", 3) == 0) return TY_PP_ObjCXX;
- break;
- }
-
- return TY_INVALID;
+ return llvm::StringSwitch<types::ID>(Ext)
+ .Case("c", TY_C)
+ .Case("i", TY_PP_C)
+ .Case("m", TY_ObjC)
+ .Case("M", TY_ObjCXX)
+ .Case("h", TY_CHeader)
+ .Case("C", TY_CXX)
+ .Case("H", TY_CXXHeader)
+ .Case("f", TY_PP_Fortran)
+ .Case("F", TY_Fortran)
+ .Case("s", TY_PP_Asm)
+ .Case("S", TY_Asm)
+ .Case("ii", TY_PP_CXX)
+ .Case("mi", TY_PP_ObjC)
+ .Case("mm", TY_ObjCXX)
+ .Case("cc", TY_CXX)
+ .Case("CC", TY_CXX)
+ .Case("cp", TY_CXX)
+ .Case("hh", TY_CXXHeader)
+ .Case("ads", TY_Ada)
+ .Case("adb", TY_Ada)
+ .Case("ast", TY_AST)
+ .Case("cxx", TY_CXX)
+ .Case("cpp", TY_CXX)
+ .Case("CPP", TY_CXX)
+ .Case("CXX", TY_CXX)
+ .Case("for", TY_PP_Fortran)
+ .Case("FOR", TY_PP_Fortran)
+ .Case("fpp", TY_Fortran)
+ .Case("FPP", TY_Fortran)
+ .Case("f90", TY_PP_Fortran)
+ .Case("f95", TY_PP_Fortran)
+ .Case("F90", TY_Fortran)
+ .Case("F95", TY_Fortran)
+ .Case("mii", TY_PP_ObjCXX)
+ .Default(TY_INVALID);
}
types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 8d76680f6f92..9a30f59465f8 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -400,11 +400,6 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
Out << "<parameter> " << PVD->getNameAsString() << "\n";
break;
}
- case Decl::OriginalParmVar: {
- OriginalParmVarDecl* OPVD = cast<OriginalParmVarDecl>(*I);
- Out << "<original parameter> " << OPVD->getNameAsString() << "\n";
- break;
- }
case Decl::ObjCProperty: {
ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
Out << "<objc property> " << OPD->getNameAsString() << "\n";
@@ -457,6 +452,8 @@ class RecordLayoutDumper : public ASTConsumer {
// Dump (non-virtual) 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/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp
index 55f274005909..049f3bd3ea14 100644
--- a/lib/Frontend/AnalysisConsumer.cpp
+++ b/lib/Frontend/AnalysisConsumer.cpp
@@ -29,7 +29,6 @@
#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 25316bed9fb4..c0b4ebaab03b 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -241,11 +241,9 @@ bool getVisualStudioDir(std::string &path) {
return(false);
}
-void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
- const llvm::Triple &triple) {
+void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) {
// FIXME: temporary hack: hard-coded paths.
llvm::Triple::OSType os = triple.getOS();
-
switch (os) {
case llvm::Triple::Win32:
{
@@ -276,162 +274,186 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
}
}
break;
- case llvm::Triple::Cygwin:
- if (Lang.CPlusPlus) {
- AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include",
- System, false, false, false);
- AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include/c++",
- System, false, false, false);
- }
- AddPath("/usr/include", System, false, false, false);
- break;
case llvm::Triple::MinGW64:
- if (Lang.CPlusPlus) { // I'm guessing here.
- // Try gcc 4.4.0
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0");
- // Try gcc 4.3.0
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0");
- }
- // Fall through.
case llvm::Triple::MinGW32:
- if (Lang.CPlusPlus) {
- // Try gcc 4.4.0
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
- // Try gcc 4.3.0
- AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0");
- }
AddPath("c:/mingw/include", System, true, false, false);
break;
default:
- if (Lang.CPlusPlus) {
- switch (os) {
- case llvm::Triple::Darwin:
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
- "i686-apple-darwin10",
- "i686-apple-darwin10/x86_64",
- triple);
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
- "i686-apple-darwin8",
- "i686-apple-darwin8",
- triple);
- break;
- case llvm::Triple::Linux:
- // Ubuntu 7.10 - Gutsy Gibbon
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.3",
- "i486-linux-gnu",
- "i486-linux-gnu",
- triple);
- // Ubuntu 9.04
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.3",
- "x86_64-linux-gnu/32",
- "x86_64-linux-gnu",
- triple);
- // Fedora 8
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
- "i386-redhat-linux",
- "i386-redhat-linux",
- triple);
- // Fedora 9
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
- "i386-redhat-linux",
- "i386-redhat-linux",
- triple);
- // Fedora 10
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
- "i386-redhat-linux",
- "i386-redhat-linux",
- triple);
- // openSUSE 11.1 32 bit
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "i586-suse-linux",
- "i586-suse-linux",
- triple);
- // openSUSE 11.1 64 bit
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "x86_64-suse-linux/32",
- "x86_64-suse-linux",
- triple);
- // openSUSE 11.2
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
- "i586-suse-linux",
- "i586-suse-linux",
- triple);
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
- "x86_64-suse-linux",
- "x86_64-suse-linux",
- triple);
- // Arch Linux 2008-06-24
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
- "x86_64-unknown-linux-gnu",
- "x86_64-unknown-linux-gnu",
- triple);
- // Gentoo x86 2009.1 stable
- AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
- // Gentoo x86 2009.0 stable
- AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
- // Gentoo x86 2008.0 stable
- AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
- // Ubuntu 8.10
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "i486-pc-linux-gnu",
- "i486-pc-linux-gnu",
- triple);
- // Ubuntu 9.04
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "i486-linux-gnu",
- "i486-linux-gnu",
- triple);
- // Gentoo amd64 stable
- AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
- break;
- case llvm::Triple::FreeBSD:
- // DragonFly
- AddPath("/usr/include/c++/4.1", System, true, false, false);
- // FreeBSD
- AddPath("/usr/include/c++/4.2", System, true, false, false);
- break;
- case llvm::Triple::Solaris:
- // Solaris - Fall though..
- case llvm::Triple::AuroraUX:
- // AuroraUX
- AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
- "i386-pc-solaris2.11",
- "i386-pc-solaris2.11",
- triple);
- break;
- default:
- break;
- }
- }
break;
}
AddPath("/usr/local/include", System, false, false, false);
AddPath("/usr/include", System, false, false, false);
+}
+
+void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
+ llvm::Triple::OSType os = triple.getOS();
+ // FIXME: temporary hack: hard-coded paths.
+ switch (os) {
+ case llvm::Triple::Cygwin:
+ AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include",
+ System, true, false, false);
+ AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include/c++",
+ System, true, false, false);
+ break;
+ case llvm::Triple::MinGW64:
+ // Try gcc 4.4.0
+ AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0");
+ // Try gcc 4.3.0
+ AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0");
+ // Fall through.
+ case llvm::Triple::MinGW32:
+ // Try gcc 4.4.0
+ AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
+ // Try gcc 4.3.0
+ AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0");
+ break;
+ case llvm::Triple::Darwin:
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
+ "i686-apple-darwin10",
+ "i686-apple-darwin10/x86_64",
+ triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
+ "i686-apple-darwin8",
+ "i686-apple-darwin8",
+ triple);
+ break;
+ case llvm::Triple::Linux:
+ // Ubuntu 7.10 - Gutsy Gibbon
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.3",
+ "i486-linux-gnu",
+ "i486-linux-gnu",
+ triple);
+ // Ubuntu 9.04
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.3",
+ "x86_64-linux-gnu/32",
+ "x86_64-linux-gnu",
+ triple);
+ // Fedora 8
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
+ "i386-redhat-linux",
+ "i386-redhat-linux",
+ triple);
+ // Fedora 9
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
+ "i386-redhat-linux",
+ "i386-redhat-linux",
+ triple);
+ // Fedora 10
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
+ "i386-redhat-linux",
+ "i386-redhat-linux",
+ triple);
+ // openSUSE 11.1 32 bit
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "i586-suse-linux",
+ "i586-suse-linux",
+ triple);
+ // openSUSE 11.1 64 bit
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "x86_64-suse-linux/32",
+ "x86_64-suse-linux",
+ triple);
+ // openSUSE 11.2
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
+ "i586-suse-linux",
+ "i586-suse-linux",
+ triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
+ "x86_64-suse-linux",
+ "x86_64-suse-linux",
+ triple);
+ // Arch Linux 2008-06-24
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
+ "i686-pc-linux-gnu",
+ "i686-pc-linux-gnu",
+ triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
+ "x86_64-unknown-linux-gnu",
+ "x86_64-unknown-linux-gnu",
+ triple);
+ // Gentoo x86 2009.1 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
+ "i686-pc-linux-gnu",
+ "i686-pc-linux-gnu",
+ triple);
+ // Gentoo x86 2009.0 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
+ "i686-pc-linux-gnu",
+ "i686-pc-linux-gnu",
+ triple);
+ // Gentoo x86 2008.0 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
+ "i686-pc-linux-gnu",
+ "i686-pc-linux-gnu",
+ triple);
+ // Ubuntu 8.10
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "i486-pc-linux-gnu",
+ "i486-pc-linux-gnu",
+ triple);
+ // Ubuntu 9.04
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "i486-linux-gnu",
+ "i486-linux-gnu",
+ triple);
+ // Gentoo amd64 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
+ "i686-pc-linux-gnu",
+ "i686-pc-linux-gnu",
+ triple);
+ // Exherbo (2009-10-26)
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/include/c++/4.4.2",
+ "x86_64-pc-linux-gnu/32",
+ "x86_64-pc-linux-gnu",
+ triple);
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/include/c++/4.4.2",
+ "i686-pc-linux-gnu",
+ "i686-pc-linux-gnu",
+ triple);
+ break;
+ case llvm::Triple::FreeBSD:
+ // DragonFly
+ AddPath("/usr/include/c++/4.1", System, true, false, false);
+ // FreeBSD
+ AddPath("/usr/include/c++/4.2", System, true, false, false);
+ break;
+ case llvm::Triple::Solaris:
+ // Solaris - Fall though..
+ case llvm::Triple::AuroraUX:
+ // AuroraUX
+ AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
+ "i386-pc-solaris2.11",
+ "i386-pc-solaris2.11",
+ triple);
+ break;
+ default:
+ break;
+ }
+}
+
+void InitHeaderSearch::AddDefaultFrameworkIncludePaths(const llvm::Triple &triple) {
+ llvm::Triple::OSType os = triple.getOS();
+ if (os != llvm::Triple::Darwin)
+ return;
AddPath("/System/Library/Frameworks", System, true, false, true);
AddPath("/Library/Frameworks", System, true, false, true);
}
+void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
+ const llvm::Triple &triple) {
+ AddDefaultCIncludePaths(triple);
+ AddDefaultFrameworkIncludePaths(triple);
+ if (Lang.CPlusPlus)
+ AddDefaultCPlusPlusIncludePaths(triple);
+}
+
void InitHeaderSearch::AddDefaultEnvVarPaths(const LangOptions &Lang) {
AddEnvVarPaths("CPATH");
if (Lang.CPlusPlus && Lang.ObjC1)
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index b1a0a5ee8d51..ec5c1061bb93 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -17,8 +17,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/System/Path.h"
-
-namespace clang {
+using namespace clang;
// Append a #define line to Buf for Macro. Macro should be of the form XXX,
// in which case we emit "#define XXX 1" or "XXX=Y z W" in which case we emit
@@ -346,27 +345,15 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
assert(TI.getCharWidth() == 8 && "Only support 8-bit char so far");
DefineBuiltinMacro(Buf, "__CHAR_BIT__=8");
- unsigned IntMaxWidth;
- const char *IntMaxSuffix;
- if (TI.getIntMaxType() == TargetInfo::SignedLongLong) {
- IntMaxWidth = TI.getLongLongWidth();
- IntMaxSuffix = "LL";
- } else if (TI.getIntMaxType() == TargetInfo::SignedLong) {
- IntMaxWidth = TI.getLongWidth();
- IntMaxSuffix = "L";
- } else {
- assert(TI.getIntMaxType() == TargetInfo::SignedInt);
- IntMaxWidth = TI.getIntWidth();
- IntMaxSuffix = "";
- }
-
DefineTypeSize("__SCHAR_MAX__", TI.getCharWidth(), "", true, Buf);
DefineTypeSize("__SHRT_MAX__", TI.getShortWidth(), "", true, Buf);
DefineTypeSize("__INT_MAX__", TI.getIntWidth(), "", true, Buf);
DefineTypeSize("__LONG_MAX__", TI.getLongWidth(), "L", true, Buf);
DefineTypeSize("__LONG_LONG_MAX__", TI.getLongLongWidth(), "LL", true, Buf);
DefineTypeSize("__WCHAR_MAX__", TI.getWCharWidth(), "", true, Buf);
- DefineTypeSize("__INTMAX_MAX__", IntMaxWidth, IntMaxSuffix, true, Buf);
+ TargetInfo::IntType IntMaxType = TI.getIntMaxType();
+ DefineTypeSize("__INTMAX_MAX__", TI.getTypeWidth(IntMaxType),
+ TI.getTypeConstantSuffix(IntMaxType), true, Buf);
DefineType("__INTMAX_TYPE__", TI.getIntMaxType(), Buf);
DefineType("__UINTMAX_TYPE__", TI.getUIntMaxType(), Buf);
@@ -455,8 +442,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
/// InitializePreprocessor - Initialize the preprocessor getting it and the
/// environment ready to process a single file. This returns true on error.
///
-bool InitializePreprocessor(Preprocessor &PP,
- const PreprocessorInitOptions& InitOpts) {
+bool clang::InitializePreprocessor(Preprocessor &PP,
+ const PreprocessorInitOptions &InitOpts,
+ bool undef_macros) {
std::vector<char> PredefineBuffer;
const char *LineDirective = "# 1 \"<built-in>\" 3\n";
@@ -464,8 +452,9 @@ bool InitializePreprocessor(Preprocessor &PP,
LineDirective, LineDirective+strlen(LineDirective));
// Install things like __POWERPC__, __GNUC__, etc into the macro table.
- InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(),
- PredefineBuffer);
+ if (!undef_macros)
+ InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(),
+ PredefineBuffer);
// Add on the predefines from the driver. Wrap in a #line directive to report
// that they come from the command line.
@@ -504,5 +493,3 @@ bool InitializePreprocessor(Preprocessor &PP,
// Once we've read this, we're done.
return false;
}
-
-} // namespace clang
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 9c6059b1c7c0..26f426ba329b 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -32,6 +32,7 @@
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <iterator>
#include <cstdio>
@@ -2104,7 +2105,13 @@ void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
}
void TypeLocReader::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) {
- TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setTemplateNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+ TL.setArgLocInfo(i,
+ Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(i).getKind(),
+ Record, Idx));
}
void TypeLocReader::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -2197,6 +2204,25 @@ QualType PCHReader::GetType(pch::TypeID ID) {
return TypesLoaded[Index].withFastQualifiers(FastQuals);
}
+TemplateArgumentLocInfo
+PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
+ const RecordData &Record,
+ unsigned &Index) {
+ switch (Kind) {
+ case TemplateArgument::Expression:
+ return ReadDeclExpr();
+ case TemplateArgument::Type:
+ return GetDeclaratorInfo(Record, Index);
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Pack:
+ return TemplateArgumentLocInfo();
+ }
+ llvm::llvm_unreachable("unexpected template argument loc");
+ return TemplateArgumentLocInfo();
+}
+
Decl *PCHReader::GetDecl(pch::DeclID ID) {
if (ID == 0)
return 0;
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index d1cb461640b7..b9ece21f74c3 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -52,7 +52,6 @@ namespace {
void VisitVarDecl(VarDecl *VD);
void VisitImplicitParamDecl(ImplicitParamDecl *PD);
void VisitParmVarDecl(ParmVarDecl *PD);
- void VisitOriginalParmVarDecl(OriginalParmVarDecl *PD);
void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
void VisitBlockDecl(BlockDecl *BD);
std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
@@ -107,9 +106,9 @@ void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
// set the underlying type of the typedef *before* we try to read
// the type associated with the TypedefDecl.
VisitNamedDecl(TD);
- TD->setUnderlyingType(Reader.GetType(Record[Idx + 1]));
- TD->setTypeForDecl(Reader.GetType(Record[Idx]).getTypePtr());
- Idx += 2;
+ uint64_t TypeData = Record[Idx++];
+ TD->setTypeDeclaratorInfo(Reader.GetDeclaratorInfo(Record, Idx));
+ TD->setTypeForDecl(Reader.GetType(TypeData).getTypePtr());
}
void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
@@ -163,7 +162,7 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->setPreviousDeclaration(
cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
- FD->setInline(Record[Idx++]);
+ FD->setInlineSpecified(Record[Idx++]);
FD->setVirtualAsWritten(Record[Idx++]);
FD->setPure(Record[Idx++]);
FD->setHasInheritedPrototype(Record[Idx++]);
@@ -370,11 +369,6 @@ void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
}
-void PCHDeclReader::VisitOriginalParmVarDecl(OriginalParmVarDecl *PD) {
- VisitParmVarDecl(PD);
- PD->setOriginalType(Reader.GetType(Record[Idx++]));
-}
-
void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
VisitDecl(AD);
AD->setAsmString(cast<StringLiteral>(Reader.ReadDeclExpr()));
@@ -618,7 +612,7 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
D = Context->getTranslationUnitDecl();
break;
case pch::DECL_TYPEDEF:
- D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, QualType());
+ D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, 0);
break;
case pch::DECL_ENUM:
D = EnumDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(), 0);
@@ -696,10 +690,6 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
VarDecl::None, 0);
break;
- case pch::DECL_ORIGINAL_PARM_VAR:
- D = OriginalParmVarDecl::Create(*Context, 0, SourceLocation(), 0,
- QualType(),0, QualType(), VarDecl::None, 0);
- break;
case pch::DECL_FILE_SCOPE_ASM:
D = FileScopeAsmDecl::Create(*Context, 0, SourceLocation(), 0);
break;
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp
index 4b9496e00f8b..01af67dd50a1 100644
--- a/lib/Frontend/PCHReaderStmt.cpp
+++ b/lib/Frontend/PCHReaderStmt.cpp
@@ -347,6 +347,8 @@ unsigned PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
VisitExpr(E);
E->setDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ // FIXME: read qualifier
+ // FIXME: read explicit template arguments
return 0;
}
@@ -422,7 +424,7 @@ unsigned PCHStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
E->setArgument(cast<Expr>(StmtStack.back()));
++Idx;
} else {
- E->setArgument(Reader.GetType(Record[Idx++]));
+ E->setArgument(Reader.GetDeclaratorInfo(Record, Idx));
}
E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index fb48df332121..de56166125ed 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -368,7 +368,11 @@ void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc(
}
void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) {
- Writer.AddSourceLocation(TL.getNameLoc(), Record);
+ Writer.AddSourceLocation(TL.getTemplateNameLoc(), Record);
+ Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
+ Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+ Writer.AddTemplateArgumentLoc(TL.getArgLoc(i), Record);
}
void TypeLocWriter::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
Writer.AddSourceLocation(TL.getNameLoc(), Record);
@@ -589,7 +593,6 @@ void PCHWriter::WriteBlockInfoBlock() {
RECORD(DECL_VAR);
RECORD(DECL_IMPLICIT_PARAM);
RECORD(DECL_PARM_VAR);
- RECORD(DECL_ORIGINAL_PARM_VAR);
RECORD(DECL_FILE_SCOPE_ASM);
RECORD(DECL_BLOCK);
RECORD(DECL_CONTEXT_LEXICAL);
@@ -2106,6 +2109,23 @@ void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {
Record.push_back(SID);
}
+void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
+ RecordData &Record) {
+ switch (Arg.getArgument().getKind()) {
+ case TemplateArgument::Expression:
+ AddStmt(Arg.getLocInfo().getAsExpr());
+ break;
+ case TemplateArgument::Type:
+ AddDeclaratorInfo(Arg.getLocInfo().getAsDeclaratorInfo(), Record);
+ break;
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Pack:
+ break;
+ }
+}
+
void PCHWriter::AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record) {
if (DInfo == 0) {
AddTypeRef(QualType(), Record);
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index fbd9929e49d7..8997e661a5a1 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -55,7 +55,6 @@ namespace {
void VisitVarDecl(VarDecl *D);
void VisitImplicitParamDecl(ImplicitParamDecl *D);
void VisitParmVarDecl(ParmVarDecl *D);
- void VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
void VisitBlockDecl(BlockDecl *D);
void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
@@ -107,7 +106,7 @@ void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
VisitTypeDecl(D);
- Writer.AddTypeRef(D->getUnderlyingType(), Record);
+ Writer.AddDeclaratorInfo(D->getTypeDeclaratorInfo(), Record);
Code = pch::DECL_TYPEDEF;
}
@@ -162,7 +161,7 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Writer.AddStmt(D->getBody());
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
Record.push_back(D->getStorageClass()); // FIXME: stable encoding
- Record.push_back(D->isInline());
+ Record.push_back(D->isInlineSpecified());
Record.push_back(D->isVirtualAsWritten());
Record.push_back(D->isPure());
Record.push_back(D->hasInheritedPrototype());
@@ -390,13 +389,6 @@ void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
assert(D->getInit() == 0 && "PARM_VAR_DECL never has init");
}
-void PCHDeclWriter::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) {
- VisitParmVarDecl(D);
- Writer.AddTypeRef(D->getOriginalType(), Record);
- Code = pch::DECL_ORIGINAL_PARM_VAR;
- AbbrevToUse = 0;
-}
-
void PCHDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
VisitDecl(D);
Writer.AddStmt(D->getAsmString());
diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp
index 9497f973f6bc..78a56db7edcd 100644
--- a/lib/Frontend/PCHWriterStmt.cpp
+++ b/lib/Frontend/PCHWriterStmt.cpp
@@ -314,6 +314,8 @@ void PCHStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
VisitExpr(E);
Writer.AddDeclRef(E->getDecl(), Record);
Writer.AddSourceLocation(E->getLocation(), Record);
+ // FIXME: write qualifier
+ // FIXME: write explicit template arguments
Code = pch::EXPR_DECL_REF;
}
@@ -382,7 +384,7 @@ void PCHStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
VisitExpr(E);
Record.push_back(E->isSizeOf());
if (E->isArgumentType())
- Writer.AddTypeRef(E->getArgumentType(), Record);
+ Writer.AddDeclaratorInfo(E->getArgumentTypeInfo(), Record);
else {
Record.push_back(0);
Writer.WriteSubStmt(E->getArgumentExpr());
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index f3cb20619ed5..630a093a4bf6 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -66,7 +66,7 @@ static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI,
OS << ' ';
// Make sure we have enough space in the spelling buffer.
- if (I->getLength() < SpellingBuffer.size())
+ if (I->getLength() > SpellingBuffer.size())
SpellingBuffer.resize(I->getLength());
const char *Buffer = SpellingBuffer.data();
unsigned SpellingLen = PP.getSpelling(*I, Buffer);
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index 0ea0a58d5239..24ad69e3e0d3 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -2569,7 +2569,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
// Build sizeof(returnType)
SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true,
- returnType,
+ Context->getTrivialDeclaratorInfo(returnType),
Context->getSizeType(),
SourceLocation(), SourceLocation());
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
@@ -2609,10 +2609,12 @@ Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
// typedef struct objc_object Protocol;
QualType RewriteObjC::getProtocolType() {
if (!ProtocolTypeDecl) {
+ DeclaratorInfo *DInfo
+ = Context->getTrivialDeclaratorInfo(Context->getObjCIdType());
ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
SourceLocation(),
&Context->Idents.get("Protocol"),
- Context->getObjCIdType());
+ DInfo);
}
return Context->getTypeDeclType(ProtocolTypeDecl);
}
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 14769c187393..b1d8800369e5 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -13,6 +13,7 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Lex/Lexer.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
@@ -37,6 +38,12 @@ static const enum llvm::raw_ostream::Colors savedColor =
/// \brief Number of spaces to indent when word-wrapping.
const unsigned WordWrapIndentation = 6;
+TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::raw_ostream &os,
+ const DiagnosticOptions &diags)
+ : OS(os), LangOpts(0), DiagOpts(&diags),
+ LastCaretDiagnosticWasNote(false) {
+}
+
void TextDiagnosticPrinter::
PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) {
if (Loc.isInvalid()) return;
@@ -46,7 +53,7 @@ PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) {
// Print out the other include frames first.
PrintIncludeStack(PLoc.getIncludeLoc(), SM);
- if (ShowLocation)
+ if (DiagOpts->ShowLocation)
OS << "In file included from " << PLoc.getFilename()
<< ':' << PLoc.getLine() << ":\n";
else
@@ -281,13 +288,13 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
Ranges[i] = SourceRange(S, E);
}
- if (ShowLocation) {
+ if (DiagOpts->ShowLocation) {
std::pair<FileID, unsigned> IInfo = SM.getDecomposedInstantiationLoc(Loc);
// Emit the file/line/column that this expansion came from.
OS << SM.getBuffer(IInfo.first)->getBufferIdentifier() << ':'
<< SM.getLineNumber(IInfo.first, IInfo.second) << ':';
- if (ShowColumn)
+ if (DiagOpts->ShowColumn)
OS << SM.getColumnNumber(IInfo.first, IInfo.second) << ':';
OS << ' ';
}
@@ -370,13 +377,13 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
// produce easily machine parsable output. Add a space before the source line
// and the caret to make it trivial to tell the main diagnostic line from what
// the user is intended to see.
- if (PrintRangeInfo) {
+ if (DiagOpts->ShowSourceRanges) {
SourceLine = ' ' + SourceLine;
CaretLine = ' ' + CaretLine;
}
std::string FixItInsertionLine;
- if (NumHints && PrintFixItInfo) {
+ if (NumHints && DiagOpts->ShowFixits) {
for (const CodeModificationHint *Hint = Hints, *LastHint = Hints + NumHints;
Hint != LastHint; ++Hint) {
if (Hint->InsertionLoc.isValid()) {
@@ -417,20 +424,20 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
// Emit what we have computed.
OS << SourceLine << '\n';
- if (UseColors)
+ if (DiagOpts->ShowColors)
OS.changeColor(caretColor, true);
OS << CaretLine << '\n';
- if (UseColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
if (!FixItInsertionLine.empty()) {
- if (UseColors)
+ if (DiagOpts->ShowColors)
// Print fixit line in color
OS.changeColor(fixitColor, false);
- if (PrintRangeInfo)
+ if (DiagOpts->ShowSourceRanges)
OS << ' ';
OS << FixItInsertionLine << '\n';
- if (UseColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
}
}
@@ -627,15 +634,15 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
}
// Compute the column number.
- if (ShowLocation) {
- if (UseColors)
+ if (DiagOpts->ShowLocation) {
+ if (DiagOpts->ShowColors)
OS.changeColor(savedColor, true);
OS << PLoc.getFilename() << ':' << LineNo << ':';
- if (ShowColumn)
+ if (DiagOpts->ShowColumn)
if (unsigned ColNo = PLoc.getColumn())
OS << ColNo << ':';
- if (PrintRangeInfo && Info.getNumRanges()) {
+ if (DiagOpts->ShowSourceRanges && Info.getNumRanges()) {
FileID CaretFileID =
SM.getFileID(SM.getInstantiationLoc(Info.getLocation()));
bool PrintedRange = false;
@@ -679,12 +686,12 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
OS << ':';
}
OS << ' ';
- if (UseColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
}
}
- if (UseColors) {
+ if (DiagOpts->ShowColors) {
// Print diagnostic category in bold and color
switch (Level) {
case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
@@ -703,20 +710,20 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
case Diagnostic::Fatal: OS << "fatal error: "; break;
}
- if (UseColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
llvm::SmallString<100> OutStr;
Info.FormatDiagnostic(OutStr);
- if (PrintDiagnosticOption)
+ if (DiagOpts->ShowOptionNames)
if (const char *Opt = Diagnostic::getWarningOptionForDiag(Info.getID())) {
OutStr += " [-W";
OutStr += Opt;
OutStr += ']';
}
- if (UseColors) {
+ if (DiagOpts->ShowColors) {
// Print warnings, errors and fatal errors in bold, no color
switch (Level) {
case Diagnostic::Warning: OS.changeColor(savedColor, true); break;
@@ -726,17 +733,17 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
}
}
- if (MessageLength) {
+ if (DiagOpts->MessageLength) {
// We will be word-wrapping the error message, so compute the
// column number where we currently are (after printing the
// location information).
unsigned Column = OS.tell() - StartOfLocationInfo;
- PrintWordWrapped(OS, OutStr, MessageLength, Column);
+ PrintWordWrapped(OS, OutStr, DiagOpts->MessageLength, Column);
} else {
OS.write(OutStr.begin(), OutStr.size());
}
OS << '\n';
- if (UseColors)
+ if (DiagOpts->ShowColors)
OS.resetColor();
// If caret diagnostics are enabled and we have location, we want to
@@ -745,7 +752,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
// was part of a different warning or error diagnostic, or if the
// diagnostic has ranges. We don't want to emit the same caret
// multiple times if one loc has multiple diagnostics.
- if (CaretDiagnostics && Info.getLocation().isValid() &&
+ if (DiagOpts->ShowCarets && Info.getLocation().isValid() &&
((LastLoc != Info.getLocation()) || Info.getNumRanges() ||
(LastCaretDiagnosticWasNote && Level != Diagnostic::Note) ||
Info.getNumCodeModificationHints())) {
@@ -772,7 +779,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager(),
Info.getCodeModificationHints(),
Info.getNumCodeModificationHints(),
- MessageLength);
+ DiagOpts->MessageLength);
}
OS.flush();
diff --git a/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt
index 6c874f4b7bb5..e63291b2af90 100644
--- a/lib/Headers/CMakeLists.txt
+++ b/lib/Headers/CMakeLists.txt
@@ -35,4 +35,4 @@ add_custom_target(clang-headers ALL
install(FILES ${files}
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
- DESTINATION lib/clang/${CLANG_VERSION}/include)
+ DESTINATION lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/include)
diff --git a/lib/Headers/stdint.h b/lib/Headers/stdint.h
index a7020d838ec9..f79a0f4af557 100644
--- a/lib/Headers/stdint.h
+++ b/lib/Headers/stdint.h
@@ -28,7 +28,8 @@
/* If we're hosted, fall back to the system's stdint.h, which might have
* additional definitions.
*/
-#if __STDC_HOSTED__
+#if __STDC_HOSTED__ && \
+ defined(__has_include_next) && __has_include_next(<stdint.h>)
# include_next <stdint.h>
#else
diff --git a/lib/Index/ResolveLocation.cpp b/lib/Index/ResolveLocation.cpp
index 8edd634f8af4..73b584b5205d 100644
--- a/lib/Index/ResolveLocation.cpp
+++ b/lib/Index/ResolveLocation.cpp
@@ -45,6 +45,9 @@ protected:
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
if (ContainsLocation(DD->getDeclaratorInfo()))
return ContainsLoc;
+ if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
+ if (ContainsLocation(TD->getTypeDeclaratorInfo()))
+ return ContainsLoc;
return CheckRange(D->getSourceRange());
}
@@ -57,11 +60,6 @@ protected:
}
template <typename T>
- bool ContainsLocation(T Node) {
- return CheckRange(Node) == ContainsLoc;
- }
-
- template <typename T>
bool isAfterLocation(T Node) {
return CheckRange(Node) == AfterLoc;
}
@@ -69,6 +67,11 @@ protected:
public:
LocResolverBase(ASTContext &ctx, SourceLocation loc)
: Ctx(ctx), Loc(loc) {}
+
+ template <typename T>
+ bool ContainsLocation(T Node) {
+ return CheckRange(Node) == ContainsLoc;
+ }
#ifndef NDEBUG
/// \brief Debugging output.
@@ -89,6 +92,7 @@ public:
StmtLocResolver(ASTContext &ctx, SourceLocation loc, Decl *parent)
: LocResolverBase(ctx, loc), Parent(parent) {}
+ ASTLocation VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
ASTLocation VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node);
ASTLocation VisitDeclStmt(DeclStmt *Node);
ASTLocation VisitStmt(Stmt *Node);
@@ -109,6 +113,7 @@ public:
ASTLocation VisitVarDecl(VarDecl *D);
ASTLocation VisitFunctionDecl(FunctionDecl *D);
ASTLocation VisitObjCMethodDecl(ObjCMethodDecl *D);
+ ASTLocation VisitTypedefDecl(TypedefDecl *D);
ASTLocation VisitDecl(Decl *D);
};
@@ -132,6 +137,25 @@ public:
} // anonymous namespace
ASTLocation
+StmtLocResolver::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
+ assert(ContainsLocation(Node) &&
+ "Should visit only after verifying that loc is in range");
+
+ if (Node->isArgumentType()) {
+ DeclaratorInfo *DInfo = Node->getArgumentTypeInfo();
+ if (ContainsLocation(DInfo))
+ return ResolveInDeclarator(Parent, Node, DInfo);
+ } else {
+ Expr *SubNode = Node->getArgumentExpr();
+ if (ContainsLocation(SubNode))
+ return Visit(SubNode);
+ }
+
+ return ASTLocation(Parent, Node);
+}
+
+
+ASTLocation
StmtLocResolver::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
assert(ContainsLocation(Node) &&
"Should visit only after verifying that loc is in range");
@@ -278,6 +302,16 @@ ASTLocation DeclLocResolver::VisitDeclaratorDecl(DeclaratorDecl *D) {
return ASTLocation(D);
}
+ASTLocation DeclLocResolver::VisitTypedefDecl(TypedefDecl *D) {
+ assert(ContainsLocation(D) &&
+ "Should visit only after verifying that loc is in range");
+
+ if (ContainsLocation(D->getTypeDeclaratorInfo()))
+ return ResolveInDeclarator(D, /*Stmt=*/0, D->getTypeDeclaratorInfo());
+
+ return ASTLocation(D);
+}
+
ASTLocation DeclLocResolver::VisitVarDecl(VarDecl *D) {
assert(ContainsLocation(D) &&
"Should visit only after verifying that loc is in range");
@@ -529,11 +563,40 @@ void LocResolverBase::print(Stmt *Node) {
/// \brief Returns the AST node that a source location points to.
///
ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
- Decl *RelativeToDecl) {
+ ASTLocation *LastLoc) {
if (Loc.isInvalid())
return ASTLocation();
- if (RelativeToDecl)
- return DeclLocResolver(Ctx, Loc).Visit(RelativeToDecl);
+ if (LastLoc && LastLoc->isValid()) {
+ DeclContext *DC = 0;
+
+ if (Decl *Dcl = LastLoc->dyn_AsDecl()) {
+ DC = Dcl->getDeclContext();
+ } else if (LastLoc->isStmt()) {
+ Decl *Parent = LastLoc->getParentDecl();
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Parent))
+ DC = FD;
+ else {
+ // This is needed to handle statements within an initializer.
+ // Example:
+ // void func() { long double fabsf = __builtin_fabsl(__x); }
+ // In this case, the 'parent' of __builtin_fabsl is fabsf.
+ DC = Parent->getDeclContext();
+ }
+ } else { // We have 'N_NamedRef' or 'N_Type'
+ DC = LastLoc->getParentDecl()->getDeclContext();
+ }
+ assert(DC && "Missing DeclContext");
+
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(DC);
+ DeclLocResolver DLocResolver(Ctx, Loc);
+
+ if (FD && FD->isThisDeclarationADefinition() &&
+ DLocResolver.ContainsLocation(FD)) {
+ return DLocResolver.VisitFunctionDecl(FD);
+ }
+ // Fall through and try the slow path...
+ // FIXME: Optimize more cases.
+ }
return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl());
}
diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp
index c9a10dc02707..df712760bb25 100644
--- a/lib/Lex/HeaderMap.cpp
+++ b/lib/Lex/HeaderMap.cpp
@@ -15,7 +15,7 @@
#include "clang/Basic/FileManager.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cstdio>
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index e264efab9d7b..dc7d95e70118 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -974,11 +974,11 @@ bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc,
/// This code concatenates and consumes tokens up to the '>' token. It returns
/// false if the > was found, otherwise it returns true if it finds and consumes
/// the EOM marker.
-static bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer,
- Preprocessor &PP) {
+bool Preprocessor::ConcatenateIncludeName(
+ llvm::SmallVector<char, 128> &FilenameBuffer) {
Token CurTok;
- PP.Lex(CurTok);
+ Lex(CurTok);
while (CurTok.isNot(tok::eom)) {
// Append the spelling of this token to the buffer. If there was a space
// before it, add it now.
@@ -990,7 +990,7 @@ static bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer,
FilenameBuffer.resize(PreAppendSize+CurTok.getLength());
const char *BufPtr = &FilenameBuffer[PreAppendSize];
- unsigned ActualLen = PP.getSpelling(CurTok, BufPtr);
+ unsigned ActualLen = getSpelling(CurTok, BufPtr);
// If the token was spelled somewhere else, copy it into FilenameBuffer.
if (BufPtr != &FilenameBuffer[PreAppendSize])
@@ -1004,12 +1004,12 @@ static bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer,
if (CurTok.is(tok::greater))
return false;
- PP.Lex(CurTok);
+ Lex(CurTok);
}
// If we hit the eom marker, emit an error and return true so that the caller
// knows the EOM has been read.
- PP.Diag(CurTok.getLocation(), diag::err_pp_expects_filename);
+ Diag(CurTok.getLocation(), diag::err_pp_expects_filename);
return true;
}
@@ -1047,7 +1047,7 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok,
// This could be a <foo/bar.h> file coming from a macro expansion. In this
// case, glue the tokens together into FilenameBuffer and interpret those.
FilenameBuffer.push_back('<');
- if (ConcatenateIncludeName(FilenameBuffer, *this))
+ if (ConcatenateIncludeName(FilenameBuffer))
return; // Found <eom> but no ">"? Diagnostic already emitted.
FilenameStart = FilenameBuffer.data();
FilenameEnd = FilenameStart + FilenameBuffer.size();
diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp
index 908385c5d392..a74396c3146c 100644
--- a/lib/Lex/PPExpressions.cpp
+++ b/lib/Lex/PPExpressions.cpp
@@ -71,6 +71,61 @@ struct DefinedTracker {
IdentifierInfo *TheMacro;
};
+/// EvaluateDefined - Process a 'defined(sym)' expression.
+static bool EvaluateDefined(PPValue &Result, Token &PeekTok,
+ DefinedTracker &DT, bool ValueLive, Preprocessor &PP) {
+ IdentifierInfo *II;
+ Result.setBegin(PeekTok.getLocation());
+
+ // Get the next token, don't expand it.
+ PP.LexUnexpandedToken(PeekTok);
+
+ // Two options, it can either be a pp-identifier or a (.
+ SourceLocation LParenLoc;
+ if (PeekTok.is(tok::l_paren)) {
+ // Found a paren, remember we saw it and skip it.
+ LParenLoc = PeekTok.getLocation();
+ PP.LexUnexpandedToken(PeekTok);
+ }
+
+ // If we don't have a pp-identifier now, this is an error.
+ if ((II = PeekTok.getIdentifierInfo()) == 0) {
+ PP.Diag(PeekTok, diag::err_pp_defined_requires_identifier);
+ return true;
+ }
+
+ // Otherwise, we got an identifier, is it defined to something?
+ Result.Val = II->hasMacroDefinition();
+ Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
+
+ // If there is a macro, mark it used.
+ if (Result.Val != 0 && ValueLive) {
+ MacroInfo *Macro = PP.getMacroInfo(II);
+ Macro->setIsUsed(true);
+ }
+
+ // Consume identifier.
+ Result.setEnd(PeekTok.getLocation());
+ PP.LexNonComment(PeekTok);
+
+ // If we are in parens, ensure we have a trailing ).
+ if (LParenLoc.isValid()) {
+ if (PeekTok.isNot(tok::r_paren)) {
+ PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen) << "defined";
+ PP.Diag(LParenLoc, diag::note_matching) << "(";
+ return true;
+ }
+ // Consume the ).
+ Result.setEnd(PeekTok.getLocation());
+ PP.LexNonComment(PeekTok);
+ }
+
+ // Success, remember that we saw defined(X).
+ DT.State = DefinedTracker::DefinedMacro;
+ DT.TheMacro = II;
+ return false;
+}
+
/// EvaluateValue - Evaluate the token PeekTok (and any others needed) and
/// return the computed value in Result. Return true if there was an error
/// parsing. This function also returns information about the form of the
@@ -87,10 +142,14 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
// 'defined' or if it is a macro. Note that we check here because many
// keywords are pp-identifiers, so we can't check the kind.
if (IdentifierInfo *II = PeekTok.getIdentifierInfo()) {
- // If this identifier isn't 'defined' and it wasn't macro expanded, it turns
- // into a simple 0, unless it is the C++ keyword "true", in which case it
- // turns into "1".
- if (!II->isStr("defined")) {
+ if (II->isStr("defined")) {
+ // Handle "defined X" and "defined(X)".
+ return(EvaluateDefined(Result, PeekTok, DT, ValueLive, PP));
+ } else {
+ // If this identifier isn't 'defined' or one of the special
+ // preprocessor keywords and it wasn't macro expanded, it turns
+ // into a simple 0, unless it is the C++ keyword "true", in which case it
+ // turns into "1".
if (ValueLive)
PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II;
Result.Val = II->getTokenID() == tok::kw_true;
@@ -99,57 +158,6 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
PP.LexNonComment(PeekTok);
return false;
}
-
- // Handle "defined X" and "defined(X)".
- Result.setBegin(PeekTok.getLocation());
-
- // Get the next token, don't expand it.
- PP.LexUnexpandedToken(PeekTok);
-
- // Two options, it can either be a pp-identifier or a (.
- SourceLocation LParenLoc;
- if (PeekTok.is(tok::l_paren)) {
- // Found a paren, remember we saw it and skip it.
- LParenLoc = PeekTok.getLocation();
- PP.LexUnexpandedToken(PeekTok);
- }
-
- // If we don't have a pp-identifier now, this is an error.
- if ((II = PeekTok.getIdentifierInfo()) == 0) {
- PP.Diag(PeekTok, diag::err_pp_defined_requires_identifier);
- return true;
- }
-
- // Otherwise, we got an identifier, is it defined to something?
- Result.Val = II->hasMacroDefinition();
- Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
-
- // If there is a macro, mark it used.
- if (Result.Val != 0 && ValueLive) {
- MacroInfo *Macro = PP.getMacroInfo(II);
- Macro->setIsUsed(true);
- }
-
- // Consume identifier.
- Result.setEnd(PeekTok.getLocation());
- PP.LexNonComment(PeekTok);
-
- // If we are in parens, ensure we have a trailing ).
- if (LParenLoc.isValid()) {
- if (PeekTok.isNot(tok::r_paren)) {
- PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen);
- PP.Diag(LParenLoc, diag::note_matching) << "(";
- return true;
- }
- // Consume the ).
- Result.setEnd(PeekTok.getLocation());
- PP.LexNonComment(PeekTok);
- }
-
- // Success, remember that we saw defined(X).
- DT.State = DefinedTracker::DefinedMacro;
- DT.TheMacro = II;
- return false;
}
switch (PeekTok.getKind()) {
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 7ddf215020d0..699b701ea870 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -64,8 +64,10 @@ void Preprocessor::RegisterBuiltinMacros() {
Ident__TIMESTAMP__ = RegisterBuiltinMacro(*this, "__TIMESTAMP__");
// Clang Extensions.
- Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
- Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
+ Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
+ Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
+ Ident__has_include = RegisterBuiltinMacro(*this, "__has_include");
+ Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
}
/// isTrivialSingleTokenExpansion - Return true if MI, which has a single token
@@ -503,6 +505,117 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
}
}
+/// EvaluateHasIncludeCommon - Process a '__has_include("path")'
+/// or '__has_include_next("path")' expression.
+/// Returns true if successful.
+static bool EvaluateHasIncludeCommon(bool &Result, Token &Tok,
+ IdentifierInfo *II, Preprocessor &PP,
+ const DirectoryLookup *LookupFrom) {
+ SourceLocation LParenLoc;
+
+ // Get '('.
+ PP.LexNonComment(Tok);
+
+ // Ensure we have a '('.
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_pp_missing_lparen) << II->getName();
+ return false;
+ }
+
+ // Save '(' location for possible missing ')' message.
+ LParenLoc = Tok.getLocation();
+
+ // Get the file name.
+ PP.getCurrentLexer()->LexIncludeFilename(Tok);
+
+ // Reserve a buffer to get the spelling.
+ llvm::SmallVector<char, 128> FilenameBuffer;
+ const char *FilenameStart, *FilenameEnd;
+
+ switch (Tok.getKind()) {
+ case tok::eom:
+ // If the token kind is EOM, the error has already been diagnosed.
+ return false;
+
+ case tok::angle_string_literal:
+ case tok::string_literal: {
+ FilenameBuffer.resize(Tok.getLength());
+ FilenameStart = &FilenameBuffer[0];
+ unsigned Len = PP.getSpelling(Tok, FilenameStart);
+ FilenameEnd = FilenameStart+Len;
+ break;
+ }
+
+ case tok::less:
+ // This could be a <foo/bar.h> file coming from a macro expansion. In this
+ // case, glue the tokens together into FilenameBuffer and interpret those.
+ FilenameBuffer.push_back('<');
+ if (PP.ConcatenateIncludeName(FilenameBuffer))
+ return false; // Found <eom> but no ">"? Diagnostic already emitted.
+ FilenameStart = FilenameBuffer.data();
+ FilenameEnd = FilenameStart + FilenameBuffer.size();
+ break;
+ default:
+ PP.Diag(Tok.getLocation(), diag::err_pp_expects_filename);
+ return false;
+ }
+
+ bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(),
+ FilenameStart, FilenameEnd);
+ // If GetIncludeFilenameSpelling set the start ptr to null, there was an
+ // error.
+ if (FilenameStart == 0) {
+ return false;
+ }
+
+ // Search include directories.
+ const DirectoryLookup *CurDir;
+ const FileEntry *File = PP.LookupFile(FilenameStart, FilenameEnd,
+ isAngled, LookupFrom, CurDir);
+
+ // Get the result value. Result = true means the file exists.
+ Result = File != 0;
+
+ // Get ')'.
+ PP.LexNonComment(Tok);
+
+ // Ensure we have a trailing ).
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_pp_missing_rparen) << II->getName();
+ PP.Diag(LParenLoc, diag::note_matching) << "(";
+ return false;
+ }
+
+ return true;
+}
+
+/// EvaluateHasInclude - Process a '__has_include("path")' expression.
+/// Returns true if successful.
+static bool EvaluateHasInclude(bool &Result, Token &Tok, IdentifierInfo *II,
+ Preprocessor &PP) {
+ return(EvaluateHasIncludeCommon(Result, Tok, II, PP, NULL));
+}
+
+/// EvaluateHasIncludeNext - Process '__has_include_next("path")' expression.
+/// Returns true if successful.
+static bool EvaluateHasIncludeNext(bool &Result, Token &Tok,
+ IdentifierInfo *II, Preprocessor &PP) {
+ // __has_include_next is like __has_include, except that we start
+ // searching after the current found directory. If we can't do this,
+ // issue a diagnostic.
+ const DirectoryLookup *Lookup = PP.GetCurDirLookup();
+ if (PP.isInPrimaryFile()) {
+ Lookup = 0;
+ PP.Diag(Tok, diag::pp_include_next_in_primary);
+ } else if (Lookup == 0) {
+ PP.Diag(Tok, diag::pp_include_next_absolute_path);
+ } else {
+ // Start looking up in the next directory.
+ ++Lookup;
+ }
+
+ return(EvaluateHasIncludeCommon(Result, Tok, II, PP, Lookup));
+}
/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
/// as a builtin macro, handle it and return the next token as 'Tok'.
@@ -671,6 +784,20 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
sprintf(TmpBuffer, "%d", (int)Value);
Tok.setKind(tok::numeric_constant);
CreateString(TmpBuffer, strlen(TmpBuffer), Tok, Tok.getLocation());
+ } else if (II == Ident__has_include ||
+ II == Ident__has_include_next) {
+ // The argument to these two builtins should be a parenthesized
+ // file name string literal using angle brackets (<>) or
+ // double-quotes ("").
+ bool Value = false;
+ bool IsValid;
+ if (II == Ident__has_include)
+ IsValid = EvaluateHasInclude(Value, Tok, II, *this);
+ else
+ IsValid = EvaluateHasIncludeNext(Value, Tok, II, *this);
+ sprintf(TmpBuffer, "%d", (int)Value);
+ Tok.setKind(tok::numeric_constant);
+ CreateString(TmpBuffer, strlen(TmpBuffer), Tok, Tok.getLocation());
} else {
assert(0 && "Unknown identifier!");
}
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index 224a31cd5a5e..344ce9e90e55 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -13,6 +13,7 @@
#include "clang/Parse/AttributeList.h"
#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/StringSwitch.h"
using namespace clang;
AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
@@ -52,94 +53,58 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
AttrName = AttrName.substr(2, AttrName.size() - 4);
// FIXME: Hand generating this is neither smart nor efficient.
- const char *Str = AttrName.data();
- switch (AttrName.size()) {
- case 4:
- if (!memcmp(Str, "weak", 4)) return AT_weak;
- if (!memcmp(Str, "pure", 4)) return AT_pure;
- if (!memcmp(Str, "mode", 4)) return AT_mode;
- if (!memcmp(Str, "used", 4)) return AT_used;
- break;
- case 5:
- if (!memcmp(Str, "alias", 5)) return AT_alias;
- if (!memcmp(Str, "const", 5)) return AT_const;
- break;
- case 6:
- if (!memcmp(Str, "packed", 6)) return AT_packed;
- if (!memcmp(Str, "malloc", 6)) return AT_malloc;
- if (!memcmp(Str, "format", 6)) return AT_format;
- if (!memcmp(Str, "unused", 6)) return AT_unused;
- if (!memcmp(Str, "blocks", 6)) return AT_blocks;
- break;
- case 7:
- if (!memcmp(Str, "aligned", 7)) return AT_aligned;
- if (!memcmp(Str, "cleanup", 7)) return AT_cleanup;
- if (!memcmp(Str, "nodebug", 7)) return AT_nodebug;
- if (!memcmp(Str, "nonnull", 7)) return AT_nonnull;
- if (!memcmp(Str, "nothrow", 7)) return AT_nothrow;
- if (!memcmp(Str, "objc_gc", 7)) return AT_objc_gc;
- if (!memcmp(Str, "regparm", 7)) return AT_regparm;
- if (!memcmp(Str, "section", 7)) return AT_section;
- if (!memcmp(Str, "stdcall", 7)) return AT_stdcall;
- break;
- case 8:
- if (!memcmp(Str, "annotate", 8)) return AT_annotate;
- if (!memcmp(Str, "noreturn", 8)) return AT_noreturn;
- if (!memcmp(Str, "noinline", 8)) return AT_noinline;
- if (!memcmp(Str, "fastcall", 8)) return AT_fastcall;
- if (!memcmp(Str, "iboutlet", 8)) return AT_IBOutlet;
- if (!memcmp(Str, "sentinel", 8)) return AT_sentinel;
- if (!memcmp(Str, "NSObject", 8)) return AT_nsobject;
- break;
- case 9:
- if (!memcmp(Str, "dllimport", 9)) return AT_dllimport;
- if (!memcmp(Str, "dllexport", 9)) return AT_dllexport;
- if (!memcmp(Str, "may_alias", 9)) return IgnoredAttribute; // FIXME: TBAA
- break;
- case 10:
- if (!memcmp(Str, "deprecated", 10)) return AT_deprecated;
- if (!memcmp(Str, "visibility", 10)) return AT_visibility;
- if (!memcmp(Str, "destructor", 10)) return AT_destructor;
- if (!memcmp(Str, "format_arg", 10)) return AT_format_arg;
- if (!memcmp(Str, "gnu_inline", 10)) return AT_gnu_inline;
- break;
- case 11:
- if (!memcmp(Str, "weak_import", 11)) return AT_weak_import;
- if (!memcmp(Str, "vector_size", 11)) return AT_vector_size;
- if (!memcmp(Str, "constructor", 11)) return AT_constructor;
- if (!memcmp(Str, "unavailable", 11)) return AT_unavailable;
- break;
- case 12:
- if (!memcmp(Str, "overloadable", 12)) return AT_overloadable;
- break;
- case 13:
- if (!memcmp(Str, "address_space", 13)) return AT_address_space;
- if (!memcmp(Str, "always_inline", 13)) return AT_always_inline;
- if (!memcmp(Str, "vec_type_hint", 13)) return IgnoredAttribute;
- break;
- case 14:
- if (!memcmp(Str, "objc_exception", 14)) return AT_objc_exception;
- break;
- case 15:
- if (!memcmp(Str, "ext_vector_type", 15)) return AT_ext_vector_type;
- break;
- case 17:
- if (!memcmp(Str, "transparent_union", 17)) return AT_transparent_union;
- if (!memcmp(Str, "analyzer_noreturn", 17)) return AT_analyzer_noreturn;
- break;
- case 18:
- if (!memcmp(Str, "warn_unused_result", 18)) return AT_warn_unused_result;
- break;
- case 19:
- if (!memcmp(Str, "ns_returns_retained", 19)) return AT_ns_returns_retained;
- if (!memcmp(Str, "cf_returns_retained", 19)) return AT_cf_returns_retained;
- break;
- case 20:
- if (!memcmp(Str, "reqd_work_group_size", 20)) return AT_reqd_wg_size;
- case 22:
- if (!memcmp(Str, "no_instrument_function", 22))
- return AT_no_instrument_function;
- break;
- }
- return UnknownAttribute;
+ return llvm::StringSwitch<AttributeList::Kind>(AttrName)
+ .Case("weak", AT_weak)
+ .Case("pure", AT_pure)
+ .Case("mode", AT_mode)
+ .Case("used", AT_used)
+ .Case("alias", AT_alias)
+ .Case("const", AT_const)
+ .Case("packed", AT_packed)
+ .Case("malloc", AT_malloc)
+ .Case("format", AT_format)
+ .Case("unused", AT_unused)
+ .Case("blocks", AT_blocks)
+ .Case("aligned", AT_aligned)
+ .Case("cleanup", AT_cleanup)
+ .Case("nodebug", AT_nodebug)
+ .Case("nonnull", AT_nonnull)
+ .Case("nothrow", AT_nothrow)
+ .Case("objc_gc", AT_objc_gc)
+ .Case("regparm", AT_regparm)
+ .Case("section", AT_section)
+ .Case("stdcall", AT_stdcall)
+ .Case("annotate", AT_annotate)
+ .Case("noreturn", AT_noreturn)
+ .Case("noinline", AT_noinline)
+ .Case("fastcall", AT_fastcall)
+ .Case("iboutlet", AT_IBOutlet)
+ .Case("sentinel", AT_sentinel)
+ .Case("NSObject", AT_nsobject)
+ .Case("dllimport", AT_dllimport)
+ .Case("dllexport", AT_dllexport)
+ .Case("may_alias", IgnoredAttribute) // FIXME: TBAA
+ .Case("deprecated", AT_deprecated)
+ .Case("visibility", AT_visibility)
+ .Case("destructor", AT_destructor)
+ .Case("format_arg", AT_format_arg)
+ .Case("gnu_inline", AT_gnu_inline)
+ .Case("weak_import", AT_weak_import)
+ .Case("vector_size", AT_vector_size)
+ .Case("constructor", AT_constructor)
+ .Case("unavailable", AT_unavailable)
+ .Case("overloadable", AT_overloadable)
+ .Case("address_space", AT_address_space)
+ .Case("always_inline", AT_always_inline)
+ .Case("vec_type_hint", IgnoredAttribute)
+ .Case("objc_exception", AT_objc_exception)
+ .Case("ext_vector_type", AT_ext_vector_type)
+ .Case("transparent_union", AT_transparent_union)
+ .Case("analyzer_noreturn", AT_analyzer_noreturn)
+ .Case("warn_unused_result", AT_warn_unused_result)
+ .Case("ns_returns_retained", AT_ns_returns_retained)
+ .Case("cf_returns_retained", AT_cf_returns_retained)
+ .Case("reqd_work_group_size", AT_reqd_wg_size)
+ .Case("no_instrument_function", AT_no_instrument_function)
+ .Default(UnknownAttribute);
}
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index b8422aad5a84..3436900027e4 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -446,3 +446,28 @@ bool DeclSpec::isMissingDeclaratorOk() {
|| tst == TST_enum
) && getTypeRep() != 0 && StorageClassSpec != DeclSpec::SCS_typedef;
}
+
+void UnqualifiedId::clear() {
+ if (Kind == IK_TemplateId)
+ TemplateId->Destroy();
+
+ Kind = IK_Identifier;
+ Identifier = 0;
+ StartLocation = SourceLocation();
+ EndLocation = SourceLocation();
+}
+
+void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
+ OverloadedOperatorKind Op,
+ SourceLocation SymbolLocations[3]) {
+ Kind = IK_OperatorFunctionId;
+ StartLocation = OperatorLoc;
+ EndLocation = OperatorLoc;
+ OperatorFunctionId.Operator = Op;
+ for (unsigned I = 0; I != 3; ++I) {
+ OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding();
+
+ if (SymbolLocations[I].isValid())
+ EndLocation = SymbolLocations[I];
+ }
+}
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index 71b22cad6f62..1e7d397fdf37 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -161,9 +161,8 @@ bool MinimalAction::isCurrentClassName(const IdentifierInfo &, Scope *,
TemplateNameKind
MinimalAction::isTemplateName(Scope *S,
- const IdentifierInfo &II,
- SourceLocation IdLoc,
- const CXXScopeSpec *SS,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType,
bool EnteringScope,
TemplateTy &TemplateDecl) {
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index b56c33170cbf..e905553fd818 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -336,10 +336,9 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
/// If RequireSemi is false, this does not check for a ';' at the end of the
/// declaration.
Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
- SourceLocation &DeclEnd,
- bool RequireSemi) {
+ SourceLocation &DeclEnd) {
// Parse the common declaration-specifiers piece.
- DeclSpec DS;
+ ParsingDeclSpec DS(*this);
ParseDeclarationSpecifiers(DS);
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
@@ -347,32 +346,109 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
if (Tok.is(tok::semi)) {
ConsumeToken();
DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ DS.complete(TheDecl);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
- Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
- ParseDeclarator(DeclaratorInfo);
+ DeclGroupPtrTy DG = ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false,
+ &DeclEnd);
+ return DG;
+}
- DeclGroupPtrTy DG =
- ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+/// ParseDeclGroup - Having concluded that this is either a function
+/// definition or a group of object declarations, actually parse the
+/// result.
+Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
+ unsigned Context,
+ bool AllowFunctionDefinitions,
+ SourceLocation *DeclEnd) {
+ // Parse the first declarator.
+ ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Context));
+ ParseDeclarator(D);
+
+ // Bail out if the first declarator didn't seem well-formed.
+ if (!D.hasName() && !D.mayOmitIdentifier()) {
+ // Skip until ; or }.
+ SkipUntil(tok::r_brace, true, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ return DeclGroupPtrTy();
+ }
+
+ if (AllowFunctionDefinitions && D.isFunctionDeclarator()) {
+ if (isDeclarationAfterDeclarator()) {
+ // Fall though. We have to check this first, though, because
+ // __attribute__ might be the start of a function definition in
+ // (extended) K&R C.
+ } else if (isStartOfFunctionDefinition()) {
+ if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
+ Diag(Tok, diag::err_function_declared_typedef);
+
+ // Recover by treating the 'typedef' as spurious.
+ DS.ClearStorageClassSpecs();
+ }
- DeclEnd = Tok.getLocation();
+ DeclPtrTy TheDecl = ParseFunctionDefinition(D);
+ return Actions.ConvertDeclToDeclGroup(TheDecl);
+ } else {
+ Diag(Tok, diag::err_expected_fn_body);
+ SkipUntil(tok::semi);
+ return DeclGroupPtrTy();
+ }
+ }
- // If the client wants to check what comes after the declaration, just return
- // immediately without checking anything!
- if (!RequireSemi) return DG;
+ llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
+ DeclPtrTy FirstDecl = ParseDeclarationAfterDeclarator(D);
+ D.complete(FirstDecl);
+ if (FirstDecl.get())
+ DeclsInGroup.push_back(FirstDecl);
- if (Tok.is(tok::semi)) {
+ // If we don't have a comma, it is either the end of the list (a ';') or an
+ // error, bail out.
+ while (Tok.is(tok::comma)) {
+ // Consume the comma.
ConsumeToken();
- return DG;
+
+ // Parse the next declarator.
+ D.clear();
+
+ // Accept attributes in an init-declarator. In the first declarator in a
+ // declaration, these would be part of the declspec. In subsequent
+ // declarators, they become part of the declarator itself, so that they
+ // don't apply to declarators after *this* one. Examples:
+ // short __attribute__((common)) var; -> declspec
+ // short var __attribute__((common)); -> declarator
+ // short x, __attribute__((common)) var; -> declarator
+ if (Tok.is(tok::kw___attribute)) {
+ SourceLocation Loc;
+ AttributeList *AttrList = ParseAttributes(&Loc);
+ D.AddAttributes(AttrList, Loc);
+ }
+
+ ParseDeclarator(D);
+
+ DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
+ D.complete(ThisDecl);
+ if (ThisDecl.get())
+ DeclsInGroup.push_back(ThisDecl);
}
- Diag(Tok, diag::err_expected_semi_declaration);
- // Skip to end of block or statement
- SkipUntil(tok::r_brace, true, true);
- if (Tok.is(tok::semi))
- ConsumeToken();
- return DG;
+ if (DeclEnd)
+ *DeclEnd = Tok.getLocation();
+
+ if (Context != Declarator::ForContext &&
+ ExpectAndConsume(tok::semi,
+ Context == Declarator::FileContext
+ ? diag::err_invalid_token_after_toplevel_declarator
+ : diag::err_expected_semi_declaration)) {
+ SkipUntil(tok::r_brace, true, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ }
+
+ return Actions.FinalizeDeclaratorGroup(CurScope, DS,
+ DeclsInGroup.data(),
+ DeclsInGroup.size());
}
/// \brief Parse 'declaration' after parsing 'declaration-specifiers
@@ -498,63 +574,6 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
return ThisDecl;
}
-/// ParseInitDeclaratorListAfterFirstDeclarator - Parse 'declaration' after
-/// parsing 'declaration-specifiers declarator'. This method is split out this
-/// way to handle the ambiguity between top-level function-definitions and
-/// declarations.
-///
-/// init-declarator-list: [C99 6.7]
-/// init-declarator
-/// init-declarator-list ',' init-declarator
-///
-/// According to the standard grammar, =default and =delete are function
-/// definitions, but that definitely doesn't fit with the parser here.
-///
-Parser::DeclGroupPtrTy Parser::
-ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
- // Declarators may be grouped together ("int X, *Y, Z();"). Remember the decls
- // that we parse together here.
- llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
-
- // At this point, we know that it is not a function definition. Parse the
- // rest of the init-declarator-list.
- while (1) {
- DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
- if (ThisDecl.get())
- DeclsInGroup.push_back(ThisDecl);
-
- // If we don't have a comma, it is either the end of the list (a ';') or an
- // error, bail out.
- if (Tok.isNot(tok::comma))
- break;
-
- // Consume the comma.
- ConsumeToken();
-
- // Parse the next declarator.
- D.clear();
-
- // Accept attributes in an init-declarator. In the first declarator in a
- // declaration, these would be part of the declspec. In subsequent
- // declarators, they become part of the declarator itself, so that they
- // don't apply to declarators after *this* one. Examples:
- // short __attribute__((common)) var; -> declspec
- // short var __attribute__((common)); -> declarator
- // short x, __attribute__((common)) var; -> declarator
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
- D.AddAttributes(AttrList, Loc);
- }
-
- ParseDeclarator(D);
- }
-
- return Actions.FinalizeDeclaratorGroup(CurScope, D.getDeclSpec(),
- DeclsInGroup.data(),
- DeclsInGroup.size());
-}
-
/// ParseSpecifierQualifierList
/// specifier-qualifier-list:
/// type-specifier specifier-qualifier-list[opt]
@@ -1468,8 +1487,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
/// [GNU] declarator[opt] ':' constant-expression attributes[opt]
///
void Parser::
-ParseStructDeclaration(DeclSpec &DS,
- llvm::SmallVectorImpl<FieldDeclarator> &Fields) {
+ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
if (Tok.is(tok::kw___extension__)) {
// __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this.
@@ -1489,9 +1507,17 @@ ParseStructDeclaration(DeclSpec &DS,
}
// Read struct-declarators until we find the semicolon.
- Fields.push_back(FieldDeclarator(DS));
+ bool FirstDeclarator = true;
while (1) {
- FieldDeclarator &DeclaratorInfo = Fields.back();
+ ParsingDeclRAIIObject PD(*this);
+ FieldDeclarator DeclaratorInfo(DS);
+
+ // Attributes are only allowed here on successive declarators.
+ if (!FirstDeclarator && Tok.is(tok::kw___attribute)) {
+ SourceLocation Loc;
+ AttributeList *AttrList = ParseAttributes(&Loc);
+ DeclaratorInfo.D.AddAttributes(AttrList, Loc);
+ }
/// struct-declarator: declarator
/// struct-declarator: declarator[opt] ':' constant-expression
@@ -1514,6 +1540,10 @@ ParseStructDeclaration(DeclSpec &DS,
DeclaratorInfo.D.AddAttributes(AttrList, Loc);
}
+ // We're done with this declarator; invoke the callback.
+ DeclPtrTy D = Fields.invoke(DeclaratorInfo);
+ PD.complete(D);
+
// If we don't have a comma, it is either the end of the list (a ';')
// or an error, bail out.
if (Tok.isNot(tok::comma))
@@ -1522,15 +1552,7 @@ ParseStructDeclaration(DeclSpec &DS,
// Consume the comma.
ConsumeToken();
- // Parse the next declarator.
- Fields.push_back(FieldDeclarator(DS));
-
- // Attributes are only allowed on the second declarator.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
- Fields.back().D.AddAttributes(AttrList, Loc);
- }
+ FirstDeclarator = false;
}
}
@@ -1562,7 +1584,6 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
<< DeclSpec::getSpecifierName((DeclSpec::TST)TagType);
llvm::SmallVector<DeclPtrTy, 32> FieldDecls;
- llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
// While we still have something to read, read the declarations in the struct.
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
@@ -1578,28 +1599,28 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
// Parse all the comma separated declarators.
DeclSpec DS;
- FieldDeclarators.clear();
+
if (!Tok.is(tok::at)) {
- ParseStructDeclaration(DS, FieldDeclarators);
-
- // Convert them all to fields.
- for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
- FieldDeclarator &FD = FieldDeclarators[i];
- DeclPtrTy Field;
- // Install the declarator into the current TagDecl.
- if (FD.D.getExtension()) {
- // Silences extension warnings
- ExtensionRAIIObject O(Diags);
- Field = Actions.ActOnField(CurScope, TagDecl,
- DS.getSourceRange().getBegin(),
- FD.D, FD.BitfieldSize);
- } else {
- Field = Actions.ActOnField(CurScope, TagDecl,
- DS.getSourceRange().getBegin(),
- FD.D, FD.BitfieldSize);
+ struct CFieldCallback : FieldCallback {
+ Parser &P;
+ DeclPtrTy TagDecl;
+ llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls;
+
+ CFieldCallback(Parser &P, DeclPtrTy TagDecl,
+ llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls) :
+ P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {}
+
+ virtual DeclPtrTy invoke(FieldDeclarator &FD) {
+ // Install the declarator into the current TagDecl.
+ DeclPtrTy Field = P.Actions.ActOnField(P.CurScope, TagDecl,
+ FD.D.getDeclSpec().getSourceRange().getBegin(),
+ FD.D, FD.BitfieldSize);
+ FieldDecls.push_back(Field);
+ return Field;
}
- FieldDecls.push_back(Field);
- }
+ } Callback(*this, TagDecl, FieldDecls);
+
+ ParseStructDeclaration(DS, Callback);
} else { // Handle @defs
ConsumeToken();
if (!Tok.isObjCAtKeyword(tok::objc_defs)) {
@@ -2107,7 +2128,6 @@ void Parser::ParseDeclarator(Declarator &D) {
/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
void Parser::ParseDeclaratorInternal(Declarator &D,
DirectDeclParseFunction DirectDeclParser) {
-
if (Diags.hasAllExtensionsSilenced())
D.setExtension();
// C++ member pointers start with a '::' or a nested-name.
@@ -2270,97 +2290,47 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
void Parser::ParseDirectDeclarator(Declarator &D) {
DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
- if (getLang().CPlusPlus) {
- if (D.mayHaveIdentifier()) {
- // ParseDeclaratorInternal might already have parsed the scope.
- bool afterCXXScope = D.getCXXScopeSpec().isSet() ||
- ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
- true);
- if (afterCXXScope) {
- // Change the declaration context for name lookup, until this function
- // is exited (and the declarator has been parsed).
- DeclScopeObj.EnterDeclaratorScope();
- }
-
- if (Tok.is(tok::identifier)) {
- assert(Tok.getIdentifierInfo() && "Not an identifier?");
-
- // If this identifier is the name of the current class, it's a
- // constructor name.
- if (!D.getDeclSpec().hasTypeSpecifier() &&
- Actions.isCurrentClassName(*Tok.getIdentifierInfo(),CurScope)) {
- CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0;
- D.setConstructor(Actions.getTypeName(*Tok.getIdentifierInfo(),
- Tok.getLocation(), CurScope, SS),
- Tok.getLocation());
- // This is a normal identifier.
- } else
- D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
- ConsumeToken();
- goto PastIdentifier;
- } else if (Tok.is(tok::annot_template_id)) {
- TemplateIdAnnotation *TemplateId
- = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
-
- D.setTemplateId(TemplateId);
- ConsumeToken();
- goto PastIdentifier;
- } else if (Tok.is(tok::kw_operator)) {
- SourceLocation OperatorLoc = Tok.getLocation();
- SourceLocation EndLoc;
-
- // First try the name of an overloaded operator
- if (OverloadedOperatorKind Op = TryParseOperatorFunctionId(&EndLoc)) {
- D.setOverloadedOperator(Op, OperatorLoc, EndLoc);
- } else {
- // This must be a conversion function (C++ [class.conv.fct]).
- if (TypeTy *ConvType = ParseConversionFunctionId(&EndLoc))
- D.setConversionFunction(ConvType, OperatorLoc, EndLoc);
- else {
- D.SetIdentifier(0, Tok.getLocation());
- }
- }
- goto PastIdentifier;
- } else if (Tok.is(tok::tilde)) {
- // This should be a C++ destructor.
- SourceLocation TildeLoc = ConsumeToken();
- if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
- // FIXME: Inaccurate.
- SourceLocation NameLoc = Tok.getLocation();
- SourceLocation EndLoc;
- CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0;
- TypeResult Type = ParseClassName(EndLoc, SS, true);
- if (Type.isInvalid())
- D.SetIdentifier(0, TildeLoc);
- else
- D.setDestructor(Type.get(), TildeLoc, NameLoc);
- } else {
- Diag(Tok, diag::err_destructor_class_name);
- D.SetIdentifier(0, TildeLoc);
- }
- goto PastIdentifier;
- }
-
- // If we reached this point, token is not identifier and not '~'.
-
- if (afterCXXScope) {
- Diag(Tok, diag::err_expected_unqualified_id);
+ if (getLang().CPlusPlus && D.mayHaveIdentifier()) {
+ // ParseDeclaratorInternal might already have parsed the scope.
+ bool afterCXXScope = D.getCXXScopeSpec().isSet() ||
+ ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
+ true);
+ if (afterCXXScope) {
+ // Change the declaration context for name lookup, until this function
+ // is exited (and the declarator has been parsed).
+ DeclScopeObj.EnterDeclaratorScope();
+ }
+
+ if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
+ Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) {
+ // We found something that indicates the start of an unqualified-id.
+ // Parse that unqualified-id.
+ if (ParseUnqualifiedId(D.getCXXScopeSpec(),
+ /*EnteringContext=*/true,
+ /*AllowDestructorName=*/true,
+ /*AllowConstructorName=*/!D.getDeclSpec().hasTypeSpecifier(),
+ /*ObjectType=*/0,
+ D.getName())) {
D.SetIdentifier(0, Tok.getLocation());
D.setInvalidType(true);
- goto PastIdentifier;
+ } else {
+ // Parsed the unqualified-id; update range information and move along.
+ if (D.getSourceRange().getBegin().isInvalid())
+ D.SetRangeBegin(D.getName().getSourceRange().getBegin());
+ D.SetRangeEnd(D.getName().getSourceRange().getEnd());
}
+ goto PastIdentifier;
}
- }
-
- // If we reached this point, we are either in C/ObjC or the token didn't
- // satisfy any of the C++-specific checks.
- if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
+ } else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
assert(!getLang().CPlusPlus &&
"There's a C++-specific check for tok::identifier above");
assert(Tok.getIdentifierInfo() && "Not an identifier?");
D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken();
- } else if (Tok.is(tok::l_paren)) {
+ goto PastIdentifier;
+ }
+
+ if (Tok.is(tok::l_paren)) {
// direct-declarator: '(' declarator ')'
// direct-declarator: '(' attributes declarator ')'
// Example: 'char (*X)' or 'int (*XX)(void)'
@@ -2374,7 +2344,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
Diag(Tok, diag::err_expected_member_name_or_semi)
<< D.getDeclSpec().getSourceRange();
else if (getLang().CPlusPlus)
- Diag(Tok, diag::err_expected_unqualified_id);
+ Diag(Tok, diag::err_expected_unqualified_id) << getLang().CPlusPlus;
else
Diag(Tok, diag::err_expected_ident_lparen);
D.SetIdentifier(0, Tok.getLocation());
@@ -2623,6 +2593,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
SourceLocation DSStart = Tok.getLocation();
// Parse the declaration-specifiers.
+ // Just use the ParsingDeclaration "scope" of the declarator.
DeclSpec DS;
// If the caller parsed attributes for the first argument, add them now.
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index d381e3e97472..91f86864f81f 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -323,6 +323,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
SkipUntil(tok::semi);
return DeclPtrTy();
}
+ // FIXME: what about conversion functions?
} else if (Tok.is(tok::identifier)) {
// Parse identifier.
TargetName = Tok.getIdentifierInfo();
@@ -589,6 +590,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
Diag(Tok, diag::err_expected_ident);
+ TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
+
// Parse the (optional) class name or simple-template-id.
IdentifierInfo *Name = 0;
SourceLocation NameLoc;
@@ -596,6 +599,56 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (Tok.is(tok::identifier)) {
Name = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
+
+ if (Tok.is(tok::less)) {
+ // The name was supposed to refer to a template, but didn't.
+ // Eat the template argument list and try to continue parsing this as
+ // a class (or template thereof).
+ TemplateArgList TemplateArgs;
+ TemplateArgIsTypeList TemplateArgIsType;
+ TemplateArgLocationList TemplateArgLocations;
+ SourceLocation LAngleLoc, RAngleLoc;
+ if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS,
+ true, LAngleLoc,
+ TemplateArgs, TemplateArgIsType,
+ TemplateArgLocations, RAngleLoc)) {
+ // We couldn't parse the template argument list at all, so don't
+ // try to give any location information for the list.
+ LAngleLoc = RAngleLoc = SourceLocation();
+ }
+
+ Diag(NameLoc, diag::err_explicit_spec_non_template)
+ << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
+ << (TagType == DeclSpec::TST_class? 0
+ : TagType == DeclSpec::TST_struct? 1
+ : 2)
+ << Name
+ << SourceRange(LAngleLoc, RAngleLoc);
+
+ // Strip off the last template parameter list if it was empty, since
+ // we've removed its template argument list.
+ if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
+ if (TemplateParams && TemplateParams->size() > 1) {
+ TemplateParams->pop_back();
+ } else {
+ TemplateParams = 0;
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
+ = ParsedTemplateInfo::NonTemplate;
+ }
+ } else if (TemplateInfo.Kind
+ == ParsedTemplateInfo::ExplicitInstantiation) {
+ // Pretend this is just a forward declaration.
+ TemplateParams = 0;
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
+ = ParsedTemplateInfo::NonTemplate;
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc
+ = SourceLocation();
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).ExternLoc
+ = SourceLocation();
+ }
+
+
+ }
} else if (Tok.is(tok::annot_template_id)) {
TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
NameLoc = ConsumeToken();
@@ -660,7 +713,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Create the tag portion of the class or class template.
Action::DeclResult TagOrTempResult = true; // invalid
Action::TypeResult TypeResult = true; // invalid
- TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
// FIXME: When TUK == TUK_Reference and we have a template-id, we need
// to turn that template-id into a type.
@@ -1047,7 +1099,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
SourceLocation DSStart = Tok.getLocation();
// decl-specifier-seq:
// Parse the common declaration-specifiers piece.
- DeclSpec DS;
+ ParsingDeclSpec DS(*this);
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
Action::MultiTemplateParamsArg TemplateParams(Actions,
@@ -1060,7 +1112,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
return;
}
- Declarator DeclaratorInfo(DS, Declarator::MemberContext);
+ ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
if (Tok.isNot(tok::colon)) {
// Parse the first declarator.
@@ -1179,6 +1231,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl);
}
+ DeclaratorInfo.complete(ThisDecl);
+
// If we don't have a comma, it is either the end of the list (a ';')
// or an error, bail out.
if (Tok.isNot(tok::comma))
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 8be89a891680..95a0e989471e 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -340,7 +340,18 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) {
// Eat the colon.
ColonLoc = ConsumeToken();
}
-
+
+ if ((OpToken.is(tok::periodstar) || OpToken.is(tok::arrowstar))
+ && Tok.is(tok::identifier)) {
+ CXXScopeSpec SS;
+ if (Actions.getTypeName(*Tok.getIdentifierInfo(),
+ Tok.getLocation(), CurScope, &SS)) {
+ const char *Opc = OpToken.is(tok::periodstar) ? "'.*'" : "'->*'";
+ Diag(OpToken, diag::err_pointer_to_member_type) << Opc;
+ return ExprError();
+ }
+
+ }
// Parse another leaf here for the RHS of the operator.
// ParseCastExpression works here because all RHS expressions in C have it
// as a prefix, at least. However, in C++, an assignment-expression could
@@ -612,36 +623,39 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
}
- // Support 'Class.property' notation.
- // We don't use isTokObjCMessageIdentifierReceiver(), since it allows
- // 'super' (which is inappropriate here).
- if (getLang().ObjC1 &&
- Actions.getTypeName(*Tok.getIdentifierInfo(),
- Tok.getLocation(), CurScope) &&
- NextToken().is(tok::period)) {
- IdentifierInfo &ReceiverName = *Tok.getIdentifierInfo();
- SourceLocation IdentLoc = ConsumeToken();
+ // Consume the identifier so that we can see if it is followed by a '(' or
+ // '.'.
+ IdentifierInfo &II = *Tok.getIdentifierInfo();
+ SourceLocation ILoc = ConsumeToken();
+
+ // Support 'Class.property' notation. We don't use
+ // isTokObjCMessageIdentifierReceiver(), since it allows 'super' (which is
+ // inappropriate here).
+ if (getLang().ObjC1 && Tok.is(tok::period) &&
+ Actions.getTypeName(II, ILoc, CurScope)) {
SourceLocation DotLoc = ConsumeToken();
-
+
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
+ Diag(Tok, diag::err_expected_property_name);
return ExprError();
}
IdentifierInfo &PropertyName = *Tok.getIdentifierInfo();
SourceLocation PropertyLoc = ConsumeToken();
-
- Res = Actions.ActOnClassPropertyRefExpr(ReceiverName, PropertyName,
- IdentLoc, PropertyLoc);
+
+ Res = Actions.ActOnClassPropertyRefExpr(II, PropertyName,
+ ILoc, PropertyLoc);
// These can be followed by postfix-expr pieces.
return ParsePostfixExpressionSuffix(move(Res));
}
- // Consume the identifier so that we can see if it is followed by a '('.
+
// Function designators are allowed to be undeclared (C99 6.5.1p2), so we
// need to know whether or not this identifier is a function designator or
// not.
- IdentifierInfo &II = *Tok.getIdentifierInfo();
- SourceLocation L = ConsumeToken();
- Res = Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren));
+ UnqualifiedId Name;
+ CXXScopeSpec ScopeSpec;
+ Name.setIdentifier(&II, ILoc);
+ Res = Actions.ActOnIdExpression(CurScope, ScopeSpec, Name,
+ Tok.is(tok::l_paren), false);
// These can be followed by postfix-expr pieces.
return ParsePostfixExpressionSuffix(move(Res));
}
@@ -954,110 +968,20 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
ConsumeToken();
}
- if (Tok.is(tok::identifier)) {
- if (!LHS.isInvalid())
- LHS = Actions.ActOnMemberReferenceExpr(CurScope, move(LHS), OpLoc,
- OpKind, Tok.getLocation(),
- *Tok.getIdentifierInfo(),
- ObjCImpDecl, &SS);
- ConsumeToken();
- } else if (getLang().CPlusPlus && Tok.is(tok::tilde)) {
- // We have a C++ pseudo-destructor or a destructor call, e.g., t.~T()
-
- // Consume the tilde.
- ConsumeToken();
-
- if (!Tok.is(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
- return ExprError();
- }
-
- if (NextToken().is(tok::less)) {
- // class-name:
- // ~ simple-template-id
- TemplateTy Template
- = Actions.ActOnDependentTemplateName(SourceLocation(),
- *Tok.getIdentifierInfo(),
- Tok.getLocation(),
- SS,
- ObjectType);
- if (AnnotateTemplateIdToken(Template, TNK_Type_template, &SS,
- SourceLocation(), true))
- return ExprError();
-
- assert(Tok.is(tok::annot_typename) &&
- "AnnotateTemplateIdToken didn't work?");
- if (!LHS.isInvalid())
- LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
- OpLoc, OpKind,
- Tok.getAnnotationRange(),
- Tok.getAnnotationValue(),
- SS,
- NextToken().is(tok::l_paren));
- } else {
- // class-name:
- // ~ identifier
- if (!LHS.isInvalid())
- LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
- OpLoc, OpKind,
- Tok.getLocation(),
- Tok.getIdentifierInfo(),
- SS,
- NextToken().is(tok::l_paren));
- }
-
- // Consume the identifier or template-id token.
- ConsumeToken();
- } else if (getLang().CPlusPlus && Tok.is(tok::kw_operator)) {
- // We have a reference to a member operator, e.g., t.operator int or
- // t.operator+.
- SourceLocation OperatorLoc = Tok.getLocation();
-
- if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
- if (!LHS.isInvalid())
- LHS = Actions.ActOnOverloadedOperatorReferenceExpr(CurScope,
- move(LHS), OpLoc,
- OpKind,
- OperatorLoc,
- Op, &SS);
- // TryParseOperatorFunctionId already consumed our token, so
- // don't bother
- } else if (TypeTy *ConvType = ParseConversionFunctionId()) {
- if (!LHS.isInvalid())
- LHS = Actions.ActOnConversionOperatorReferenceExpr(CurScope,
- move(LHS), OpLoc,
- OpKind,
- OperatorLoc,
- ConvType, &SS);
- } else {
- // Don't emit a diagnostic; ParseConversionFunctionId does it for us
- return ExprError();
- }
- } else if (getLang().CPlusPlus && Tok.is(tok::annot_template_id)) {
- // We have a reference to a member template along with explicitly-
- // specified template arguments, e.g., t.f<int>.
- TemplateIdAnnotation *TemplateId
- = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
- if (!LHS.isInvalid()) {
- ASTTemplateArgsPtr TemplateArgsPtr(Actions,
- TemplateId->getTemplateArgs(),
- TemplateId->getTemplateArgIsType(),
- TemplateId->NumArgs);
-
- LHS = Actions.ActOnMemberTemplateIdReferenceExpr(CurScope, move(LHS),
- OpLoc, OpKind, SS,
- TemplateTy::make(TemplateId->Template),
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
- TemplateId->RAngleLoc);
- }
- ConsumeToken();
- } else {
- Diag(Tok, diag::err_expected_ident);
+ UnqualifiedId Name;
+ if (ParseUnqualifiedId(SS,
+ /*EnteringContext=*/false,
+ /*AllowDestructorName=*/true,
+ /*AllowConstructorName=*/false,
+ ObjectType,
+ Name))
return ExprError();
- }
+
+ if (!LHS.isInvalid())
+ LHS = Actions.ActOnMemberAccessExpr(CurScope, move(LHS), OpLoc, OpKind,
+ SS, Name, ObjCImpDecl,
+ Tok.is(tok::l_paren));
+
break;
}
case tok::plusplus: // postfix-expression: postfix-expression '++'
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index fa651569f8e1..a7ca0c54dbe6 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -14,6 +14,8 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/DeclSpec.h"
+#include "llvm/Support/ErrorHandling.h"
+
using namespace clang;
/// \brief Parse global scope or nested-name-specifier if present.
@@ -107,31 +109,58 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
break;
SourceLocation TemplateKWLoc = ConsumeToken();
-
- if (Tok.isNot(tok::identifier)) {
+
+ UnqualifiedId TemplateName;
+ if (Tok.is(tok::identifier)) {
+ TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+
+ // If the next token is not '<', we may have a stray 'template' keyword.
+ // Complain and suggest removing the template keyword, but otherwise
+ // allow parsing to continue.
+ if (NextToken().isNot(tok::less)) {
+ Diag(NextToken().getLocation(),
+ diag::err_less_after_template_name_in_nested_name_spec)
+ << Tok.getIdentifierInfo()->getName()
+ << CodeModificationHint::CreateRemoval(SourceRange(TemplateKWLoc));
+ break;
+ }
+
+ // Consume the identifier.
+ ConsumeToken();
+ } else if (Tok.is(tok::kw_operator)) {
+ if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType,
+ TemplateName))
+ break;
+
+ if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId) {
+ Diag(TemplateName.getSourceRange().getBegin(),
+ diag::err_id_after_template_in_nested_name_spec)
+ << TemplateName.getSourceRange();
+ break;
+ } else if (Tok.isNot(tok::less)) {
+ std::string OperatorName = "operator ";
+ OperatorName += getOperatorSpelling(
+ TemplateName.OperatorFunctionId.Operator);
+ Diag(Tok.getLocation(),
+ diag::err_less_after_template_name_in_nested_name_spec)
+ << OperatorName
+ << TemplateName.getSourceRange();
+ break;
+ }
+ } else {
Diag(Tok.getLocation(),
diag::err_id_after_template_in_nested_name_spec)
<< SourceRange(TemplateKWLoc);
break;
}
- if (NextToken().isNot(tok::less)) {
- Diag(NextToken().getLocation(),
- diag::err_less_after_template_name_in_nested_name_spec)
- << Tok.getIdentifierInfo()->getName()
- << SourceRange(TemplateKWLoc, Tok.getLocation());
- break;
- }
-
TemplateTy Template
- = Actions.ActOnDependentTemplateName(TemplateKWLoc,
- *Tok.getIdentifierInfo(),
- Tok.getLocation(), SS,
+ = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
ObjectType);
if (!Template)
break;
if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
- &SS, TemplateKWLoc, false))
+ &SS, TemplateName, TemplateKWLoc, false))
break;
continue;
@@ -218,9 +247,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// type-name '<'
if (Next.is(tok::less)) {
TemplateTy Template;
- if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, II,
- Tok.getLocation(),
- &SS,
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(&II, Tok.getLocation());
+ if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS,
+ TemplateName,
ObjectType,
EnteringContext,
Template)) {
@@ -230,8 +260,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// because some clients (e.g., the parsing of class template
// specializations) still want to see the original template-id
// token.
- if (AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(),
- false))
+ ConsumeToken();
+ if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName,
+ SourceLocation(), false))
break;
continue;
}
@@ -251,25 +282,12 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
/// unqualified-id
/// qualified-id
///
-/// unqualified-id:
-/// identifier
-/// operator-function-id
-/// conversion-function-id [TODO]
-/// '~' class-name [TODO]
-/// template-id
-///
/// qualified-id:
/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
/// '::' identifier
/// '::' operator-function-id
/// '::' template-id
///
-/// nested-name-specifier:
-/// type-name '::'
-/// namespace-name '::'
-/// nested-name-specifier identifier '::'
-/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
-///
/// NOTE: The standard specifies that, for qualified-id, the parser does not
/// expect:
///
@@ -307,69 +325,19 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
//
CXXScopeSpec SS;
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
-
- // unqualified-id:
- // identifier
- // operator-function-id
- // conversion-function-id
- // '~' class-name [TODO]
- // template-id
- //
- switch (Tok.getKind()) {
- default:
- return ExprError(Diag(Tok, diag::err_expected_unqualified_id));
-
- case tok::identifier: {
- // Consume the identifier so that we can see if it is followed by a '('.
- IdentifierInfo &II = *Tok.getIdentifierInfo();
- SourceLocation L = ConsumeToken();
- return Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren),
- &SS, isAddressOfOperand);
- }
-
- case tok::kw_operator: {
- SourceLocation OperatorLoc = Tok.getLocation();
- if (OverloadedOperatorKind Op = TryParseOperatorFunctionId())
- return Actions.ActOnCXXOperatorFunctionIdExpr(
- CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS,
- isAddressOfOperand);
- if (TypeTy *Type = ParseConversionFunctionId())
- return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type,
- Tok.is(tok::l_paren), SS,
- isAddressOfOperand);
-
- // We already complained about a bad conversion-function-id,
- // above.
+
+ UnqualifiedId Name;
+ if (ParseUnqualifiedId(SS,
+ /*EnteringContext=*/false,
+ /*AllowDestructorName=*/false,
+ /*AllowConstructorName=*/false,
+ /*ObjectType=*/0,
+ Name))
return ExprError();
- }
-
- case tok::annot_template_id: {
- TemplateIdAnnotation *TemplateId
- = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
- assert((TemplateId->Kind == TNK_Function_template ||
- TemplateId->Kind == TNK_Dependent_template_name) &&
- "A template type name is not an ID expression");
-
- ASTTemplateArgsPtr TemplateArgsPtr(Actions,
- TemplateId->getTemplateArgs(),
- TemplateId->getTemplateArgIsType(),
- TemplateId->NumArgs);
-
- OwningExprResult Result
- = Actions.ActOnTemplateIdExpr(SS,
- TemplateTy::make(TemplateId->Template),
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
- TemplateId->RAngleLoc);
- ConsumeToken(); // Consume the template-id token
- return move(Result);
- }
-
- } // switch.
-
- assert(0 && "The switch was supposed to take care everything.");
+
+ return Actions.ActOnIdExpression(CurScope, SS, Name, Tok.is(tok::l_paren),
+ isAddressOfOperand);
+
}
/// ParseCXXCasts - This handles the various ways to cast expressions to another
@@ -761,6 +729,473 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
return false;
}
+/// \brief Finish parsing a C++ unqualified-id that is a template-id of
+/// some form.
+///
+/// This routine is invoked when a '<' is encountered after an identifier or
+/// operator-function-id is parsed by \c ParseUnqualifiedId() to determine
+/// whether the unqualified-id is actually a template-id. This routine will
+/// then parse the template arguments and form the appropriate template-id to
+/// return to the caller.
+///
+/// \param SS the nested-name-specifier that precedes this template-id, if
+/// we're actually parsing a qualified-id.
+///
+/// \param Name for constructor and destructor names, this is the actual
+/// identifier that may be a template-name.
+///
+/// \param NameLoc the location of the class-name in a constructor or
+/// destructor.
+///
+/// \param EnteringContext whether we're entering the scope of the
+/// nested-name-specifier.
+///
+/// \param ObjectType if this unqualified-id occurs within a member access
+/// expression, the type of the base object whose member is being accessed.
+///
+/// \param Id as input, describes the template-name or operator-function-id
+/// that precedes the '<'. If template arguments were parsed successfully,
+/// will be updated with the template-id.
+///
+/// \returns true if a parse error occurred, false otherwise.
+bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool EnteringContext,
+ TypeTy *ObjectType,
+ UnqualifiedId &Id) {
+ assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
+
+ TemplateTy Template;
+ TemplateNameKind TNK = TNK_Non_template;
+ switch (Id.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ case UnqualifiedId::IK_OperatorFunctionId:
+ TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType, EnteringContext,
+ Template);
+ break;
+
+ case UnqualifiedId::IK_ConstructorName: {
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(Name, NameLoc);
+ TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType,
+ EnteringContext, Template);
+ break;
+ }
+
+ case UnqualifiedId::IK_DestructorName: {
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(Name, NameLoc);
+ if (ObjectType) {
+ Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS,
+ TemplateName, ObjectType);
+ TNK = TNK_Dependent_template_name;
+ if (!Template.get())
+ return true;
+ } else {
+ TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType,
+ EnteringContext, Template);
+
+ if (TNK == TNK_Non_template && Id.DestructorName == 0) {
+ // The identifier following the destructor did not refer to a template
+ // or to a type. Complain.
+ if (ObjectType)
+ Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
+ << Name;
+ else
+ Diag(NameLoc, diag::err_destructor_class_name);
+ return true;
+ }
+ }
+ break;
+ }
+
+ default:
+ return false;
+ }
+
+ if (TNK == TNK_Non_template)
+ return false;
+
+ // Parse the enclosed template argument list.
+ SourceLocation LAngleLoc, RAngleLoc;
+ TemplateArgList TemplateArgs;
+ TemplateArgIsTypeList TemplateArgIsType;
+ TemplateArgLocationList TemplateArgLocations;
+ if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
+ &SS, true, LAngleLoc,
+ TemplateArgs,
+ TemplateArgIsType,
+ TemplateArgLocations,
+ RAngleLoc))
+ return true;
+
+ if (Id.getKind() == UnqualifiedId::IK_Identifier ||
+ Id.getKind() == UnqualifiedId::IK_OperatorFunctionId) {
+ // Form a parsed representation of the template-id to be stored in the
+ // UnqualifiedId.
+ TemplateIdAnnotation *TemplateId
+ = TemplateIdAnnotation::Allocate(TemplateArgs.size());
+
+ if (Id.getKind() == UnqualifiedId::IK_Identifier) {
+ TemplateId->Name = Id.Identifier;
+ TemplateId->Operator = OO_None;
+ TemplateId->TemplateNameLoc = Id.StartLocation;
+ } else {
+ TemplateId->Name = 0;
+ TemplateId->Operator = Id.OperatorFunctionId.Operator;
+ TemplateId->TemplateNameLoc = Id.StartLocation;
+ }
+
+ TemplateId->Template = Template.getAs<void*>();
+ TemplateId->Kind = TNK;
+ TemplateId->LAngleLoc = LAngleLoc;
+ TemplateId->RAngleLoc = RAngleLoc;
+ void **Args = TemplateId->getTemplateArgs();
+ bool *ArgIsType = TemplateId->getTemplateArgIsType();
+ SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations();
+ for (unsigned Arg = 0, ArgEnd = TemplateArgs.size();
+ Arg != ArgEnd; ++Arg) {
+ Args[Arg] = TemplateArgs[Arg];
+ ArgIsType[Arg] = TemplateArgIsType[Arg];
+ ArgLocs[Arg] = TemplateArgLocations[Arg];
+ }
+
+ Id.setTemplateId(TemplateId);
+ return false;
+ }
+
+ // Bundle the template arguments together.
+ ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
+ TemplateArgIsType.data(),
+ TemplateArgs.size());
+
+ // Constructor and destructor names.
+ Action::TypeResult Type
+ = Actions.ActOnTemplateIdType(Template, NameLoc,
+ LAngleLoc, TemplateArgsPtr,
+ &TemplateArgLocations[0],
+ RAngleLoc);
+ if (Type.isInvalid())
+ return true;
+
+ if (Id.getKind() == UnqualifiedId::IK_ConstructorName)
+ Id.setConstructorName(Type.get(), NameLoc, RAngleLoc);
+ else
+ Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc);
+
+ return false;
+}
+
+/// \brief Parse an operator-function-id or conversion-function-id as part
+/// of a C++ unqualified-id.
+///
+/// This routine is responsible only for parsing the operator-function-id or
+/// conversion-function-id; it does not handle template arguments in any way.
+///
+/// \code
+/// operator-function-id: [C++ 13.5]
+/// 'operator' operator
+///
+/// operator: one of
+/// new delete new[] delete[]
+/// + - * / % ^ & | ~
+/// ! = < > += -= *= /= %=
+/// ^= &= |= << >> >>= <<= == !=
+/// <= >= && || ++ -- , ->* ->
+/// () []
+///
+/// conversion-function-id: [C++ 12.3.2]
+/// operator conversion-type-id
+///
+/// conversion-type-id:
+/// type-specifier-seq conversion-declarator[opt]
+///
+/// conversion-declarator:
+/// ptr-operator conversion-declarator[opt]
+/// \endcode
+///
+/// \param The nested-name-specifier that preceded this unqualified-id. If
+/// non-empty, then we are parsing the unqualified-id of a qualified-id.
+///
+/// \param EnteringContext whether we are entering the scope of the
+/// nested-name-specifier.
+///
+/// \param ObjectType if this unqualified-id occurs within a member access
+/// expression, the type of the base object whose member is being accessed.
+///
+/// \param Result on a successful parse, contains the parsed unqualified-id.
+///
+/// \returns true if parsing fails, false otherwise.
+bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
+ TypeTy *ObjectType,
+ UnqualifiedId &Result) {
+ assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
+
+ // Consume the 'operator' keyword.
+ SourceLocation KeywordLoc = ConsumeToken();
+
+ // Determine what kind of operator name we have.
+ unsigned SymbolIdx = 0;
+ SourceLocation SymbolLocations[3];
+ OverloadedOperatorKind Op = OO_None;
+ switch (Tok.getKind()) {
+ case tok::kw_new:
+ case tok::kw_delete: {
+ bool isNew = Tok.getKind() == tok::kw_new;
+ // Consume the 'new' or 'delete'.
+ SymbolLocations[SymbolIdx++] = ConsumeToken();
+ if (Tok.is(tok::l_square)) {
+ // Consume the '['.
+ SourceLocation LBracketLoc = ConsumeBracket();
+ // Consume the ']'.
+ SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
+ LBracketLoc);
+ if (RBracketLoc.isInvalid())
+ return true;
+
+ SymbolLocations[SymbolIdx++] = LBracketLoc;
+ SymbolLocations[SymbolIdx++] = RBracketLoc;
+ Op = isNew? OO_Array_New : OO_Array_Delete;
+ } else {
+ Op = isNew? OO_New : OO_Delete;
+ }
+ break;
+ }
+
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ case tok::Token: \
+ SymbolLocations[SymbolIdx++] = ConsumeToken(); \
+ Op = OO_##Name; \
+ break;
+#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
+#include "clang/Basic/OperatorKinds.def"
+
+ case tok::l_paren: {
+ // Consume the '('.
+ SourceLocation LParenLoc = ConsumeParen();
+ // Consume the ')'.
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren,
+ LParenLoc);
+ if (RParenLoc.isInvalid())
+ return true;
+
+ SymbolLocations[SymbolIdx++] = LParenLoc;
+ SymbolLocations[SymbolIdx++] = RParenLoc;
+ Op = OO_Call;
+ break;
+ }
+
+ case tok::l_square: {
+ // Consume the '['.
+ SourceLocation LBracketLoc = ConsumeBracket();
+ // Consume the ']'.
+ SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
+ LBracketLoc);
+ if (RBracketLoc.isInvalid())
+ return true;
+
+ SymbolLocations[SymbolIdx++] = LBracketLoc;
+ SymbolLocations[SymbolIdx++] = RBracketLoc;
+ Op = OO_Subscript;
+ break;
+ }
+
+ case tok::code_completion: {
+ // Code completion for the operator name.
+ Actions.CodeCompleteOperatorName(CurScope);
+
+ // Consume the operator token.
+ ConsumeToken();
+
+ // Don't try to parse any further.
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ if (Op != OO_None) {
+ // We have parsed an operator-function-id.
+ Result.setOperatorFunctionId(KeywordLoc, Op, SymbolLocations);
+ return false;
+ }
+
+ // Parse a conversion-function-id.
+ //
+ // conversion-function-id: [C++ 12.3.2]
+ // operator conversion-type-id
+ //
+ // conversion-type-id:
+ // type-specifier-seq conversion-declarator[opt]
+ //
+ // conversion-declarator:
+ // ptr-operator conversion-declarator[opt]
+
+ // Parse the type-specifier-seq.
+ DeclSpec DS;
+ if (ParseCXXTypeSpecifierSeq(DS))
+ return true;
+
+ // Parse the conversion-declarator, which is merely a sequence of
+ // ptr-operators.
+ Declarator D(DS, Declarator::TypeNameContext);
+ ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
+
+ // Finish up the type.
+ Action::TypeResult Ty = Actions.ActOnTypeName(CurScope, D);
+ if (Ty.isInvalid())
+ return true;
+
+ // Note that this is a conversion-function-id.
+ Result.setConversionFunctionId(KeywordLoc, Ty.get(),
+ D.getSourceRange().getEnd());
+ return false;
+}
+
+/// \brief Parse a C++ unqualified-id (or a C identifier), which describes the
+/// name of an entity.
+///
+/// \code
+/// unqualified-id: [C++ expr.prim.general]
+/// identifier
+/// operator-function-id
+/// conversion-function-id
+/// [C++0x] literal-operator-id [TODO]
+/// ~ class-name
+/// template-id
+///
+/// \endcode
+///
+/// \param The nested-name-specifier that preceded this unqualified-id. If
+/// non-empty, then we are parsing the unqualified-id of a qualified-id.
+///
+/// \param EnteringContext whether we are entering the scope of the
+/// nested-name-specifier.
+///
+/// \param AllowDestructorName whether we allow parsing of a destructor name.
+///
+/// \param AllowConstructorName whether we allow parsing a constructor name.
+///
+/// \param ObjectType if this unqualified-id occurs within a member access
+/// expression, the type of the base object whose member is being accessed.
+///
+/// \param Result on a successful parse, contains the parsed unqualified-id.
+///
+/// \returns true if parsing fails, false otherwise.
+bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
+ bool AllowDestructorName,
+ bool AllowConstructorName,
+ TypeTy *ObjectType,
+ UnqualifiedId &Result) {
+ // unqualified-id:
+ // identifier
+ // template-id (when it hasn't already been annotated)
+ if (Tok.is(tok::identifier)) {
+ // Consume the identifier.
+ IdentifierInfo *Id = Tok.getIdentifierInfo();
+ SourceLocation IdLoc = ConsumeToken();
+
+ if (AllowConstructorName &&
+ Actions.isCurrentClassName(*Id, CurScope, &SS)) {
+ // We have parsed a constructor name.
+ Result.setConstructorName(Actions.getTypeName(*Id, IdLoc, CurScope,
+ &SS, false),
+ IdLoc, IdLoc);
+ } else {
+ // We have parsed an identifier.
+ Result.setIdentifier(Id, IdLoc);
+ }
+
+ // If the next token is a '<', we may have a template.
+ if (Tok.is(tok::less))
+ return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext,
+ ObjectType, Result);
+
+ return false;
+ }
+
+ // unqualified-id:
+ // template-id (already parsed and annotated)
+ if (Tok.is(tok::annot_template_id)) {
+ // FIXME: Could this be a constructor name???
+
+ // We have already parsed a template-id; consume the annotation token as
+ // our unqualified-id.
+ Result.setTemplateId(
+ static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue()));
+ ConsumeToken();
+ return false;
+ }
+
+ // unqualified-id:
+ // operator-function-id
+ // conversion-function-id
+ if (Tok.is(tok::kw_operator)) {
+ if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, Result))
+ return true;
+
+ // If we have an operator-function-id and the next token is a '<', we may
+ // have a
+ //
+ // template-id:
+ // operator-function-id < template-argument-list[opt] >
+ if (Result.getKind() == UnqualifiedId::IK_OperatorFunctionId &&
+ Tok.is(tok::less))
+ return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(),
+ EnteringContext, ObjectType,
+ Result);
+
+ return false;
+ }
+
+ if ((AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) {
+ // C++ [expr.unary.op]p10:
+ // There is an ambiguity in the unary-expression ~X(), where X is a
+ // class-name. The ambiguity is resolved in favor of treating ~ as a
+ // unary complement rather than treating ~X as referring to a destructor.
+
+ // Parse the '~'.
+ SourceLocation TildeLoc = ConsumeToken();
+
+ // Parse the class-name.
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_destructor_class_name);
+ return true;
+ }
+
+ // Parse the class-name (or template-name in a simple-template-id).
+ IdentifierInfo *ClassName = Tok.getIdentifierInfo();
+ SourceLocation ClassNameLoc = ConsumeToken();
+
+ if (Tok.is(tok::less)) {
+ Result.setDestructorName(TildeLoc, 0, ClassNameLoc);
+ return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc,
+ EnteringContext, ObjectType, Result);
+ }
+
+ // Note that this is a destructor name.
+ Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc,
+ CurScope, &SS);
+ if (!Ty) {
+ if (ObjectType)
+ Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
+ << ClassName;
+ else
+ Diag(ClassNameLoc, diag::err_destructor_class_name);
+ return true;
+ }
+
+ Result.setDestructorName(TildeLoc, Ty, ClassNameLoc);
+ return false;
+ }
+
+ Diag(Tok, diag::err_expected_unqualified_id)
+ << getLang().CPlusPlus;
+ return true;
+}
+
/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
/// operator name (C++ [over.oper]). If successful, returns the
/// predefined identifier that corresponds to that overloaded
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 2e0cd6d0d932..b043dd99f304 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -305,51 +305,68 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
if (Tok.is(tok::l_paren))
ParseObjCPropertyAttribute(OCDS);
+ struct ObjCPropertyCallback : FieldCallback {
+ Parser &P;
+ DeclPtrTy IDecl;
+ llvm::SmallVectorImpl<DeclPtrTy> &Props;
+ ObjCDeclSpec &OCDS;
+ SourceLocation AtLoc;
+ tok::ObjCKeywordKind MethodImplKind;
+
+ ObjCPropertyCallback(Parser &P, DeclPtrTy IDecl,
+ llvm::SmallVectorImpl<DeclPtrTy> &Props,
+ ObjCDeclSpec &OCDS, SourceLocation AtLoc,
+ tok::ObjCKeywordKind MethodImplKind) :
+ P(P), IDecl(IDecl), Props(Props), OCDS(OCDS), AtLoc(AtLoc),
+ MethodImplKind(MethodImplKind) {
+ }
+
+ DeclPtrTy invoke(FieldDeclarator &FD) {
+ if (FD.D.getIdentifier() == 0) {
+ P.Diag(AtLoc, diag::err_objc_property_requires_field_name)
+ << FD.D.getSourceRange();
+ return DeclPtrTy();
+ }
+ if (FD.BitfieldSize) {
+ P.Diag(AtLoc, diag::err_objc_property_bitfield)
+ << FD.D.getSourceRange();
+ return DeclPtrTy();
+ }
+
+ // Install the property declarator into interfaceDecl.
+ IdentifierInfo *SelName =
+ OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
+
+ Selector GetterSel =
+ P.PP.getSelectorTable().getNullarySelector(SelName);
+ IdentifierInfo *SetterName = OCDS.getSetterName();
+ Selector SetterSel;
+ if (SetterName)
+ SetterSel = P.PP.getSelectorTable().getSelector(1, &SetterName);
+ else
+ SetterSel = SelectorTable::constructSetterName(P.PP.getIdentifierTable(),
+ P.PP.getSelectorTable(),
+ FD.D.getIdentifier());
+ bool isOverridingProperty = false;
+ DeclPtrTy Property =
+ P.Actions.ActOnProperty(P.CurScope, AtLoc, FD, OCDS,
+ GetterSel, SetterSel, IDecl,
+ &isOverridingProperty,
+ MethodImplKind);
+ if (!isOverridingProperty)
+ Props.push_back(Property);
+
+ return Property;
+ }
+ } Callback(*this, interfaceDecl, allProperties,
+ OCDS, AtLoc, MethodImplKind);
+
// Parse all the comma separated declarators.
DeclSpec DS;
- llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
- ParseStructDeclaration(DS, FieldDeclarators);
+ ParseStructDeclaration(DS, Callback);
ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "",
tok::at);
-
- // Convert them all to property declarations.
- for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
- FieldDeclarator &FD = FieldDeclarators[i];
- if (FD.D.getIdentifier() == 0) {
- Diag(AtLoc, diag::err_objc_property_requires_field_name)
- << FD.D.getSourceRange();
- continue;
- }
- if (FD.BitfieldSize) {
- Diag(AtLoc, diag::err_objc_property_bitfield)
- << FD.D.getSourceRange();
- continue;
- }
-
- // Install the property declarator into interfaceDecl.
- IdentifierInfo *SelName =
- OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
-
- Selector GetterSel =
- PP.getSelectorTable().getNullarySelector(SelName);
- IdentifierInfo *SetterName = OCDS.getSetterName();
- Selector SetterSel;
- if (SetterName)
- SetterSel = PP.getSelectorTable().getSelector(1, &SetterName);
- else
- SetterSel = SelectorTable::constructSetterName(PP.getIdentifierTable(),
- PP.getSelectorTable(),
- FD.D.getIdentifier());
- bool isOverridingProperty = false;
- DeclPtrTy Property = Actions.ActOnProperty(CurScope, AtLoc, FD, OCDS,
- GetterSel, SetterSel,
- interfaceDecl,
- &isOverridingProperty,
- MethodImplKind);
- if (!isOverridingProperty)
- allProperties.push_back(Property);
- }
break;
}
}
@@ -681,6 +698,8 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
tok::TokenKind mType,
DeclPtrTy IDecl,
tok::ObjCKeywordKind MethodImplKind) {
+ ParsingDeclRAIIObject PD(*this);
+
// Parse the return type if present.
TypeTy *ReturnType = 0;
ObjCDeclSpec DSRet;
@@ -707,10 +726,13 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
MethodAttrs = ParseAttributes();
Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
- return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
+ DeclPtrTy Result
+ = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
mType, IDecl, DSRet, ReturnType, Sel,
0, CargNames, MethodAttrs,
MethodImplKind);
+ PD.complete(Result);
+ return Result;
}
llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
@@ -783,10 +805,13 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
return DeclPtrTy();
Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
&KeyIdents[0]);
- return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
+ DeclPtrTy Result
+ = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
mType, IDecl, DSRet, ReturnType, Sel,
&ArgInfos[0], CargNames, MethodAttrs,
MethodImplKind, isVariadic);
+ PD.complete(Result);
+ return Result;
}
/// objc-protocol-refs:
@@ -858,7 +883,6 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
SourceLocation atLoc) {
assert(Tok.is(tok::l_brace) && "expected {");
llvm::SmallVector<DeclPtrTy, 32> AllIvarDecls;
- llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
@@ -893,21 +917,31 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
}
}
+ struct ObjCIvarCallback : FieldCallback {
+ Parser &P;
+ DeclPtrTy IDecl;
+ tok::ObjCKeywordKind visibility;
+ llvm::SmallVectorImpl<DeclPtrTy> &AllIvarDecls;
+
+ ObjCIvarCallback(Parser &P, DeclPtrTy IDecl, tok::ObjCKeywordKind V,
+ llvm::SmallVectorImpl<DeclPtrTy> &AllIvarDecls) :
+ P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) {
+ }
+
+ DeclPtrTy invoke(FieldDeclarator &FD) {
+ // Install the declarator into the interface decl.
+ DeclPtrTy Field
+ = P.Actions.ActOnIvar(P.CurScope,
+ FD.D.getDeclSpec().getSourceRange().getBegin(),
+ IDecl, FD.D, FD.BitfieldSize, visibility);
+ AllIvarDecls.push_back(Field);
+ return Field;
+ }
+ } Callback(*this, interfaceDecl, visibility, AllIvarDecls);
+
// Parse all the comma separated declarators.
DeclSpec DS;
- FieldDeclarators.clear();
- ParseStructDeclaration(DS, FieldDeclarators);
-
- // Convert them all to fields.
- for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
- FieldDeclarator &FD = FieldDeclarators[i];
- // Install the declarator into interfaceDecl.
- DeclPtrTy Field = Actions.ActOnIvar(CurScope,
- DS.getSourceRange().getBegin(),
- interfaceDecl,
- FD.D, FD.BitfieldSize, visibility);
- AllIvarDecls.push_back(Field);
- }
+ ParseStructDeclaration(DS, Callback);
if (Tok.is(tok::semi)) {
ConsumeToken();
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 272be2f66017..7637382ac032 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -938,8 +938,7 @@ Parser::OwningStmtResult Parser::ParseForStatement() {
Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
- false);
+ DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd);
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
if (Tok.is(tok::semi)) { // for (int x = 4;
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 8e63fb89db31..045acd86ad0f 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -101,6 +101,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
// (and retrieves the outer template parameter list from its
// context).
bool isSpecialization = true;
+ bool LastParamListWasEmpty = false;
TemplateParameterLists ParamLists;
TemplateParameterDepthCounter Depth(TemplateParameterDepth);
do {
@@ -140,13 +141,16 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
if (!TemplateParams.empty()) {
isSpecialization = false;
++Depth;
+ } else {
+ LastParamListWasEmpty = true;
}
} while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
// Parse the actual template declaration.
return ParseSingleDeclarationAfterTemplate(Context,
ParsedTemplateInfo(&ParamLists,
- isSpecialization),
+ isSpecialization,
+ LastParamListWasEmpty),
DeclEnd, AS);
}
@@ -186,16 +190,18 @@ Parser::ParseSingleDeclarationAfterTemplate(
}
// Parse the declaration specifiers.
- DeclSpec DS;
+ ParsingDeclSpec DS(*this);
ParseDeclarationSpecifiers(DS, TemplateInfo, AS);
if (Tok.is(tok::semi)) {
DeclEnd = ConsumeToken();
- return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ DeclPtrTy Decl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ DS.complete(Decl);
+ return Decl;
}
// Parse the declarator.
- Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
+ ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context);
ParseDeclarator(DeclaratorInfo);
// Error parsing the declarator?
if (!DeclaratorInfo.hasName()) {
@@ -221,6 +227,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
// Eat the semi colon after the declaration.
ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
+ DS.complete(ThisDecl);
return ThisDecl;
}
@@ -668,22 +675,23 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
///
bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
const CXXScopeSpec *SS,
+ UnqualifiedId &TemplateName,
SourceLocation TemplateKWLoc,
bool AllowTypeAnnotation) {
assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
- assert(Template && Tok.is(tok::identifier) && NextToken().is(tok::less) &&
+ assert(Template && Tok.is(tok::less) &&
"Parser isn't at the beginning of a template-id");
// Consume the template-name.
- IdentifierInfo *Name = Tok.getIdentifierInfo();
- SourceLocation TemplateNameLoc = ConsumeToken();
+ SourceLocation TemplateNameLoc = TemplateName.getSourceRange().getBegin();
// Parse the enclosed template argument list.
SourceLocation LAngleLoc, RAngleLoc;
TemplateArgList TemplateArgs;
TemplateArgIsTypeList TemplateArgIsType;
TemplateArgLocationList TemplateArgLocations;
- bool Invalid = ParseTemplateIdAfterTemplateName(Template, TemplateNameLoc,
+ bool Invalid = ParseTemplateIdAfterTemplateName(Template,
+ TemplateNameLoc,
SS, false, LAngleLoc,
TemplateArgs,
TemplateArgIsType,
@@ -732,7 +740,13 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
TemplateIdAnnotation *TemplateId
= TemplateIdAnnotation::Allocate(TemplateArgs.size());
TemplateId->TemplateNameLoc = TemplateNameLoc;
- TemplateId->Name = Name;
+ if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) {
+ TemplateId->Name = TemplateName.Identifier;
+ TemplateId->Operator = OO_None;
+ } else {
+ TemplateId->Name = 0;
+ TemplateId->Operator = TemplateName.OperatorFunctionId.Operator;
+ }
TemplateId->Template = Template.getAs<void*>();
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index bc737e9f0c80..335a6cf36254 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -526,7 +526,7 @@ bool Parser::isStartOfFunctionDefinition() {
Parser::DeclGroupPtrTy
Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
// Parse the common declaration-specifiers piece.
- DeclSpec DS;
+ ParsingDeclSpec DS(*this);
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS);
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
@@ -534,6 +534,7 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
if (Tok.is(tok::semi)) {
ConsumeToken();
DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ DS.complete(TheDecl);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
@@ -548,6 +549,9 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
SkipUntil(tok::semi); // FIXME: better skip?
return DeclGroupPtrTy();
}
+
+ DS.abort();
+
const char *PrevSpec = 0;
unsigned DiagID;
if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID))
@@ -567,58 +571,12 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
if (Tok.is(tok::string_literal) && getLang().CPlusPlus &&
DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
+ DS.abort();
DeclPtrTy TheDecl = ParseLinkage(Declarator::FileContext);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
- // Parse the first declarator.
- Declarator DeclaratorInfo(DS, Declarator::FileContext);
- ParseDeclarator(DeclaratorInfo);
- // Error parsing the declarator?
- if (!DeclaratorInfo.hasName()) {
- // If so, skip until the semi-colon or a }.
- SkipUntil(tok::r_brace, true, true);
- if (Tok.is(tok::semi))
- ConsumeToken();
- return DeclGroupPtrTy();
- }
-
- // If we have a declaration or declarator list, handle it.
- if (isDeclarationAfterDeclarator()) {
- // Parse the init-declarator-list for a normal declaration.
- DeclGroupPtrTy DG =
- ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
- // Eat the semi colon after the declaration.
- ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
- return DG;
- }
-
- if (DeclaratorInfo.isFunctionDeclarator() &&
- isStartOfFunctionDefinition()) {
- if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
- Diag(Tok, diag::err_function_declared_typedef);
-
- if (Tok.is(tok::l_brace)) {
- // This recovery skips the entire function body. It would be nice
- // to simply call ParseFunctionDefinition() below, however Sema
- // assumes the declarator represents a function, not a typedef.
- ConsumeBrace();
- SkipUntil(tok::r_brace, true);
- } else {
- SkipUntil(tok::semi);
- }
- return DeclGroupPtrTy();
- }
- DeclPtrTy TheDecl = ParseFunctionDefinition(DeclaratorInfo);
- return Actions.ConvertDeclToDeclGroup(TheDecl);
- }
-
- if (DeclaratorInfo.isFunctionDeclarator())
- Diag(Tok, diag::err_expected_fn_body);
- else
- Diag(Tok, diag::err_invalid_token_after_toplevel_declarator);
- SkipUntil(tok::semi);
- return DeclGroupPtrTy();
+ return ParseDeclGroup(DS, Declarator::FileContext, true);
}
/// ParseFunctionDefinition - We parsed and verified that the specified
@@ -635,7 +593,7 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
/// [C++] function-definition: [C++ 8.4]
/// decl-specifier-seq[opt] declarator function-try-block
///
-Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D,
+Parser::DeclPtrTy Parser::ParseFunctionDefinition(ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo) {
const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0);
assert(FnTypeInfo.Kind == DeclaratorChunk::Function &&
@@ -687,6 +645,13 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D,
D)
: Actions.ActOnStartOfFunctionDef(CurScope, D);
+ // Break out of the ParsingDeclarator context before we parse the body.
+ D.complete(Res);
+
+ // Break out of the ParsingDeclSpec context, too. This const_cast is
+ // safe because we're always the sole owner.
+ D.getMutableDeclSpec().abort();
+
if (Tok.is(tok::kw_try))
return ParseFunctionTryBlock(Res);
@@ -981,17 +946,21 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
// If this is a template-id, annotate with a template-id or type token.
if (NextToken().is(tok::less)) {
TemplateTy Template;
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
if (TemplateNameKind TNK
- = Actions.isTemplateName(CurScope, *Tok.getIdentifierInfo(),
- Tok.getLocation(), &SS,
+ = Actions.isTemplateName(CurScope, SS, TemplateName,
/*ObjectType=*/0, EnteringContext,
- Template))
- if (AnnotateTemplateIdToken(Template, TNK, &SS)) {
+ Template)) {
+ // Consume the identifier.
+ ConsumeToken();
+ if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName)) {
// If an unrecoverable error occurred, we need to return true here,
// because the token stream is in a damaged state. We may not return
// a valid identifier.
return Tok.isNot(tok::identifier);
}
+ }
}
// The current token, which is either an identifier or a
@@ -1065,3 +1034,10 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
PP.AnnotateCachedTokens(Tok);
return true;
}
+
+// Anchor the Parser::FieldCallback vtable to this translation unit.
+// We use a spurious method instead of the destructor because
+// destroying FieldCallbacks can actually be slightly
+// performance-sensitive.
+void Parser::FieldCallback::_anchor() {
+}
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index c78ab5b3e959..9b24d55f3ece 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -156,6 +156,17 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results,
case Result::RK_Keyword:
OS << Results[I].Keyword << " : " << Results[I].Rank << '\n';
break;
+
+ case Result::RK_Macro: {
+ OS << Results[I].Macro->getName() << " : " << Results[I].Rank;
+ if (CodeCompletionString *CCS
+ = Results[I].CreateCodeCompletionString(SemaRef)) {
+ OS << " : " << CCS->getAsString();
+ delete CCS;
+ }
+ OS << '\n';
+ break;
+ }
}
}
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index fc9c14f456bd..8104dd39d052 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -277,15 +277,20 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
PushDeclContext(S, Context.getTranslationUnitDecl());
if (PP.getTargetInfo().getPointerWidth(0) >= 64) {
+ DeclaratorInfo *DInfo;
+
// Install [u]int128_t for 64-bit targets.
+ DInfo = Context.getTrivialDeclaratorInfo(Context.Int128Ty);
PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
SourceLocation(),
&Context.Idents.get("__int128_t"),
- Context.Int128Ty), TUScope);
+ DInfo), TUScope);
+
+ DInfo = Context.getTrivialDeclaratorInfo(Context.UnsignedInt128Ty);
PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
SourceLocation(),
&Context.Idents.get("__uint128_t"),
- Context.UnsignedInt128Ty), TUScope);
+ DInfo), TUScope);
}
@@ -298,10 +303,10 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
PushOnScopeChains(SelTag, TUScope);
QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
- TypedefDecl *SelTypedef = TypedefDecl::Create(Context, CurContext,
- SourceLocation(),
- &Context.Idents.get("SEL"),
- SelT);
+ DeclaratorInfo *SelInfo = Context.getTrivialDeclaratorInfo(SelT);
+ TypedefDecl *SelTypedef
+ = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+ &Context.Idents.get("SEL"), SelInfo);
PushOnScopeChains(SelTypedef, TUScope);
Context.setObjCSelType(Context.getTypeDeclType(SelTypedef));
}
@@ -317,22 +322,23 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
}
// Create the built-in typedef for 'id'.
if (Context.getObjCIdType().isNull()) {
- TypedefDecl *IdTypedef =
- TypedefDecl::Create(
- Context, CurContext, SourceLocation(), &Context.Idents.get("id"),
- Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy)
- );
+ QualType IdT = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy);
+ DeclaratorInfo *IdInfo = Context.getTrivialDeclaratorInfo(IdT);
+ TypedefDecl *IdTypedef
+ = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+ &Context.Idents.get("id"), IdInfo);
PushOnScopeChains(IdTypedef, TUScope);
Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
Context.ObjCIdRedefinitionType = Context.getObjCIdType();
}
// Create the built-in typedef for 'Class'.
if (Context.getObjCClassType().isNull()) {
- TypedefDecl *ClassTypedef =
- TypedefDecl::Create(
- Context, CurContext, SourceLocation(), &Context.Idents.get("Class"),
- Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy)
- );
+ QualType ClassType
+ = Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy);
+ DeclaratorInfo *ClassInfo = Context.getTrivialDeclaratorInfo(ClassType);
+ TypedefDecl *ClassTypedef
+ = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+ &Context.Idents.get("Class"), ClassInfo);
PushOnScopeChains(ClassTypedef, TUScope);
Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
Context.ObjCClassRedefinitionType = Context.getObjCClassType();
@@ -344,7 +350,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
: LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
ExternalSource(0), CodeCompleter(0), CurContext(0),
- PreDeclaratorDC(0), CurBlock(0), PackContext(0),
+ PreDeclaratorDC(0), CurBlock(0), PackContext(0), ParsingDeclDepth(0),
IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated),
CompleteTranslationUnit(CompleteTranslationUnit),
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 6dd081bdc25e..0f84b46ed405 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -73,6 +73,7 @@ namespace clang {
class TypedefDecl;
class TemplateDecl;
class TemplateArgument;
+ class TemplateArgumentLoc;
class TemplateArgumentList;
class TemplateParameterList;
class TemplateTemplateParmDecl;
@@ -271,6 +272,15 @@ public:
llvm::DenseMap<DeclarationName, VarDecl *> TentativeDefinitions;
std::vector<DeclarationName> TentativeDefinitionList;
+ /// \brief The collection of delayed deprecation warnings.
+ llvm::SmallVector<std::pair<SourceLocation,NamedDecl*>, 8>
+ DelayedDeprecationWarnings;
+
+ /// \brief The depth of the current ParsingDeclaration stack.
+ /// If nonzero, we are currently parsing a declaration (and
+ /// hence should delay deprecation warnings).
+ unsigned ParsingDeclDepth;
+
/// WeakUndeclaredIdentifiers - Identifiers contained in
/// #pragma weak before declared. rare. may alias another
/// identifier, declared or undeclared
@@ -447,8 +457,6 @@ public:
// Type Analysis / Processing: SemaType.cpp.
//
QualType adjustParameterType(QualType T);
- QualType ConvertDeclSpecToType(const DeclSpec &DS, SourceLocation DeclLoc,
- bool &IsInvalid);
void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
QualType BuildPointerType(QualType T, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
@@ -470,12 +478,12 @@ public:
SourceLocation Loc, DeclarationName Entity);
QualType GetTypeForDeclarator(Declarator &D, Scope *S,
DeclaratorInfo **DInfo = 0,
- unsigned Skip = 0, TagDecl **OwnedDecl = 0);
- DeclaratorInfo *GetDeclaratorInfoForDeclarator(Declarator &D, QualType T,
- unsigned Skip);
+ TagDecl **OwnedDecl = 0);
+ DeclaratorInfo *GetDeclaratorInfoForDeclarator(Declarator &D, QualType T);
/// \brief Create a LocInfoType to hold the given QualType and DeclaratorInfo.
QualType CreateLocInfoType(QualType T, DeclaratorInfo *DInfo);
DeclarationName GetNameForDeclarator(Declarator &D);
+ DeclarationName GetNameFromUnqualifiedId(UnqualifiedId &Name);
static QualType GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo = 0);
bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
bool CheckDistantExceptionSpec(QualType T);
@@ -767,7 +775,8 @@ public:
/// Subroutines of ActOnDeclarator().
- TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T);
+ TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
+ DeclaratorInfo *DInfo);
void MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
@@ -868,7 +877,7 @@ public:
bool ForceRValue = false);
void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr *Object, Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@@ -876,7 +885,7 @@ public:
bool ForceRValue = false);
void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@@ -914,7 +923,7 @@ public:
void AddArgumentDependentLookupCandidates(DeclarationName Name,
Expr **Args, unsigned NumArgs,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
bool PartialOverloading = false);
@@ -936,7 +945,7 @@ public:
DeclarationName &UnqualifiedName,
bool &ArgumentDependentLookup,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
@@ -945,7 +954,7 @@ public:
FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
DeclarationName UnqualifiedName,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
@@ -963,6 +972,10 @@ public:
FunctionSet &Functions,
Expr *LHS, Expr *RHS);
+ OwningExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+ SourceLocation RLoc,
+ ExprArg Base,ExprArg Idx);
+
ExprResult
BuildCallToMemberFunction(Scope *S, Expr *MemExpr,
SourceLocation LParenLoc, Expr **Args,
@@ -990,7 +1003,7 @@ public:
void CheckCXXDefaultArguments(FunctionDecl *FD);
void CheckExtraCXXDefaultArguments(Declarator &D);
enum ControlFlowKind { NeverFallThrough = 0, MaybeFallThrough = 1,
- AlwaysFallThrough = 2 };
+ AlwaysFallThrough = 2, NeverFallThroughOrReturn = 3 };
ControlFlowKind CheckFallThrough(Stmt *);
Scope *getNonFieldDeclScope(Scope *S);
@@ -1377,7 +1390,7 @@ public:
QualType T1, QualType T2,
FunctionSet &Functions);
- void ArgumentDependentLookup(DeclarationName Name,
+ void ArgumentDependentLookup(DeclarationName Name, bool Operator,
Expr **Args, unsigned NumArgs,
FunctionSet &Functions);
@@ -1582,6 +1595,10 @@ public:
/// whose result is unused, warn.
void DiagnoseUnusedExprResult(const Stmt *S);
+ ParsingDeclStackState PushParsingDeclaration();
+ void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D);
+ void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc);
+
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks: SemaExpr.cpp.
@@ -1604,23 +1621,12 @@ public:
// Primary Expressions.
virtual SourceRange getExprRange(ExprTy *E) const;
- virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
- IdentifierInfo &II,
- bool HasTrailingLParen,
- const CXXScopeSpec *SS = 0,
- bool isAddressOfOperand = false);
- virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(Scope *S,
- SourceLocation OperatorLoc,
- OverloadedOperatorKind Op,
- bool HasTrailingLParen,
- const CXXScopeSpec &SS,
- bool isAddressOfOperand);
- virtual OwningExprResult ActOnCXXConversionFunctionExpr(Scope *S,
- SourceLocation OperatorLoc,
- TypeTy *Ty,
- bool HasTrailingLParen,
- const CXXScopeSpec &SS,
- bool isAddressOfOperand);
+ virtual OwningExprResult ActOnIdExpression(Scope *S,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ bool HasTrailingLParen,
+ bool IsAddressOfOperand);
+
OwningExprResult BuildDeclRefExpr(NamedDecl *D, QualType Ty,
SourceLocation Loc, bool TypeDependent,
bool ValueDependent,
@@ -1664,7 +1670,8 @@ public:
virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
tok::TokenKind Op, ExprArg Input);
- OwningExprResult CreateSizeOfAlignOfExpr(QualType T, SourceLocation OpLoc,
+ OwningExprResult CreateSizeOfAlignOfExpr(DeclaratorInfo *T,
+ SourceLocation OpLoc,
bool isSizeOf, SourceRange R);
OwningExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
bool isSizeOf, SourceRange R);
@@ -1684,6 +1691,10 @@ public:
SourceLocation LLoc,
ExprArg Idx,
SourceLocation RLoc);
+ OwningExprResult CreateBuiltinArraySubscriptExpr(ExprArg Base,
+ SourceLocation LLoc,
+ ExprArg Idx,
+ SourceLocation RLoc);
OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base,
SourceLocation OpLoc,
@@ -1709,20 +1720,21 @@ public:
DeclarationName MemberName,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
DeclPtrTy ImplDecl,
const CXXScopeSpec *SS,
NamedDecl *FirstQualifierInScope = 0);
- virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation MemberLoc,
- IdentifierInfo &Member,
- DeclPtrTy ImplDecl,
- const CXXScopeSpec *SS = 0);
+ virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Member,
+ DeclPtrTy ObjCImpDecl,
+ bool HasTrailingLParen);
+
virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl);
bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
FunctionDecl *FDecl,
@@ -1742,7 +1754,7 @@ public:
SourceRange &QualifierRange,
bool &ArgumentDependentLookup,
bool &HasExplicitTemplateArguments,
- const TemplateArgument *&ExplicitTemplateArgs,
+ const TemplateArgumentLoc *&ExplicitTemplateArgs,
unsigned &NumExplicitTemplateArgs);
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
@@ -1900,7 +1912,6 @@ public:
/// and sets it as the initializer for the the passed in VarDecl.
bool InitializeVarWithConstructor(VarDecl *VD,
CXXConstructorDecl *Constructor,
- QualType DeclInitType,
MultiExprArg Exprs);
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
@@ -2099,52 +2110,6 @@ public:
tok::TokenKind OpKind,
TypeTy *&ObjectType);
- virtual OwningExprResult
- ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- IdentifierInfo *ClassName,
- const CXXScopeSpec &SS,
- bool HasTrailingLParen);
-
- virtual OwningExprResult
- ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceRange TypeRange,
- TypeTy *Type,
- const CXXScopeSpec &SS,
- bool HasTrailingLParen);
-
- virtual OwningExprResult
- ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- OverloadedOperatorKind OverOpKind,
- const CXXScopeSpec *SS = 0);
- virtual OwningExprResult
- ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- TypeTy *Ty,
- const CXXScopeSpec *SS = 0);
-
- virtual OwningExprResult
- ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- // FIXME: "template" keyword?
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
- SourceLocation RAngleLoc);
-
/// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
/// non-empty, will create a new CXXExprWithTemporaries expression.
/// Otherwise, just returs the passed in expression.
@@ -2305,7 +2270,7 @@ public:
SourceLocation RParenLoc,
CXXRecordDecl *ClassDecl);
- void setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
+ void SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
CXXBaseOrMemberInitializer **Initializers,
unsigned NumInitializers,
llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases,
@@ -2445,9 +2410,8 @@ public:
// C++ Templates [C++ 14]
//
virtual TemplateNameKind isTemplateName(Scope *S,
- const IdentifierInfo &II,
- SourceLocation IdLoc,
- const CXXScopeSpec *SS,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType,
bool EnteringContext,
TemplateTy &Template);
@@ -2507,13 +2471,13 @@ public:
AccessSpecifier AS);
void translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
- SourceLocation *TemplateArgLocs,
- llvm::SmallVector<TemplateArgument, 16> &TemplateArgs);
+ SourceLocation *TemplateArgLocsIn,
+ llvm::SmallVector<TemplateArgumentLoc, 16> &TempArgs);
QualType CheckTemplateIdType(TemplateName Template,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
@@ -2534,22 +2498,21 @@ public:
TemplateName Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
- virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
- SourceLocation RAngleLoc);
+ OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
+ TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation *TemplateArgLocs,
+ SourceLocation RAngleLoc);
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
- const IdentifierInfo &Name,
- SourceLocation NameLoc,
const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType);
bool CheckClassTemplatePartialSpecializationArgs(
@@ -2578,10 +2541,18 @@ public:
MultiTemplateParamsArg TemplateParameterLists,
Declarator &D);
+ bool
+ CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
+ TemplateSpecializationKind NewTSK,
+ NamedDecl *PrevDecl,
+ TemplateSpecializationKind PrevTSK,
+ SourceLocation PrevPointOfInstantiation,
+ bool &SuppressNew);
+
bool CheckFunctionTemplateSpecialization(FunctionDecl *FD,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
NamedDecl *&PrevDecl);
@@ -2621,18 +2592,18 @@ public:
bool CheckTemplateArgumentList(TemplateDecl *Template,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc,
bool PartialTemplateArgs,
TemplateArgumentListBuilder &Converted);
bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
- const TemplateArgument &Arg,
+ const TemplateArgumentLoc &Arg,
TemplateArgumentListBuilder &Converted);
- bool CheckTemplateArgument(TemplateTypeParmDecl *Param, QualType Arg,
- SourceLocation ArgLoc);
+ bool CheckTemplateArgument(TemplateTypeParmDecl *Param,
+ DeclaratorInfo *Arg);
bool CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
NamedDecl *&Entity);
bool CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member);
@@ -2807,7 +2778,7 @@ public:
TemplateDeductionResult
SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
llvm::SmallVectorImpl<TemplateArgument> &Deduced,
llvm::SmallVectorImpl<QualType> &ParamTypes,
@@ -2823,7 +2794,7 @@ public:
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
FunctionDecl *&Specialization,
@@ -2832,7 +2803,7 @@ public:
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
QualType ArgFunctionType,
FunctionDecl *&Specialization,
@@ -2863,6 +2834,7 @@ public:
void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
bool OnlyDeduced,
+ unsigned Depth,
llvm::SmallVectorImpl<bool> &Used);
void MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate,
llvm::SmallVectorImpl<bool> &Deduced);
@@ -3101,7 +3073,7 @@ public:
llvm::DenseMap<const Decl *, Decl *> LocalDecls;
/// \brief The outer scope, in which contains local variable
- /// definitions from some other instantiation (that is not
+ /// definitions from some other instantiation (that may not be
/// relevant to this particular scope).
LocalInstantiationScope *Outer;
@@ -3110,9 +3082,13 @@ public:
LocalInstantiationScope &operator=(const LocalInstantiationScope &);
public:
- LocalInstantiationScope(Sema &SemaRef)
+ LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
: SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope) {
- SemaRef.CurrentInstantiationScope = this;
+ if (!CombineWithOuterScope)
+ SemaRef.CurrentInstantiationScope = this;
+ else
+ assert(SemaRef.CurrentInstantiationScope &&
+ "No outer instantiation scope?");
}
~LocalInstantiationScope() {
@@ -3133,6 +3109,11 @@ public:
return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var)));
}
+ NonTypeTemplateParmDecl *getInstantiationOf(
+ const NonTypeTemplateParmDecl *Var) {
+ return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var)));
+ }
+
void InstantiatedLocal(const Decl *D, Decl *Inst) {
Decl *&Stored = LocalDecls[D];
assert(!Stored && "Already instantiated this local");
@@ -3190,7 +3171,7 @@ public:
bool Complain = true);
bool
- InstantiateClassTemplateSpecialization(
+ InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK,
bool Complain = true);
@@ -3213,8 +3194,8 @@ public:
TemplateName
SubstTemplateName(TemplateName Name, SourceLocation Loc,
const MultiLevelTemplateArgumentList &TemplateArgs);
- TemplateArgument Subst(TemplateArgument Arg,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ bool Subst(const TemplateArgumentLoc &Arg, TemplateArgumentLoc &Result,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function,
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index bf396041b473..8bb334855d02 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -83,7 +83,8 @@ static TryCastResult TryStaticDowncast(Sema &Self, QualType SrcType,
static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType,
QualType DestType,bool CStyle,
const SourceRange &OpRange,
- unsigned &msg);
+ unsigned &msg,
+ CastExpr::CastKind &Kind);
static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
@@ -480,7 +481,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr,
// conversion. C++ 5.2.9p9 has additional information.
// DR54's access restrictions apply here also.
tcr = TryStaticMemberPointerUpcast(Self, SrcType, DestType, CStyle,
- OpRange, msg);
+ OpRange, msg, Kind);
if (tcr != TC_NotApplicable)
return tcr;
@@ -706,7 +707,7 @@ TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType,
TryCastResult
TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType,
bool CStyle, const SourceRange &OpRange,
- unsigned &msg) {
+ unsigned &msg, CastExpr::CastKind &Kind) {
const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>();
if (!DestMemPtr)
return TC_NotApplicable;
@@ -760,6 +761,7 @@ TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType,
return TC_Failed;
}
+ Kind = CastExpr::CK_DerivedToBaseMemberPointer;
return TC_Success;
}
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 589b0c6bd0ec..38b6ebeefab9 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -1272,10 +1272,15 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
// Skip over implicit cast expressions when checking for block expressions.
RetValExp = RetValExp->IgnoreParenCasts();
- if (BlockExpr *C = dyn_cast_or_null<BlockExpr>(RetValExp))
+ if (BlockExpr *C = dyn_cast<BlockExpr>(RetValExp))
if (C->hasBlockDeclRefExprs())
Diag(C->getLocStart(), diag::err_ret_local_block)
<< C->getSourceRange();
+
+ if (AddrLabelExpr *ALE = dyn_cast<AddrLabelExpr>(RetValExp))
+ Diag(ALE->getLocStart(), diag::warn_ret_addr_label)
+ << ALE->getSourceRange();
+
} else if (lhsType->isReferenceType()) {
// Perform checking for stack values returned by reference.
// Check for a reference to the stack
@@ -1420,8 +1425,7 @@ static DeclRefExpr* EvalVal(Expr *E) {
// viewed AST node. We then recursively traverse the AST by calling
// EvalAddr and EvalVal appropriately.
switch (E->getStmtClass()) {
- case Stmt::DeclRefExprClass:
- case Stmt::QualifiedDeclRefExprClass: {
+ case Stmt::DeclRefExprClass: {
// DeclRefExpr: the base case. When we hit a DeclRefExpr we are looking
// at code that refers to a variable's name. We check if it has local
// storage within the function, and if so, return the expression.
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 381151325a03..e9df17d6a115 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -13,6 +13,8 @@
#include "Sema.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h"
#include <list>
@@ -801,9 +803,45 @@ void AddQualifierToCompletionString(CodeCompletionString *Result,
/// result is all that is needed.
CodeCompletionString *
CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
- if (Kind != RK_Declaration)
+ if (Kind == RK_Keyword)
return 0;
+ if (Kind == RK_Macro) {
+ MacroInfo *MI = S.PP.getMacroInfo(Macro);
+ if (!MI || !MI->isFunctionLike())
+ return 0;
+
+ // Format a function-like macro with placeholders for the arguments.
+ CodeCompletionString *Result = new CodeCompletionString;
+ Result->AddTextChunk(Macro->getName().str().c_str());
+ Result->AddTextChunk("(");
+ for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
+ A != AEnd; ++A) {
+ if (A != MI->arg_begin())
+ Result->AddTextChunk(", ");
+
+ if (!MI->isVariadic() || A != AEnd - 1) {
+ // Non-variadic argument.
+ Result->AddPlaceholderChunk((*A)->getName().str().c_str());
+ continue;
+ }
+
+ // Variadic argument; cope with the different between GNU and C99
+ // variadic macros, providing a single placeholder for the rest of the
+ // arguments.
+ if ((*A)->isStr("__VA_ARGS__"))
+ Result->AddPlaceholderChunk("...");
+ else {
+ std::string Arg = (*A)->getName();
+ Arg += "...";
+ Result->AddPlaceholderChunk(Arg.c_str());
+ }
+ }
+ Result->AddTextChunk(")");
+ return Result;
+ }
+
+ assert(Kind == RK_Declaration && "Missed a macro kind?");
NamedDecl *ND = Declaration;
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
@@ -999,6 +1037,10 @@ namespace {
case Result::RK_Keyword:
return strcmp(X.Keyword, Y.Keyword) < 0;
+
+ case Result::RK_Macro:
+ return llvm::LowercaseString(X.Macro->getName()) <
+ llvm::LowercaseString(Y.Macro->getName());
}
// Silence GCC warning.
@@ -1007,6 +1049,16 @@ namespace {
};
}
+// Add all of the known macros as code-completion results.
+static void AddMacroResults(Preprocessor &PP, unsigned Rank,
+ ResultBuilder &Results) {
+ Results.EnterNewScope();
+ for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end();
+ M != MEnd; ++M)
+ Results.MaybeAddResult(CodeCompleteConsumer::Result(M->first, Rank));
+ Results.ExitScope();
+}
+
static void HandleCodeCompleteResults(CodeCompleteConsumer *CodeCompleter,
CodeCompleteConsumer::Result *Results,
unsigned NumResults) {
@@ -1019,8 +1071,9 @@ static void HandleCodeCompleteResults(CodeCompleteConsumer *CodeCompleter,
void Sema::CodeCompleteOrdinaryName(Scope *S) {
ResultBuilder Results(*this, &ResultBuilder::IsOrdinaryName);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext,
- Results);
+ unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
+ 0, CurContext, Results);
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1076,6 +1129,9 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
CurContext, Results);
}
+ // Add macros
+ AddMacroResults(PP, NextRank, Results);
+
// Hand off the results found for code completion.
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
@@ -1117,10 +1173,11 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
// We could have the start of a nested-name-specifier. Add those
// results as well.
Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank,
- CurContext, Results);
+ NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
+ NextRank, CurContext, Results);
}
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1171,8 +1228,7 @@ void Sema::CodeCompleteCase(Scope *S) {
// At the XXX, our completions are TagDecl::TK_union,
// TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
// TK_struct, and TK_class.
- if (QualifiedDeclRefExpr *QDRE = dyn_cast<QualifiedDeclRefExpr>(DRE))
- Qualifier = QDRE->getQualifier();
+ Qualifier = DRE->getQualifier();
}
}
@@ -1199,6 +1255,7 @@ void Sema::CodeCompleteCase(Scope *S) {
}
Results.ExitScope();
+ AddMacroResults(PP, 1, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1235,7 +1292,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
SourceRange QualifierRange;
bool ArgumentDependentLookup;
bool HasExplicitTemplateArgs;
- const TemplateArgument *ExplicitTemplateArgs;
+ const TemplateArgumentLoc *ExplicitTemplateArgs;
unsigned NumExplicitTemplateArgs;
DeconstructCallFunction(Fn,
@@ -1293,6 +1350,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS,
if (!Results.empty() && NNS->isDependent())
Results.MaybeAddResult(CodeCompleteConsumer::Result("template", NextRank));
+ AddMacroResults(PP, NextRank + 1, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1309,10 +1367,11 @@ void Sema::CodeCompleteUsing(Scope *S) {
// After "using", we can see anything that would start a
// nested-name-specifier.
- CollectLookupResults(S, Context.getTranslationUnitDecl(), 0,
- CurContext, Results);
+ unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
+ 0, CurContext, Results);
Results.ExitScope();
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1324,9 +1383,10 @@ void Sema::CodeCompleteUsingDirective(Scope *S) {
// alias.
ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
Results.EnterNewScope();
- CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext,
- Results);
+ unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
+ 0, CurContext, Results);
Results.ExitScope();
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1361,6 +1421,7 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Results.ExitScope();
}
+ AddMacroResults(PP, 1, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1370,8 +1431,9 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
// After "namespace", we expect to see a namespace or alias.
ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext,
- Results);
+ unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
+ 0, CurContext, Results);
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1398,10 +1460,11 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
// Add any nested-name-specifiers
Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank + 1,
- CurContext, Results);
+ NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
+ NextRank + 1, CurContext, Results);
Results.ExitScope();
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index b83181becb93..d89cb5fc97f5 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -95,7 +95,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
case LookupResult::FoundOverloaded:
return 0;
- case LookupResult::Ambiguous: {
+ case LookupResult::Ambiguous:
// Recover from type-hiding ambiguities by hiding the type. We'll
// do the lookup again when looking for an object, and we can
// diagnose the error then. If we don't do this, then the error
@@ -131,51 +131,43 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
// perform the name lookup again.
DiagnoseAmbiguousLookup(Result, DeclarationName(&II), NameLoc);
break;
- }
case LookupResult::Found:
IIDecl = Result.getFoundDecl();
break;
}
- if (IIDecl) {
- QualType T;
-
- if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
- // Check whether we can use this type
- (void)DiagnoseUseOfDecl(IIDecl, NameLoc);
-
- if (getLangOptions().CPlusPlus) {
- // C++ [temp.local]p2:
- // Within the scope of a class template specialization or
- // partial specialization, when the injected-class-name is
- // not followed by a <, it is equivalent to the
- // injected-class-name followed by the template-argument s
- // of the class template specialization or partial
- // specialization enclosed in <>.
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD))
- if (RD->isInjectedClassName())
- if (ClassTemplateDecl *Template = RD->getDescribedClassTemplate())
- T = Template->getInjectedClassNameType(Context);
- }
-
- if (T.isNull())
- T = Context.getTypeDeclType(TD);
- } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
- // Check whether we can use this interface.
- (void)DiagnoseUseOfDecl(IIDecl, NameLoc);
-
- T = Context.getObjCInterfaceType(IDecl);
- } else
- return 0;
+ assert(IIDecl && "Didn't find decl");
+ QualType T;
+ if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
+ DiagnoseUseOfDecl(IIDecl, NameLoc);
+
+ // C++ [temp.local]p2:
+ // Within the scope of a class template specialization or
+ // partial specialization, when the injected-class-name is
+ // not followed by a <, it is equivalent to the
+ // injected-class-name followed by the template-argument s
+ // of the class template specialization or partial
+ // specialization enclosed in <>.
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD))
+ if (RD->isInjectedClassName())
+ if (ClassTemplateDecl *Template = RD->getDescribedClassTemplate())
+ T = Template->getInjectedClassNameType(Context);
+
+ if (T.isNull())
+ T = Context.getTypeDeclType(TD);
+
if (SS)
T = getQualifiedNameType(*SS, T);
+
+ } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
+ DiagnoseUseOfDecl(IIDecl, NameLoc);
+ T = Context.getObjCInterfaceType(IDecl);
+ } else
+ return 0;
- return T.getAsOpaquePtr();
- }
-
- return 0;
+ return T.getAsOpaquePtr();
}
/// isTagName() - This method is called *for error recovery purposes only*
@@ -1055,9 +1047,11 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
/// Statement that should return a value.
///
/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
-/// MaybeFallThrough iff we might or might not fall off the end and
-/// NeverFallThrough iff we never fall off the end of the statement. We assume
-/// that functions not marked noreturn will return.
+/// MaybeFallThrough iff we might or might not fall off the end,
+/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
+/// return. We assume NeverFallThrough iff we never fall off the end of the
+/// statement but we may return. We assume that functions not marked noreturn
+/// will return.
Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
// FIXME: Eventually share this CFG object when we have other warnings based
// of the CFG. This can be done using AnalysisContext.
@@ -1065,7 +1059,8 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
// FIXME: They should never return 0, fix that, delete this code.
if (cfg == 0)
- return NeverFallThrough;
+ // FIXME: This should be NeverFallThrough
+ return NeverFallThroughOrReturn;
// The CFG leaves in dead things, and we don't want to dead code paths to
// confuse us, so we mark all live things first.
std::queue<CFGBlock*> workq;
@@ -1094,7 +1089,7 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
bool HasLiveReturn = false;
bool HasFakeEdge = false;
bool HasPlainEdge = false;
- for (CFGBlock::succ_iterator I=cfg->getExit().pred_begin(),
+ for (CFGBlock::pred_iterator I=cfg->getExit().pred_begin(),
E = cfg->getExit().pred_end();
I != E;
++I) {
@@ -1138,8 +1133,11 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
if (NoReturnEdge == false)
HasPlainEdge = true;
}
- if (!HasPlainEdge)
- return NeverFallThrough;
+ if (!HasPlainEdge) {
+ if (HasLiveReturn)
+ return NeverFallThrough;
+ return NeverFallThroughOrReturn;
+ }
if (HasFakeEdge || HasLiveReturn)
return MaybeFallThrough;
// This says AlwaysFallThrough for calls to functions that are not marked
@@ -1161,6 +1159,7 @@ void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body) {
// which this code would then warn about.
if (getDiagnostics().hasErrorOccurred())
return;
+
bool ReturnsVoid = false;
bool HasNoReturn = false;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
@@ -1202,10 +1201,12 @@ void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body) {
else if (!ReturnsVoid)
Diag(Compound->getRBracLoc(), diag::warn_falloff_nonvoid_function);
break;
- case NeverFallThrough:
- if (ReturnsVoid)
+ case NeverFallThroughOrReturn:
+ if (ReturnsVoid && !HasNoReturn)
Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_function);
break;
+ case NeverFallThrough:
+ break;
}
}
}
@@ -1225,7 +1226,7 @@ void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body) {
return;
bool ReturnsVoid = false;
bool HasNoReturn = false;
- if (const FunctionType *FT = BlockTy->getPointeeType()->getAs<FunctionType>()) {
+ if (const FunctionType *FT =BlockTy->getPointeeType()->getAs<FunctionType>()){
if (FT->getResultType()->isVoidType())
ReturnsVoid = true;
if (FT->getNoReturnAttr())
@@ -1253,10 +1254,12 @@ void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body) {
else if (!ReturnsVoid)
Diag(Compound->getRBracLoc(), diag::err_falloff_nonvoid_block);
break;
- case NeverFallThrough:
+ case NeverFallThroughOrReturn:
if (ReturnsVoid)
Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_block);
break;
+ case NeverFallThrough:
+ break;
}
}
}
@@ -1330,6 +1333,10 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
}
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
+ // If there are attributes in the DeclSpec, apply them to the record.
+ if (const AttributeList *AL = DS.getAttributes())
+ ProcessDeclAttributeList(S, Record, AL);
+
if (!Record->getDeclName() && Record->isDefinition() &&
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
if (getLangOptions().CPlusPlus ||
@@ -1602,53 +1609,60 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
/// GetNameForDeclarator - Determine the full declaration name for the
/// given Declarator.
DeclarationName Sema::GetNameForDeclarator(Declarator &D) {
- switch (D.getKind()) {
- case Declarator::DK_Abstract:
- assert(D.getIdentifier() == 0 && "abstract declarators have no name");
- return DeclarationName();
-
- case Declarator::DK_Normal:
- assert (D.getIdentifier() != 0 && "normal declarators have an identifier");
- return DeclarationName(D.getIdentifier());
-
- case Declarator::DK_Constructor: {
- QualType Ty = GetTypeFromParser(D.getDeclaratorIdType());
- return Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(Ty));
- }
-
- case Declarator::DK_Destructor: {
- QualType Ty = GetTypeFromParser(D.getDeclaratorIdType());
- return Context.DeclarationNames.getCXXDestructorName(
- Context.getCanonicalType(Ty));
- }
-
- case Declarator::DK_Conversion: {
- // FIXME: We'd like to keep the non-canonical type for diagnostics!
- QualType Ty = GetTypeFromParser(D.getDeclaratorIdType());
- return Context.DeclarationNames.getCXXConversionFunctionName(
- Context.getCanonicalType(Ty));
- }
+ return GetNameFromUnqualifiedId(D.getName());
+}
- case Declarator::DK_Operator:
- assert(D.getIdentifier() == 0 && "operator names have no identifier");
- return Context.DeclarationNames.getCXXOperatorName(
- D.getOverloadedOperator());
+/// \brief Retrieves the canonicalized name from a parsed unqualified-id.
+DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) {
+ switch (Name.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ return DeclarationName(Name.Identifier);
- case Declarator::DK_TemplateId: {
- TemplateName Name
- = TemplateName::getFromVoidPointer(D.getTemplateId()->Template);
- if (TemplateDecl *Template = Name.getAsTemplateDecl())
- return Template->getDeclName();
- if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl())
- return Ovl->getDeclName();
-
- return DeclarationName();
- }
+ case UnqualifiedId::IK_OperatorFunctionId:
+ return Context.DeclarationNames.getCXXOperatorName(
+ Name.OperatorFunctionId.Operator);
+
+ case UnqualifiedId::IK_ConversionFunctionId: {
+ QualType Ty = GetTypeFromParser(Name.ConversionFunctionId);
+ if (Ty.isNull())
+ return DeclarationName();
+
+ return Context.DeclarationNames.getCXXConversionFunctionName(
+ Context.getCanonicalType(Ty));
+ }
+
+ case UnqualifiedId::IK_ConstructorName: {
+ QualType Ty = GetTypeFromParser(Name.ConstructorName);
+ if (Ty.isNull())
+ return DeclarationName();
+
+ return Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(Ty));
+ }
+
+ case UnqualifiedId::IK_DestructorName: {
+ QualType Ty = GetTypeFromParser(Name.DestructorName);
+ if (Ty.isNull())
+ return DeclarationName();
+
+ return Context.DeclarationNames.getCXXDestructorName(
+ Context.getCanonicalType(Ty));
+ }
+
+ case UnqualifiedId::IK_TemplateId: {
+ TemplateName TName
+ = TemplateName::getFromVoidPointer(Name.TemplateId->Template);
+ if (TemplateDecl *Template = TName.getAsTemplateDecl())
+ return Template->getDeclName();
+ if (OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl())
+ return Ovl->getDeclName();
+
+ return DeclarationName();
+ }
}
-
+
assert(false && "Unknown name kind");
- return DeclarationName();
+ return DeclarationName();
}
/// isNearlyMatchingFunction - Determine whether the C++ functions
@@ -1986,12 +2000,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
- TypedefDecl *NewTD = ParseTypedefDecl(S, D, R);
+ TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, DInfo);
if (!NewTD) return 0;
- if (D.isInvalidType())
- NewTD->setInvalidDecl();
-
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewTD, D);
// Merge the decl with the existing one if appropriate. If the decl is
@@ -2013,7 +2024,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative);
if (!FixedTy.isNull()) {
Diag(D.getIdentifierLoc(), diag::warn_illegal_constant_array_size);
- NewTD->setUnderlyingType(FixedTy);
+ NewTD->setTypeDeclaratorInfo(Context.getTrivialDeclaratorInfo(FixedTy));
} else {
if (SizeIsNegative)
Diag(D.getIdentifierLoc(), diag::err_typecheck_negative_array_size);
@@ -2516,7 +2527,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
isInline |= IsFunctionDefinition;
}
- if (D.getKind() == Declarator::DK_Constructor) {
+ if (Name.getNameKind() == DeclarationName::CXXConstructorName) {
// This is a C++ constructor declaration.
assert(DC->isRecord() &&
"Constructors can only be declared in a member context");
@@ -2529,7 +2540,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
D.getIdentifierLoc(), Name, R, DInfo,
isExplicit, isInline,
/*isImplicitlyDeclared=*/false);
- } else if (D.getKind() == Declarator::DK_Destructor) {
+ } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
// This is a C++ destructor declaration.
if (DC->isRecord()) {
R = CheckDestructorDeclarator(D, SC);
@@ -2551,7 +2562,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
/*hasPrototype=*/true);
D.setInvalidType();
}
- } else if (D.getKind() == Declarator::DK_Conversion) {
+ } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
if (!DC->isRecord()) {
Diag(D.getIdentifierLoc(),
diag::err_conv_function_not_member);
@@ -2795,10 +2806,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// If the declarator is a template-id, translate the parser's template
// argument list into our AST format.
bool HasExplicitTemplateArgs = false;
- llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+ llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
SourceLocation LAngleLoc, RAngleLoc;
- if (D.getKind() == Declarator::DK_TemplateId) {
- TemplateIdAnnotation *TemplateId = D.getTemplateId();
+ if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+ TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
ASTTemplateArgsPtr TemplateArgsPtr(*this,
TemplateId->getTemplateArgs(),
TemplateId->getTemplateArgIsType(),
@@ -3101,7 +3112,7 @@ void Sema::CheckMain(FunctionDecl* FD) {
// C99 6.7.4p4: In a hosted environment, the inline function specifier
// shall not appear in a declaration of main.
// static main is not an error under C99, but we should warn about it.
- bool isInline = FD->isInline();
+ bool isInline = FD->isInlineSpecified();
bool isStatic = FD->getStorageClass() == FunctionDecl::Static;
if (isInline || isStatic) {
unsigned diagID = diag::warn_unusual_main_decl;
@@ -3442,7 +3453,7 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
if (getLangOptions().CPlusPlus) {
QualType InitType = Type;
if (const ArrayType *Array = Context.getAsArrayType(Type))
- InitType = Array->getElementType();
+ InitType = Context.getBaseElementType(Array);
if ((!Var->hasExternalStorage() && !Var->isExternC()) &&
InitType->isRecordType() && !InitType->isDependentType()) {
if (!RequireCompleteType(Var->getLocation(), InitType,
@@ -3465,7 +3476,7 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
else {
// FIXME: Cope with initialization of arrays
if (!Constructor->isTrivial() &&
- InitializeVarWithConstructor(Var, Constructor, InitType,
+ InitializeVarWithConstructor(Var, Constructor,
move_arg(ConstructorArgs)))
Var->setInvalidDecl();
@@ -3626,8 +3637,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
DeclaratorInfo *DInfo = 0;
TagDecl *OwnedDecl = 0;
- QualType parmDeclType = GetTypeForDeclarator(D, S, &DInfo, /*Skip=*/0,
- &OwnedDecl);
+ QualType parmDeclType = GetTypeForDeclarator(D, S, &DInfo, &OwnedDecl);
if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) {
// C++ [dcl.fct]p6:
@@ -3668,16 +3678,9 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
QualType T = adjustParameterType(parmDeclType);
- ParmVarDecl *New;
- if (T == parmDeclType) // parameter type did not need adjustment
- New = ParmVarDecl::Create(Context, CurContext,
- D.getIdentifierLoc(), II,
- parmDeclType, DInfo, StorageClass,
- 0);
- else // keep track of both the adjusted and unadjusted types
- New = OriginalParmVarDecl::Create(Context, CurContext,
- D.getIdentifierLoc(), II, T, DInfo,
- parmDeclType, StorageClass, 0);
+ ParmVarDecl *New
+ = ParmVarDecl::Create(Context, CurContext, D.getIdentifierLoc(), II,
+ T, DInfo, StorageClass, 0);
if (D.isInvalidType())
New->setInvalidDecl();
@@ -3776,6 +3779,9 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
}
Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
+ // Clear the last template instantiation error context.
+ LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation();
+
if (!D)
return D;
FunctionDecl *FD = 0;
@@ -4104,15 +4110,21 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
}
}
-TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T) {
+TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
+ DeclaratorInfo *DInfo) {
assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
+ if (!DInfo) {
+ assert(D.isInvalidType() && "no declarator info for valid type");
+ DInfo = Context.getTrivialDeclaratorInfo(T);
+ }
+
// Scope manipulation handled by caller.
TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext,
D.getIdentifierLoc(),
D.getIdentifier(),
- T);
+ DInfo);
if (const TagType *TT = T->getAs<TagType>()) {
TagDecl *TD = TT->getDecl();
@@ -4321,9 +4333,6 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
if (PrevDecl) {
- // Check whether the previous declaration is usable.
- (void)DiagnoseUseOfDecl(PrevDecl, NameLoc);
-
if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
// If this is a use of a previous tag, or if the tag is already declared
// in the same scope (so that the definition/declaration completes or
@@ -4955,12 +4964,16 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
case CXXDefaultConstructor:
if (RD->hasUserDeclaredConstructor()) {
typedef CXXRecordDecl::ctor_iterator ctor_iter;
- for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce; ++ci)
- if (!ci->isImplicitlyDefined(Context)) {
+ for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce;++ci){
+ const FunctionDecl *body = 0;
+ ci->getBody(body);
+ if (!body ||
+ !cast<CXXConstructorDecl>(body)->isImplicitlyDefined(Context)) {
SourceLocation CtorLoc = ci->getLocation();
Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
return;
}
+ }
assert(0 && "found no user-declared constructors");
return;
@@ -5038,7 +5051,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
// Check for nontrivial bases (and recurse).
for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) {
const RecordType *BaseRT = bi->getType()->getAs<RecordType>();
- assert(BaseRT);
+ assert(BaseRT && "Don't know how to handle dependent bases");
CXXRecordDecl *BaseRecTy = cast<CXXRecordDecl>(BaseRT->getDecl());
if (!(BaseRecTy->*hasTrivial)()) {
SourceLocation BaseLoc = bi->getSourceRange().getBegin();
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 341d49ead418..18f57da76912 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -193,7 +193,8 @@ static void HandleExtVectorTypeAttr(Scope *scope, Decl *d,
// This will run the reguired checks.
QualType T = S.BuildExtVectorType(curType, S.Owned(sizeExpr), Attr.getLoc());
if (!T.isNull()) {
- tDecl->setUnderlyingType(T);
+ // FIXME: preserve the old source info.
+ tDecl->setTypeDeclaratorInfo(S.Context.getTrivialDeclaratorInfo(T));
// Remember this typedef decl, we will need it later for diagnostics.
S.ExtVectorDecls.push_back(tDecl);
@@ -278,8 +279,11 @@ static void HandleVectorSizeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
VD->setType(CurType);
- else
- cast<TypedefDecl>(D)->setUnderlyingType(CurType);
+ else {
+ // FIXME: preserve existing source info.
+ DeclaratorInfo *DInfo = S.Context.getTrivialDeclaratorInfo(CurType);
+ cast<TypedefDecl>(D)->setTypeDeclaratorInfo(DInfo);
+ }
}
static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -897,7 +901,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// Currently, the dllimport attribute is ignored for inlined functions.
// Warning is emitted.
- if (FD->isInline()) {
+ if (FD->isInlineSpecified()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
return;
}
@@ -942,7 +946,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// Currently, the dllexport attribute is ignored for inlined functions, unless
// the -fkeep-inline-functions flag has been used. Warning is emitted;
- if (FD->isInline()) {
+ if (FD->isInlineSpecified()) {
// FIXME: ... unless the -fkeep-inline-functions flag has been used.
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
return;
@@ -1028,6 +1032,22 @@ static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
d->addAttr(::new (S.Context) StdCallAttr());
}
+/// Diagnose the use of a non-standard calling convention on the given
+/// function.
+static void DiagnoseCConv(FunctionDecl *D, const char *CConv,
+ SourceLocation Loc, Sema &S) {
+ if (!D->hasPrototype()) {
+ S.Diag(Loc, diag::err_cconv_knr) << CConv;
+ return;
+ }
+
+ const FunctionProtoType *T = D->getType()->getAs<FunctionProtoType>();
+ if (T->isVariadic()) {
+ S.Diag(Loc, diag::err_cconv_varargs) << CConv;
+ return;
+ }
+}
+
static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// Attribute has no arguments.
if (Attr.getNumArgs() != 0) {
@@ -1041,6 +1061,8 @@ static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
+ DiagnoseCConv(cast<FunctionDecl>(d), "fastcall", Attr.getLoc(), S);
+
// stdcall and fastcall attributes are mutually incompatible.
if (d->getAttr<StdCallAttr>()) {
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
@@ -1636,9 +1658,10 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
}
// Install the new type.
- if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
- TD->setUnderlyingType(NewTy);
- else
+ if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+ // FIXME: preserve existing source info.
+ TD->setTypeDeclaratorInfo(S.Context.getTrivialDeclaratorInfo(NewTy));
+ } else
cast<ValueDecl>(D)->setType(NewTy);
}
@@ -1688,7 +1711,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- if (!Fn->isInline()) {
+ if (!Fn->isInlineSpecified()) {
S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
return;
}
@@ -1944,3 +1967,62 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
if (const AttributeList *Attrs = PD.getAttributes())
ProcessDeclAttributeList(S, D, Attrs);
}
+
+/// PushParsingDeclaration - Enter a new "scope" of deprecation
+/// warnings.
+///
+/// The state token we use is the start index of this scope
+/// on the warning stack.
+Action::ParsingDeclStackState Sema::PushParsingDeclaration() {
+ ParsingDeclDepth++;
+ return (ParsingDeclStackState) DelayedDeprecationWarnings.size();
+}
+
+static bool isDeclDeprecated(Decl *D) {
+ do {
+ if (D->hasAttr<DeprecatedAttr>())
+ return true;
+ } while ((D = cast_or_null<Decl>(D->getDeclContext())));
+ return false;
+}
+
+void Sema::PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy Ctx) {
+ assert(ParsingDeclDepth > 0 && "empty ParsingDeclaration stack");
+ ParsingDeclDepth--;
+
+ if (DelayedDeprecationWarnings.empty())
+ return;
+
+ unsigned SavedIndex = (unsigned) S;
+ assert(SavedIndex <= DelayedDeprecationWarnings.size() &&
+ "saved index is out of bounds");
+
+ if (Ctx && !isDeclDeprecated(Ctx.getAs<Decl>())) {
+ for (unsigned I = 0, E = DelayedDeprecationWarnings.size(); I != E; ++I) {
+ SourceLocation Loc = DelayedDeprecationWarnings[I].first;
+ NamedDecl *&ND = DelayedDeprecationWarnings[I].second;
+ if (ND) {
+ Diag(Loc, diag::warn_deprecated) << ND->getDeclName();
+
+ // Prevent this from triggering multiple times.
+ ND = 0;
+ }
+ }
+ }
+
+ DelayedDeprecationWarnings.set_size(SavedIndex);
+}
+
+void Sema::EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc) {
+ // Delay if we're currently parsing a declaration.
+ if (ParsingDeclDepth) {
+ DelayedDeprecationWarnings.push_back(std::make_pair(Loc, D));
+ return;
+ }
+
+ // Otherwise, don't warn if our current context is deprecated.
+ if (isDeclDeprecated(cast<Decl>(CurContext)))
+ return;
+
+ Diag(Loc, diag::warn_deprecated) << D->getDeclName();
+}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 6d1f4ea4a865..bc255137fccf 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1123,7 +1123,7 @@ Sema::BuildBaseInitializer(QualType BaseType, Expr **Args,
}
void
-Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
+Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
CXXBaseOrMemberInitializer **Initializers,
unsigned NumInitializers,
llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases,
@@ -1179,7 +1179,7 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
- assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null");
+ assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null");
if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context))
MarkDeclarationReferenced(Value->getSourceLocation(), Ctor);
AllToInit.push_back(Value);
@@ -1187,18 +1187,26 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
else {
CXXRecordDecl *VBaseDecl =
cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
- assert(VBaseDecl && "setBaseOrMemberInitializers - VBaseDecl null");
+ assert(VBaseDecl && "SetBaseOrMemberInitializers - VBaseDecl null");
CXXConstructorDecl *Ctor = VBaseDecl->getDefaultConstructor(Context);
- if (!Ctor)
+ if (!Ctor) {
Bases.push_back(VBase);
- else
- MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
+ continue;
+ }
+ ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
+ if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0),
+ Constructor->getLocation(), CtorArgs))
+ continue;
+
+ MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
+
CXXBaseOrMemberInitializer *Member =
- new (Context) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0,
- Ctor,
- SourceLocation(),
- SourceLocation());
+ new (Context) CXXBaseOrMemberInitializer(VBase->getType(),
+ CtorArgs.takeAs<Expr>(),
+ CtorArgs.size(), Ctor,
+ SourceLocation(),
+ SourceLocation());
AllToInit.push_back(Member);
}
}
@@ -1216,7 +1224,7 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null");
+ assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null");
if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context))
MarkDeclarationReferenced(Value->getSourceLocation(), Ctor);
AllToInit.push_back(Value);
@@ -1224,18 +1232,26 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
else {
CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null");
+ assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null");
CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context);
- if (!Ctor)
+ if (!Ctor) {
Bases.push_back(Base);
- else
- MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
+ continue;
+ }
+
+ ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
+ if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0),
+ Constructor->getLocation(), CtorArgs))
+ continue;
+
+ MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
CXXBaseOrMemberInitializer *Member =
- new (Context) CXXBaseOrMemberInitializer(Base->getType(), 0, 0,
- BaseDecl->getDefaultConstructor(Context),
- SourceLocation(),
- SourceLocation());
+ new (Context) CXXBaseOrMemberInitializer(Base->getType(),
+ CtorArgs.takeAs<Expr>(),
+ CtorArgs.size(), Ctor,
+ SourceLocation(),
+ SourceLocation());
AllToInit.push_back(Member);
}
}
@@ -1268,7 +1284,7 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
QualType FT = (*Field)->getType();
if (const RecordType* RT = FT->getAs<RecordType>()) {
CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RT->getDecl());
- assert(FieldRecDecl && "setBaseOrMemberInitializers - BaseDecl null");
+ assert(FieldRecDecl && "SetBaseOrMemberInitializers - BaseDecl null");
if (CXXConstructorDecl *Ctor =
FieldRecDecl->getDefaultConstructor(Context))
MarkDeclarationReferenced(Value->getSourceLocation(), Ctor);
@@ -1281,13 +1297,22 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
if (const RecordType* RT = FT->getAs<RecordType>()) {
CXXConstructorDecl *Ctor =
cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context);
- if (!Ctor && !FT->isDependentType())
+ if (!Ctor && !FT->isDependentType()) {
Fields.push_back(*Field);
+ continue;
+ }
+
+ ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
+ if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0),
+ Constructor->getLocation(), CtorArgs))
+ continue;
+
CXXBaseOrMemberInitializer *Member =
- new (Context) CXXBaseOrMemberInitializer((*Field), 0, 0,
- Ctor,
- SourceLocation(),
- SourceLocation());
+ new (Context) CXXBaseOrMemberInitializer(*Field,CtorArgs.takeAs<Expr>(),
+ CtorArgs.size(), Ctor,
+ SourceLocation(),
+ SourceLocation());
+
AllToInit.push_back(Member);
if (Ctor)
MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
@@ -1327,10 +1352,10 @@ Sema::BuildBaseOrMemberInitializers(ASTContext &C,
CXXBaseOrMemberInitializer **Initializers,
unsigned NumInitializers
) {
- llvm::SmallVector<CXXBaseSpecifier *, 4>Bases;
- llvm::SmallVector<FieldDecl *, 4>Members;
+ llvm::SmallVector<CXXBaseSpecifier *, 4> Bases;
+ llvm::SmallVector<FieldDecl *, 4> Members;
- setBaseOrMemberInitializers(Constructor,
+ SetBaseOrMemberInitializers(Constructor,
Initializers, NumInitializers, Bases, Members);
for (unsigned int i = 0; i < Bases.size(); i++)
Diag(Bases[i]->getSourceRange().getBegin(),
@@ -1976,6 +2001,8 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
// and
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
HasConstCopyAssignment && Base != ClassDecl->bases_end(); ++Base) {
+ assert(!Base->getType()->isDependentType() &&
+ "Cannot generate implicit members for class with dependent bases.");
const CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
const CXXMethodDecl *MD = 0;
@@ -2268,7 +2295,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D,
// (7.1.3); however, a typedef-name that names a class shall not
// be used as the identifier in the declarator for a destructor
// declaration.
- QualType DeclaratorType = GetTypeFromParser(D.getDeclaratorIdType());
+ QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName);
if (isa<TypedefType>(DeclaratorType)) {
Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
<< DeclaratorType;
@@ -2394,7 +2421,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
// C++ [class.conv.fct]p4:
// The conversion-type-id shall not represent a function type nor
// an array type.
- QualType ConvType = GetTypeFromParser(D.getDeclaratorIdType());
+ QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId);
if (ConvType->isArrayType()) {
Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array);
ConvType = Context.getPointerType(ConvType);
@@ -3152,10 +3179,9 @@ Sema::BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Constructor,
bool Sema::InitializeVarWithConstructor(VarDecl *VD,
CXXConstructorDecl *Constructor,
- QualType DeclInitType,
MultiExprArg Exprs) {
OwningExprResult TempResult =
- BuildCXXConstructExpr(VD->getLocation(), DeclInitType, Constructor,
+ BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor,
move(Exprs));
if (TempResult.isInvalid())
return true;
@@ -3235,7 +3261,7 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
// class type.
QualType DeclInitType = VDecl->getType();
if (const ArrayType *Array = Context.getAsArrayType(DeclInitType))
- DeclInitType = Array->getElementType();
+ DeclInitType = Context.getBaseElementType(Array);
// FIXME: This isn't the right place to complete the type.
if (RequireCompleteType(VDecl->getLocation(), VDecl->getType(),
@@ -3260,7 +3286,7 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
RealDecl->setInvalidDecl();
else {
VDecl->setCXXDirectInitializer(true);
- if (InitializeVarWithConstructor(VDecl, Constructor, DeclInitType,
+ if (InitializeVarWithConstructor(VDecl, Constructor,
move_arg(ConstructorArgs)))
RealDecl->setInvalidDecl();
FinalizeVarWithDestructor(VDecl, DeclInitType);
@@ -4269,8 +4295,7 @@ Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
/// We permit this as a special case; if there are any template
/// parameters present at all, require proper matching, i.e.
/// template <> template <class T> friend class A<int>::B;
-Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S,
- const DeclSpec &DS,
+Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
MultiTemplateParamsArg TempParams) {
SourceLocation Loc = DS.getSourceRange().getBegin();
@@ -4280,9 +4305,10 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S,
// Try to convert the decl specifier to a type. This works for
// friend templates because ActOnTag never produces a ClassTemplateDecl
// for a TUK_Friend.
- bool invalid = false;
- QualType T = ConvertDeclSpecToType(DS, Loc, invalid);
- if (invalid) return DeclPtrTy();
+ Declarator TheDeclarator(DS, Declarator::MemberContext);
+ QualType T = GetTypeForDeclarator(TheDeclarator, S);
+ if (TheDeclarator.isInvalidType())
+ return DeclPtrTy();
// This is definitely an error in C++98. It's probably meant to
// be forbidden in C++0x, too, but the specification is just
@@ -4489,12 +4515,12 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
if (DC->isFileContext()) {
// This implies that it has to be an operator or function.
- if (D.getKind() == Declarator::DK_Constructor ||
- D.getKind() == Declarator::DK_Destructor ||
- D.getKind() == Declarator::DK_Conversion) {
+ if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ||
+ D.getName().getKind() == UnqualifiedId::IK_DestructorName ||
+ D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) {
Diag(Loc, diag::err_introducing_special_friend) <<
- (D.getKind() == Declarator::DK_Constructor ? 0 :
- D.getKind() == Declarator::DK_Destructor ? 1 : 2);
+ (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 :
+ D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2);
return DeclPtrTy();
}
}
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 22a517934c7e..93f8d0dc37c1 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1707,29 +1707,22 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
llvm::SmallVector<ParmVarDecl*, 16> Params;
for (unsigned i = 0, e = Sel.getNumArgs(); i != e; ++i) {
- QualType ArgType, UnpromotedArgType;
+ QualType ArgType;
+ DeclaratorInfo *DI;
if (ArgInfo[i].Type == 0) {
- UnpromotedArgType = ArgType = Context.getObjCIdType();
+ ArgType = Context.getObjCIdType();
+ DI = 0;
} else {
- UnpromotedArgType = ArgType = GetTypeFromParser(ArgInfo[i].Type);
+ ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI);
// Perform the default array/function conversions (C99 6.7.5.3p[7,8]).
ArgType = adjustParameterType(ArgType);
}
- ParmVarDecl* Param;
- if (ArgType == UnpromotedArgType)
- Param = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc,
- ArgInfo[i].Name, ArgType,
- /*DInfo=*/0, //FIXME: Pass info here.
- VarDecl::None, 0);
- else
- Param = OriginalParmVarDecl::Create(Context, ObjCMethod,
- ArgInfo[i].NameLoc,
- ArgInfo[i].Name, ArgType,
- /*DInfo=*/0, //FIXME: Pass info here.
- UnpromotedArgType,
- VarDecl::None, 0);
+ ParmVarDecl* Param
+ = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc,
+ ArgInfo[i].Name, ArgType, DI,
+ VarDecl::None, 0);
if (ArgType->isObjCInterfaceType()) {
Diag(ArgInfo[i].NameLoc,
@@ -1755,6 +1748,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
if (AttrList)
ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
+ const ObjCMethodDecl *InterfaceMD = 0;
+
// For implementations (which can be very "coarse grain"), we add the
// method now. This allows the AST to implement lookup methods that work
// incrementally (without waiting until we parse the @end). It also allows
@@ -1768,6 +1763,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
PrevMethod = ImpDecl->getClassMethod(Sel);
ImpDecl->addClassMethod(ObjCMethod);
}
+ InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel,
+ MethodType == tok::minus);
if (AttrList)
Diag(EndLoc, diag::warn_attribute_method_def);
} else if (ObjCCategoryImplDecl *CatImpDecl =
@@ -1788,6 +1785,12 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
<< ObjCMethod->getDeclName();
Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
}
+
+ // If the interface declared this method, and it was deprecated there,
+ // mark it deprecated here.
+ if (InterfaceMD && InterfaceMD->hasAttr<DeprecatedAttr>())
+ ObjCMethod->addAttr(::new (Context) DeprecatedAttr());
+
return DeclPtrTy::make(ObjCMethod);
}
@@ -1900,33 +1903,34 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
// handling.
if ((CCPrimary = CDecl->getClassInterface())) {
// Find the property in continuation class's primary class only.
- ObjCPropertyDecl *PIDecl = 0;
IdentifierInfo *PropertyId = FD.D.getIdentifier();
- for (ObjCInterfaceDecl::prop_iterator
- I = CCPrimary->prop_begin(), E = CCPrimary->prop_end();
- I != E; ++I)
- if ((*I)->getIdentifier() == PropertyId) {
- PIDecl = *I;
- break;
- }
-
- if (PIDecl) {
+ if (ObjCPropertyDecl *PIDecl =
+ CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId)) {
// property 'PIDecl's readonly attribute will be over-ridden
// with continuation class's readwrite property attribute!
unsigned PIkind = PIDecl->getPropertyAttributes();
if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
- if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) !=
- (PIkind & ObjCPropertyDecl::OBJC_PR_nonatomic))
+ unsigned assignRetainCopyNonatomic =
+ (ObjCPropertyDecl::OBJC_PR_assign |
+ ObjCPropertyDecl::OBJC_PR_retain |
+ ObjCPropertyDecl::OBJC_PR_copy |
+ ObjCPropertyDecl::OBJC_PR_nonatomic);
+ if ((Attributes & assignRetainCopyNonatomic) !=
+ (PIkind & assignRetainCopyNonatomic)) {
Diag(AtLoc, diag::warn_property_attr_mismatch);
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ }
PIDecl->makeitReadWriteAttribute();
if (Attributes & ObjCDeclSpec::DQ_PR_retain)
PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
if (Attributes & ObjCDeclSpec::DQ_PR_copy)
PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
PIDecl->setSetterName(SetterSel);
- } else
+ } else {
Diag(AtLoc, diag::err_use_continuation_class)
<< CCPrimary->getDeclName();
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ }
*isOverridingProperty = true;
// Make sure setter decl is synthesized, and added to primary
// class's list.
@@ -2054,6 +2058,14 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
return DeclPtrTy();
}
+ if (const ObjCCategoryDecl *CD =
+ dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
+ if (CD->getIdentifier()) {
+ Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
+ Diag(property->getLocation(), diag::note_property_declare);
+ return DeclPtrTy();
+ }
+ }
} else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
if (Synthesize) {
Diag(AtLoc, diag::error_synthesize_category_decl);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index ae45429952c7..ac7cced2eaef 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -37,40 +37,24 @@ using namespace clang;
/// used, or produce an error (and return true) if a C++0x deleted
/// function is being used.
///
+/// If IgnoreDeprecated is set to true, this should not want about deprecated
+/// decls.
+///
/// \returns true if there was an error (this declaration cannot be
/// referenced), false otherwise.
+///
bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
// See if the decl is deprecated.
if (D->getAttr<DeprecatedAttr>()) {
- // Implementing deprecated stuff requires referencing deprecated
- // stuff. Don't warn if we are implementing a deprecated
- // construct.
- bool isSilenced = false;
-
- if (NamedDecl *ND = getCurFunctionOrMethodDecl()) {
- // If this reference happens *in* a deprecated function or method, don't
- // warn.
- isSilenced = ND->getAttr<DeprecatedAttr>();
-
- // If this is an Objective-C method implementation, check to see if the
- // method was deprecated on the declaration, not the definition.
- if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ND)) {
- // The semantic decl context of a ObjCMethodDecl is the
- // ObjCImplementationDecl.
- if (ObjCImplementationDecl *Impl
- = dyn_cast<ObjCImplementationDecl>(MD->getParent())) {
-
- MD = Impl->getClassInterface()->getMethod(MD->getSelector(),
- MD->isInstanceMethod());
- isSilenced |= MD && MD->getAttr<DeprecatedAttr>();
- }
- }
- }
-
- if (!isSilenced)
- Diag(Loc, diag::warn_deprecated) << D->getDeclName();
+ EmitDeprecationWarning(D, Loc);
}
+ // See if the decl is unavailable
+ if (D->getAttr<UnavailableAttr>()) {
+ Diag(Loc, diag::warn_unavailable) << D->getDeclName();
+ Diag(D->getLocation(), diag::note_unavailable_here) << 0;
+ }
+
// See if this is a deleted function.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isDeleted()) {
@@ -80,12 +64,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
}
}
- // See if the decl is unavailable
- if (D->getAttr<UnavailableAttr>()) {
- Diag(Loc, diag::warn_unavailable) << D->getDeclName();
- Diag(D->getLocation(), diag::note_unavailable_here) << 0;
- }
-
return false;
}
@@ -432,23 +410,7 @@ static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock,
-/// ActOnIdentifierExpr - The parser read an identifier in expression context,
-/// validate it per-C99 6.5.1. HasTrailingLParen indicates whether this
-/// identifier is used in a function call context.
-/// SS is only used for a C++ qualified-id (foo::bar) to indicate the
-/// class or namespace that the identifier must be a member of.
-Sema::OwningExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
- IdentifierInfo &II,
- bool HasTrailingLParen,
- const CXXScopeSpec *SS,
- bool isAddressOfOperand) {
- return ActOnDeclarationNameExpr(S, Loc, &II, HasTrailingLParen, SS,
- isAddressOfOperand);
-}
-
-/// BuildDeclRefExpr - Build either a DeclRefExpr or a
-/// QualifiedDeclRefExpr based on whether or not SS is a
-/// nested-name-specifier.
+/// BuildDeclRefExpr - Build a DeclRefExpr.
Sema::OwningExprResult
Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
bool TypeDependent, bool ValueDependent,
@@ -476,15 +438,11 @@ Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
MarkDeclarationReferenced(Loc, D);
- Expr *E;
- if (SS && !SS->isEmpty()) {
- E = new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent,
- ValueDependent, SS->getRange(),
- static_cast<NestedNameSpecifier *>(SS->getScopeRep()));
- } else
- E = new (Context) DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent);
-
- return Owned(E);
+ return Owned(DeclRefExpr::Create(Context,
+ SS? (NestedNameSpecifier *)SS->getScopeRep() : 0,
+ SS? SS->getRange() : SourceRange(),
+ D, Loc,
+ Ty, TypeDependent, ValueDependent));
}
/// getObjectForAnonymousRecordDecl - Retrieve the (unnamed) field or
@@ -656,15 +614,43 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
return Owned(Result);
}
+Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ bool HasTrailingLParen,
+ bool IsAddressOfOperand) {
+ if (Name.getKind() == UnqualifiedId::IK_TemplateId) {
+ ASTTemplateArgsPtr TemplateArgsPtr(*this,
+ Name.TemplateId->getTemplateArgs(),
+ Name.TemplateId->getTemplateArgIsType(),
+ Name.TemplateId->NumArgs);
+ return ActOnTemplateIdExpr(SS,
+ TemplateTy::make(Name.TemplateId->Template),
+ Name.TemplateId->TemplateNameLoc,
+ Name.TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ Name.TemplateId->getTemplateArgLocations(),
+ Name.TemplateId->RAngleLoc);
+ }
+
+ // FIXME: We lose a bunch of source information by doing this. Later,
+ // we'll want to merge ActOnDeclarationNameExpr's logic into
+ // ActOnIdExpression.
+ return ActOnDeclarationNameExpr(S,
+ Name.StartLocation,
+ GetNameFromUnqualifiedId(Name),
+ HasTrailingLParen,
+ &SS,
+ IsAddressOfOperand);
+}
+
/// ActOnDeclarationNameExpr - The parser has read some kind of name
/// (e.g., a C++ id-expression (C++ [expr.prim]p1)). This routine
/// performs lookup on that name and returns an expression that refers
/// to that name. This routine isn't directly called from the parser,
/// because the parser doesn't know about DeclarationName. Rather,
-/// this routine is called by ActOnIdentifierExpr,
-/// ActOnOperatorFunctionIdExpr, and ActOnConversionFunctionExpr,
-/// which form the DeclarationName from the corresponding syntactic
-/// forms.
+/// this routine is called by ActOnIdExpression, which contains a
+/// parsed UnqualifiedId.
///
/// HasTrailingLParen indicates whether this identifier is used in a
/// function call context. LookupCtx is only used for a C++
@@ -745,8 +731,11 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// FIXME: This should use a new expr for a direct reference, don't
// turn this into Self->ivar, just return a BareIVarExpr or something.
IdentifierInfo &II = Context.Idents.get("self");
- OwningExprResult SelfExpr = ActOnIdentifierExpr(S, SourceLocation(),
- II, false);
+ UnqualifiedId SelfName;
+ SelfName.setIdentifier(&II, SourceLocation());
+ CXXScopeSpec SelfScopeSpec;
+ OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec,
+ SelfName, false, false);
MarkDeclarationReferenced(Loc, IV);
return Owned(new (Context)
ObjCIvarRefExpr(IV, IV->getType(), Loc,
@@ -1083,7 +1072,8 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,
// - a constant with integral or enumeration type and is
// initialized with an expression that is value-dependent
else if (const VarDecl *Dcl = dyn_cast<VarDecl>(VD)) {
- if (Dcl->getType().getCVRQualifiers() == Qualifiers::Const &&
+ if (Context.getCanonicalType(Dcl->getType()).getCVRQualifiers()
+ == Qualifiers::Const &&
Dcl->getInit()) {
ValueDependent = Dcl->getInit()->isValueDependent();
}
@@ -1300,7 +1290,7 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
return false;
// C99 6.5.3.4p1:
- if (isa<FunctionType>(exprType)) {
+ if (exprType->isFunctionType()) {
// alignof(function) is allowed as an extension.
if (isSizeof)
Diag(OpLoc, diag::ext_sizeof_function_type) << ExprRange;
@@ -1358,17 +1348,20 @@ bool Sema::CheckAlignOfExpr(Expr *E, SourceLocation OpLoc,
/// \brief Build a sizeof or alignof expression given a type operand.
Action::OwningExprResult
-Sema::CreateSizeOfAlignOfExpr(QualType T, SourceLocation OpLoc,
+Sema::CreateSizeOfAlignOfExpr(DeclaratorInfo *DInfo,
+ SourceLocation OpLoc,
bool isSizeOf, SourceRange R) {
- if (T.isNull())
+ if (!DInfo)
return ExprError();
+ QualType T = DInfo->getType();
+
if (!T->isDependentType() &&
CheckSizeOfAlignOfOperand(T, OpLoc, R, isSizeOf))
return ExprError();
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
- return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, T,
+ return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, DInfo,
Context.getSizeType(), OpLoc,
R.getEnd()));
}
@@ -1410,12 +1403,11 @@ Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
if (TyOrEx == 0) return ExprError();
if (isType) {
- // FIXME: Preserve type source info.
- QualType ArgTy = GetTypeFromParser(TyOrEx);
- return CreateSizeOfAlignOfExpr(ArgTy, OpLoc, isSizeof, ArgRange);
+ DeclaratorInfo *DInfo;
+ (void) GetTypeFromParser(TyOrEx, &DInfo);
+ return CreateSizeOfAlignOfExpr(DInfo, OpLoc, isSizeof, ArgRange);
}
- // Get the end location.
Expr *ArgEx = (Expr *)TyOrEx;
Action::OwningExprResult Result
= CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange());
@@ -1602,103 +1594,18 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,
LHSExp->getType()->isEnumeralType() ||
RHSExp->getType()->isRecordType() ||
RHSExp->getType()->isEnumeralType())) {
- // Add the appropriate overloaded operators (C++ [over.match.oper])
- // to the candidate set.
- OverloadCandidateSet CandidateSet;
- Expr *Args[2] = { LHSExp, RHSExp };
- AddOperatorCandidates(OO_Subscript, S, LLoc, Args, 2, CandidateSet,
- SourceRange(LLoc, RLoc));
-
- // Perform overload resolution.
- OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, LLoc, Best)) {
- case OR_Success: {
- // We found a built-in operator or an overloaded operator.
- FunctionDecl *FnDecl = Best->Function;
-
- if (FnDecl) {
- // We matched an overloaded operator. Build a call to that
- // operator.
-
- // Convert the arguments.
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
- if (PerformObjectArgumentInitialization(LHSExp, Method) ||
- PerformCopyInitialization(RHSExp,
- FnDecl->getParamDecl(0)->getType(),
- "passing"))
- return ExprError();
- } else {
- // Convert the arguments.
- if (PerformCopyInitialization(LHSExp,
- FnDecl->getParamDecl(0)->getType(),
- "passing") ||
- PerformCopyInitialization(RHSExp,
- FnDecl->getParamDecl(1)->getType(),
- "passing"))
- return ExprError();
- }
-
- // Determine the result type
- QualType ResultTy = FnDecl->getResultType().getNonReferenceType();
-
- // Build the actual expression node.
- Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
- SourceLocation());
- UsualUnaryConversions(FnExpr);
-
- Base.release();
- Idx.release();
- Args[0] = LHSExp;
- Args[1] = RHSExp;
-
- ExprOwningPtr<CXXOperatorCallExpr>
- TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
- FnExpr, Args, 2,
- ResultTy, RLoc));
- if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall.get(),
- FnDecl))
- return ExprError();
-
- return Owned(TheCall.release());
- } else {
- // We matched a built-in operator. Convert the arguments, then
- // break out so that we will build the appropriate built-in
- // operator node.
- if (PerformCopyInitialization(LHSExp, Best->BuiltinTypes.ParamTypes[0],
- "passing") ||
- PerformCopyInitialization(RHSExp, Best->BuiltinTypes.ParamTypes[1],
- "passing"))
- return ExprError();
-
- break;
- }
- }
-
- case OR_No_Viable_Function:
- // No viable function; fall through to handling this as a
- // built-in operator, which will produce an error message for us.
- break;
+ return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, move(Base),move(Idx));
+ }
- case OR_Ambiguous:
- Diag(LLoc, diag::err_ovl_ambiguous_oper)
- << "[]"
- << LHSExp->getSourceRange() << RHSExp->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
- return ExprError();
+ return CreateBuiltinArraySubscriptExpr(move(Base), LLoc, move(Idx), RLoc);
+}
- case OR_Deleted:
- Diag(LLoc, diag::err_ovl_deleted_oper)
- << Best->Function->isDeleted()
- << "[]"
- << LHSExp->getSourceRange() << RHSExp->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
- return ExprError();
- }
- // Either we found no viable overloaded operator or we matched a
- // built-in operator. In either case, fall through to trying to
- // build a built-in operation.
- }
+Action::OwningExprResult
+Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc,
+ ExprArg Idx, SourceLocation RLoc) {
+ Expr *LHSExp = static_cast<Expr*>(Base.get());
+ Expr *RHSExp = static_cast<Expr*>(Idx.get());
// Perform default conversions.
DefaultFunctionArrayConversion(LHSExp);
@@ -1961,7 +1868,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
DeclarationName MemberName,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS,
@@ -2549,13 +2456,77 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
return ExprError();
}
-Action::OwningExprResult
-Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
- tok::TokenKind OpKind, SourceLocation MemberLoc,
- IdentifierInfo &Member,
- DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS) {
- return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, MemberLoc,
- DeclarationName(&Member), ObjCImpDecl, SS);
+Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Member,
+ DeclPtrTy ObjCImpDecl,
+ bool HasTrailingLParen) {
+ if (Member.getKind() == UnqualifiedId::IK_TemplateId) {
+ TemplateName Template
+ = TemplateName::getFromVoidPointer(Member.TemplateId->Template);
+
+ // FIXME: We're going to end up looking up the template based on its name,
+ // twice!
+ DeclarationName Name;
+ if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl())
+ Name = ActualTemplate->getDeclName();
+ else if (OverloadedFunctionDecl *Ovl = Template.getAsOverloadedFunctionDecl())
+ Name = Ovl->getDeclName();
+ else {
+ DependentTemplateName *DTN = Template.getAsDependentTemplateName();
+ if (DTN->isIdentifier())
+ Name = DTN->getIdentifier();
+ else
+ Name = Context.DeclarationNames.getCXXOperatorName(DTN->getOperator());
+ }
+
+ // Translate the parser's template argument list in our AST format.
+ ASTTemplateArgsPtr TemplateArgsPtr(*this,
+ Member.TemplateId->getTemplateArgs(),
+ Member.TemplateId->getTemplateArgIsType(),
+ Member.TemplateId->NumArgs);
+
+ llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
+ translateTemplateArguments(TemplateArgsPtr,
+ Member.TemplateId->getTemplateArgLocations(),
+ TemplateArgs);
+ TemplateArgsPtr.release();
+
+ // Do we have the save the actual template name? We might need it...
+ return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind,
+ Member.TemplateId->TemplateNameLoc,
+ Name, true, Member.TemplateId->LAngleLoc,
+ TemplateArgs.data(), TemplateArgs.size(),
+ Member.TemplateId->RAngleLoc, DeclPtrTy(),
+ &SS);
+ }
+
+ // FIXME: We lose a lot of source information by mapping directly to the
+ // DeclarationName.
+ OwningExprResult Result
+ = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind,
+ Member.getSourceRange().getBegin(),
+ GetNameFromUnqualifiedId(Member),
+ ObjCImpDecl, &SS);
+
+ if (Result.isInvalid() || HasTrailingLParen ||
+ Member.getKind() != UnqualifiedId::IK_DestructorName)
+ return move(Result);
+
+ // The only way a reference to a destructor can be used is to
+ // immediately call them. Since the next token is not a '(', produce a
+ // diagnostic and build the call now.
+ Expr *E = (Expr *)Result.get();
+ SourceLocation ExpectedLParenLoc
+ = PP.getLocForEndOfToken(Member.getSourceRange().getEnd());
+ Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
+ << isa<CXXPseudoDestructorExpr>(E)
+ << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()");
+
+ return ActOnCallExpr(0, move(Result), ExpectedLParenLoc,
+ MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc);
}
Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
@@ -2713,7 +2684,7 @@ void Sema::DeconstructCallFunction(Expr *FnExpr,
SourceRange &QualifierRange,
bool &ArgumentDependentLookup,
bool &HasExplicitTemplateArguments,
- const TemplateArgument *&ExplicitTemplateArgs,
+ const TemplateArgumentLoc *&ExplicitTemplateArgs,
unsigned &NumExplicitTemplateArgs) {
// Set defaults for all of the output parameters.
Function = 0;
@@ -2738,16 +2709,12 @@ void Sema::DeconstructCallFunction(Expr *FnExpr,
cast<UnaryOperator>(FnExpr)->getOpcode()
== UnaryOperator::AddrOf) {
FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr();
- } else if (QualifiedDeclRefExpr *QDRExpr
- = dyn_cast<QualifiedDeclRefExpr>(FnExpr)) {
- // Qualified names disable ADL (C++0x [basic.lookup.argdep]p1).
- ArgumentDependentLookup = false;
- Qualifier = QDRExpr->getQualifier();
- QualifierRange = QDRExpr->getQualifierRange();
- Function = dyn_cast<NamedDecl>(QDRExpr->getDecl());
- break;
} else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) {
Function = dyn_cast<NamedDecl>(DRExpr->getDecl());
+ if ((Qualifier = DRExpr->getQualifier())) {
+ ArgumentDependentLookup = false;
+ QualifierRange = DRExpr->getQualifierRange();
+ }
break;
} else if (UnresolvedFunctionNameExpr *DepName
= dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) {
@@ -2866,24 +2833,29 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Fn->IgnoreParens())) {
if (BO->getOpcode() == BinaryOperator::PtrMemD ||
BO->getOpcode() == BinaryOperator::PtrMemI) {
- const FunctionProtoType *FPT = cast<FunctionProtoType>(BO->getType());
- QualType ResultTy = FPT->getResultType().getNonReferenceType();
+ if (const FunctionProtoType *FPT =
+ dyn_cast<FunctionProtoType>(BO->getType())) {
+ QualType ResultTy = FPT->getResultType().getNonReferenceType();
- ExprOwningPtr<CXXMemberCallExpr>
- TheCall(this, new (Context) CXXMemberCallExpr(Context, BO, Args,
- NumArgs, ResultTy,
- RParenLoc));
+ ExprOwningPtr<CXXMemberCallExpr>
+ TheCall(this, new (Context) CXXMemberCallExpr(Context, BO, Args,
+ NumArgs, ResultTy,
+ RParenLoc));
- if (CheckCallReturnType(FPT->getResultType(),
- BO->getRHS()->getSourceRange().getBegin(),
- TheCall.get(), 0))
- return ExprError();
+ if (CheckCallReturnType(FPT->getResultType(),
+ BO->getRHS()->getSourceRange().getBegin(),
+ TheCall.get(), 0))
+ return ExprError();
- if (ConvertArgumentsForCall(&*TheCall, BO, 0, FPT, Args, NumArgs,
- RParenLoc))
- return ExprError();
+ if (ConvertArgumentsForCall(&*TheCall, BO, 0, FPT, Args, NumArgs,
+ RParenLoc))
+ return ExprError();
- return Owned(MaybeBindToTemporary(TheCall.release()).release());
+ return Owned(MaybeBindToTemporary(TheCall.release()).release());
+ }
+ return ExprError(Diag(Fn->getLocStart(),
+ diag::err_typecheck_call_not_function)
+ << Fn->getType() << Fn->getSourceRange());
}
}
}
@@ -2893,7 +2865,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
// lookup and whether there were any explicitly-specified template arguments.
bool ADL = true;
bool HasExplicitTemplateArgs = 0;
- const TemplateArgument *ExplicitTemplateArgs = 0;
+ const TemplateArgumentLoc *ExplicitTemplateArgs = 0;
unsigned NumExplicitTemplateArgs = 0;
NestedNameSpecifier *Qualifier = 0;
SourceRange QualifierRange;
@@ -2932,19 +2904,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
if (!FDecl)
return ExprError();
- // Update Fn to refer to the actual function selected.
- Expr *NewFn = 0;
- if (Qualifier)
- NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(),
- Fn->getLocStart(),
- false, false,
- QualifierRange,
- Qualifier);
- else
- NewFn = new (Context) DeclRefExpr(FDecl, FDecl->getType(),
- Fn->getLocStart());
- Fn->Destroy(Context);
- Fn = NewFn;
+ Fn = FixOverloadedFunctionReference(Fn, FDecl);
}
}
@@ -3543,7 +3503,10 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
compositeType = Context.getObjCIdType();
} else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) {
compositeType = Context.getObjCIdType();
- } else {
+ } else if (!(compositeType =
+ Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull())
+ ;
+ else {
Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)
<< LHSTy << RHSTy
<< LHS->getSourceRange() << RHS->getSourceRange();
@@ -4080,7 +4043,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
// This check seems unnatural, however it is necessary to ensure the proper
// conversion of functions/arrays. If the conversion were done for all
- // DeclExpr's (created by ActOnIdentifierExpr), it would mess up the unary
+ // DeclExpr's (created by ActOnIdExpression), it would mess up the unary
// expressions that surpress this implicit conversion (&, sizeof).
//
// Suppress this for references: C++ 8.5.3p5.
@@ -4428,6 +4391,10 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType())
return InvalidOperands(Loc, lex, rex);
+ // Vector shifts promote their scalar inputs to vector type.
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+ return CheckVectorOperands(Loc, lex, rex);
+
// Shifts don't perform usual arithmetic conversions, they just do integer
// promotions on each operand. C99 6.5.7p3
QualType LHSTy = Context.isPromotableBitField(lex);
@@ -5083,7 +5050,6 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc,
static NamedDecl *getPrimaryDecl(Expr *E) {
switch (E->getStmtClass()) {
case Stmt::DeclRefExprClass:
- case Stmt::QualifiedDeclRefExprClass:
return cast<DeclRefExpr>(E)->getDecl();
case Stmt::MemberExprClass:
// If this is an arrow operator, the address is an offset from
@@ -5199,7 +5165,7 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
// Okay: we can take the address of a field.
// Could be a pointer to member, though, if there is an explicit
// scope qualifier for the class.
- if (isa<QualifiedDeclRefExpr>(op)) {
+ if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier()) {
DeclContext *Ctx = dcl->getDeclContext();
if (Ctx && Ctx->isRecord()) {
if (FD->getType()->isReferenceType()) {
@@ -5216,7 +5182,8 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
} else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(dcl)) {
// Okay: we can take the address of a function.
// As above.
- if (isa<QualifiedDeclRefExpr>(op) && MD->isInstance())
+ if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier() &&
+ MD->isInstance())
return Context.getMemberPointerType(op->getType(),
Context.getTypeDeclType(MD->getParent()).getTypePtr());
} else if (!isa<FunctionDecl>(dcl))
@@ -5426,6 +5393,72 @@ Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
OpLoc));
}
+/// SuggestParentheses - Emit a diagnostic together with a fixit hint that wraps
+/// ParenRange in parentheses.
+static void SuggestParentheses(Sema &Self, SourceLocation Loc,
+ const PartialDiagnostic &PD,
+ SourceRange ParenRange)
+{
+ SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd());
+ if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
+ // We can't display the parentheses, so just dig the
+ // warning/error and return.
+ Self.Diag(Loc, PD);
+ return;
+ }
+
+ Self.Diag(Loc, PD)
+ << CodeModificationHint::CreateInsertion(ParenRange.getBegin(), "(")
+ << CodeModificationHint::CreateInsertion(EndLoc, ")");
+}
+
+/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
+/// operators are mixed in a way that suggests that the programmer forgot that
+/// comparison operators have higher precedence. The most typical example of
+/// such code is "flags & 0x0020 != 0", which is equivalent to "flags & 1".
+static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc,
+ SourceLocation OpLoc,Expr *lhs,Expr *rhs){
+ typedef BinaryOperator BinOp;
+ BinOp::Opcode lhsopc = static_cast<BinOp::Opcode>(-1),
+ rhsopc = static_cast<BinOp::Opcode>(-1);
+ if (BinOp *BO = dyn_cast<BinOp>(lhs))
+ lhsopc = BO->getOpcode();
+ if (BinOp *BO = dyn_cast<BinOp>(rhs))
+ rhsopc = BO->getOpcode();
+
+ // Subs are not binary operators.
+ if (lhsopc == -1 && rhsopc == -1)
+ return;
+
+ // Bitwise operations are sometimes used as eager logical ops.
+ // Don't diagnose this.
+ if ((BinOp::isComparisonOp(lhsopc) || BinOp::isBitwiseOp(lhsopc)) &&
+ (BinOp::isComparisonOp(rhsopc) || BinOp::isBitwiseOp(rhsopc)))
+ return;
+
+ if (BinOp::isComparisonOp(lhsopc))
+ SuggestParentheses(Self, OpLoc,
+ PDiag(diag::warn_precedence_bitwise_rel)
+ << SourceRange(lhs->getLocStart(), OpLoc)
+ << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(lhsopc),
+ SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd()));
+ else if (BinOp::isComparisonOp(rhsopc))
+ SuggestParentheses(Self, OpLoc,
+ PDiag(diag::warn_precedence_bitwise_rel)
+ << SourceRange(OpLoc, rhs->getLocEnd())
+ << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(rhsopc),
+ SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart()));
+}
+
+/// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky
+/// precedence. This currently diagnoses only "arg1 'bitwise' arg2 'eq' arg3".
+/// But it could also warn about arg1 && arg2 || arg3, as GCC 4.3+ does.
+static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperator::Opcode Opc,
+ SourceLocation OpLoc, Expr *lhs, Expr *rhs){
+ if (BinaryOperator::isBitwiseOp(Opc))
+ DiagnoseBitwisePrecedence(Self, Opc, OpLoc, lhs, rhs);
+}
+
// Binary Operators. 'Tok' is the token for the operator.
Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
tok::TokenKind Kind,
@@ -5436,6 +5469,9 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
assert((lhs != 0) && "ActOnBinOp(): missing left expression");
assert((rhs != 0) && "ActOnBinOp(): missing right expression");
+ // Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
+ DiagnoseBinOpPrecedence(*this, Opc, TokLoc, lhs, rhs);
+
if (getLangOptions().CPlusPlus &&
(lhs->getType()->isOverloadableType() ||
rhs->getType()->isOverloadableType())) {
@@ -5451,7 +5487,7 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
Expr *Args[2] = { lhs, rhs };
DeclarationName OpName
= Context.DeclarationNames.getCXXOperatorName(OverOp);
- ArgumentDependentLookup(OpName, Args, 2, Functions);
+ ArgumentDependentLookup(OpName, /*Operator*/true, Args, 2, Functions);
}
// Build the (potentially-overloaded, potentially-dependent)
@@ -5569,7 +5605,7 @@ Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
Functions);
DeclarationName OpName
= Context.DeclarationNames.getCXXOperatorName(OverOp);
- ArgumentDependentLookup(OpName, &Input, 1, Functions);
+ ArgumentDependentLookup(OpName, /*Operator*/true, &Input, 1, Functions);
}
return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input));
@@ -5673,6 +5709,10 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
if (!Dependent) {
bool DidWarnAboutNonPOD = false;
+ if (RequireCompleteType(TypeLoc, Res->getType(),
+ diag::err_offsetof_incomplete_type))
+ return ExprError();
+
// FIXME: Dependent case loses a lot of information here. And probably
// leaks like a sieve.
for (unsigned i = 0; i != NumComponents; ++i) {
@@ -6240,21 +6280,21 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
// Implicit instantiation of function templates and member functions of
// class templates.
- if (!Function->getBody() &&
- Function->getTemplateSpecializationKind()
- == TSK_ImplicitInstantiation) {
+ if (!Function->getBody() && Function->isImplicitlyInstantiable()) {
bool AlreadyInstantiated = false;
if (FunctionTemplateSpecializationInfo *SpecInfo
= Function->getTemplateSpecializationInfo()) {
if (SpecInfo->getPointOfInstantiation().isInvalid())
SpecInfo->setPointOfInstantiation(Loc);
- else
+ else if (SpecInfo->getTemplateSpecializationKind()
+ == TSK_ImplicitInstantiation)
AlreadyInstantiated = true;
} else if (MemberSpecializationInfo *MSInfo
= Function->getMemberSpecializationInfo()) {
if (MSInfo->getPointOfInstantiation().isInvalid())
MSInfo->setPointOfInstantiation(Loc);
- else
+ else if (MSInfo->getTemplateSpecializationKind()
+ == TSK_ImplicitInstantiation)
AlreadyInstantiated = true;
}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index d4d031f91ed5..4868c14835f4 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -22,41 +22,6 @@
#include "llvm/ADT/STLExtras.h"
using namespace clang;
-/// ActOnCXXConversionFunctionExpr - Parse a C++ conversion function
-/// name (e.g., operator void const *) as an expression. This is
-/// very similar to ActOnIdentifierExpr, except that instead of
-/// providing an identifier the parser provides the type of the
-/// conversion function.
-Sema::OwningExprResult
-Sema::ActOnCXXConversionFunctionExpr(Scope *S, SourceLocation OperatorLoc,
- TypeTy *Ty, bool HasTrailingLParen,
- const CXXScopeSpec &SS,
- bool isAddressOfOperand) {
- //FIXME: Preserve type source info.
- QualType ConvType = GetTypeFromParser(Ty);
- CanQualType ConvTypeCanon = Context.getCanonicalType(ConvType);
- DeclarationName ConvName
- = Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon);
- return ActOnDeclarationNameExpr(S, OperatorLoc, ConvName, HasTrailingLParen,
- &SS, isAddressOfOperand);
-}
-
-/// ActOnCXXOperatorFunctionIdExpr - Parse a C++ overloaded operator
-/// name (e.g., @c operator+ ) as an expression. This is very
-/// similar to ActOnIdentifierExpr, except that instead of providing
-/// an identifier the parser provides the kind of overloaded
-/// operator that was parsed.
-Sema::OwningExprResult
-Sema::ActOnCXXOperatorFunctionIdExpr(Scope *S, SourceLocation OperatorLoc,
- OverloadedOperatorKind Op,
- bool HasTrailingLParen,
- const CXXScopeSpec &SS,
- bool isAddressOfOperand) {
- DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(Op);
- return ActOnDeclarationNameExpr(S, OperatorLoc, Name, HasTrailingLParen, &SS,
- isAddressOfOperand);
-}
-
/// ActOnCXXTypeidOfType - Parse typeid( type-id ).
Action::OwningExprResult
Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
@@ -212,7 +177,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
PDiag(diag::err_invalid_incomplete_type_use)
<< FullRange))
return ExprError();
-
+
if (RequireNonAbstractType(TyBeginLoc, Ty,
diag::err_allocation_of_abstract_type))
return ExprError();
@@ -288,7 +253,6 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
<< FullRange);
assert(NumExprs == 0 && "Expected 0 expressions");
-
// C++ [expr.type.conv]p2:
// The expression T(), where T is a simple-type-specifier for a non-array
// complete object type or the (possibly cv-qualified) void type, creates an
@@ -312,7 +276,6 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
MultiExprArg ConstructorArgs,
SourceLocation ConstructorRParen) {
Expr *ArraySize = 0;
- unsigned Skip = 0;
// If the specified type is an array, unwrap it and save the expression.
if (D.getNumTypeObjects() > 0 &&
D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
@@ -323,14 +286,25 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
if (!Chunk.Arr.NumElts)
return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size)
<< D.getSourceRange());
+
+ if (ParenTypeId) {
+ // Can't have dynamic array size when the type-id is in parentheses.
+ Expr *NumElts = (Expr *)Chunk.Arr.NumElts;
+ if (!NumElts->isTypeDependent() && !NumElts->isValueDependent() &&
+ !NumElts->isIntegerConstantExpr(Context)) {
+ Diag(D.getTypeObject(0).Loc, diag::err_new_paren_array_nonconst)
+ << NumElts->getSourceRange();
+ return ExprError();
+ }
+ }
+
ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts);
- Skip = 1;
+ D.DropFirstTypeObject();
}
// Every dimension shall be of constant size.
- if (D.getNumTypeObjects() > 0 &&
- D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
- for (unsigned I = 1, N = D.getNumTypeObjects(); I < N; ++I) {
+ if (ArraySize) {
+ for (unsigned I = 0, N = D.getNumTypeObjects(); I < N; ++I) {
if (D.getTypeObject(I).Kind != DeclaratorChunk::Array)
break;
@@ -345,10 +319,10 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
}
}
}
-
+
//FIXME: Store DeclaratorInfo in CXXNew expression.
DeclaratorInfo *DInfo = 0;
- QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, &DInfo, Skip);
+ QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, &DInfo);
if (D.isInvalidType())
return ExprError();
@@ -935,7 +909,7 @@ Sema::ActOnCXXConditionDeclarationExpr(Scope *S, SourceLocation StartLoc,
// FIXME: Store DeclaratorInfo in the expression.
DeclaratorInfo *DInfo = 0;
TagDecl *OwnedTag = 0;
- QualType Ty = GetTypeForDeclarator(D, S, &DInfo, /*Skip=*/0, &OwnedTag);
+ QualType Ty = GetTypeForDeclarator(D, S, &DInfo, &OwnedTag);
if (Ty->isFunctionType()) { // The declarator shall not specify a function...
// We exit without creating a CXXConditionDeclExpr because a FunctionDecl
@@ -1139,6 +1113,10 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
From = CastArg.takeAs<Expr>();
return BuildCXXDerivedToBaseExpr(From, CastKind, ICS, Flavor);
}
+
+ if (ICS.UserDefined.After.Second == ICK_Pointer_Member &&
+ ToType.getNonReferenceType()->isMemberFunctionPointerType())
+ CastKind = CastExpr::CK_BaseToDerivedMemberPointer;
From = new (Context) ImplicitCastExpr(ToType.getNonReferenceType(),
CastKind, CastArg.takeAs<Expr>(),
@@ -1390,7 +1368,8 @@ QualType Sema::CheckPointerToMemberOperands(
LType = Ptr->getPointeeType().getNonReferenceType();
else {
Diag(Loc, diag::err_bad_memptr_lhs)
- << OpSpelling << 1 << LType << lex->getSourceRange();
+ << OpSpelling << 1 << LType
+ << CodeModificationHint::CreateReplacement(SourceRange(Loc), ".*");
return QualType();
}
}
@@ -1403,8 +1382,10 @@ QualType Sema::CheckPointerToMemberOperands(
// overkill?
if (!IsDerivedFrom(LType, Class, Paths) ||
Paths.isAmbiguous(Context.getCanonicalType(Class))) {
+ const char *ReplaceStr = isIndirect ? ".*" : "->*";
Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
- << (int)isIndirect << lex->getType() << lex->getSourceRange();
+ << (int)isIndirect << lex->getType() <<
+ CodeModificationHint::CreateReplacement(SourceRange(Loc), ReplaceStr);
return QualType();
}
}
@@ -2105,110 +2086,6 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
return move(Base);
}
-Sema::OwningExprResult
-Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- IdentifierInfo *ClassName,
- const CXXScopeSpec &SS,
- bool HasTrailingLParen) {
- if (SS.isInvalid())
- return ExprError();
-
- QualType BaseType;
- if (isUnknownSpecialization(SS))
- BaseType = Context.getTypenameType((NestedNameSpecifier *)SS.getScopeRep(),
- ClassName);
- else {
- TypeTy *BaseTy = getTypeName(*ClassName, ClassNameLoc, S, &SS);
-
- // FIXME: If Base is dependent, we might not be able to resolve it here.
- if (!BaseTy) {
- Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
- << ClassName;
- return ExprError();
- }
-
- BaseType = GetTypeFromParser(BaseTy);
- }
-
- return ActOnDestructorReferenceExpr(S, move(Base), OpLoc, OpKind,
- SourceRange(ClassNameLoc),
- BaseType.getAsOpaquePtr(),
- SS, HasTrailingLParen);
-}
-
-Sema::OwningExprResult
-Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceRange TypeRange,
- TypeTy *T,
- const CXXScopeSpec &SS,
- bool HasTrailingLParen) {
- QualType Type = QualType::getFromOpaquePtr(T);
- CanQualType CanType = Context.getCanonicalType(Type);
- DeclarationName DtorName =
- Context.DeclarationNames.getCXXDestructorName(CanType);
-
- OwningExprResult Result
- = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind,
- TypeRange.getBegin(), DtorName, DeclPtrTy(),
- &SS);
- if (Result.isInvalid() || HasTrailingLParen)
- return move(Result);
-
- // The only way a reference to a destructor can be used is to
- // immediately call them. Since the next token is not a '(', produce a
- // diagnostic and build the call now.
- Expr *E = (Expr *)Result.get();
- SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(TypeRange.getEnd());
- Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
- << isa<CXXPseudoDestructorExpr>(E)
- << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()");
-
- return ActOnCallExpr(0, move(Result), ExpectedLParenLoc,
- MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc);
-}
-
-Sema::OwningExprResult
-Sema::ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- OverloadedOperatorKind OverOpKind,
- const CXXScopeSpec *SS) {
- if (SS && SS->isInvalid())
- return ExprError();
-
- DeclarationName Name =
- Context.DeclarationNames.getCXXOperatorName(OverOpKind);
-
- return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc,
- Name, DeclPtrTy(), SS);
-}
-
-Sema::OwningExprResult
-Sema::ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- TypeTy *Ty,
- const CXXScopeSpec *SS) {
- if (SS && SS->isInvalid())
- return ExprError();
-
- //FIXME: Preserve type source info.
- QualType ConvType = GetTypeFromParser(Ty);
- CanQualType ConvTypeCanon = Context.getCanonicalType(ConvType);
- DeclarationName ConvName =
- Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon);
-
- return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc,
- ConvName, DeclPtrTy(), SS);
-}
-
CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp,
CXXMethodDecl *Method) {
MemberExpr *ME =
@@ -2333,6 +2210,7 @@ bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D,
if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl)))
Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+ // FIXME: Do we have to know if there are explicit template arguments?
if (Method && !Method->isStatic()) {
Ctx = Method->getParent();
if (isa<CXXMethodDecl>(D) && !FunTmpl)
@@ -2350,6 +2228,12 @@ bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D,
// Determine whether the declaration(s) we found are actually in a base
// class. If not, this isn't an implicit member reference.
ThisType = MD->getThisType(Context);
+
+ // If the type of "this" is dependent, we can't tell if the member is in a
+ // base class or not, so treat this as a dependent implicit member reference.
+ if (ThisType->isDependentType())
+ return true;
+
QualType CtxType = Context.getTypeDeclType(cast<CXXRecordDecl>(Ctx));
QualType ClassType
= Context.getTypeDeclType(cast<CXXRecordDecl>(MD->getParent()));
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index dd877c16fba7..93752e130c94 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1239,6 +1239,14 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
BaseEnd = Class->bases_end();
Base != BaseEnd; ++Base) {
const RecordType *BaseType = Base->getType()->getAs<RecordType>();
+ // In dependent contexts, we do ADL twice, and the first time around,
+ // the base type might be a dependent TemplateSpecializationType, or a
+ // TemplateTypeParmType. If that happens, simply ignore it.
+ // FIXME: If we want to support export, we probably need to add the
+ // namespace of the template in a TemplateSpecializationType, or even
+ // the classes and namespaces of known non-dependent arguments.
+ if (!BaseType)
+ continue;
CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl());
if (AssociatedClasses.insert(BaseDecl)) {
// Find the associated namespace for this base class.
@@ -1561,7 +1569,7 @@ static void CollectFunctionDecl(Sema::FunctionSet &Functions,
Functions.insert(FunTmpl);
}
-void Sema::ArgumentDependentLookup(DeclarationName Name,
+void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
Expr **Args, unsigned NumArgs,
FunctionSet &Functions) {
// Find all of the associated namespaces and classes based on the
@@ -1572,6 +1580,13 @@ void Sema::ArgumentDependentLookup(DeclarationName Name,
AssociatedNamespaces,
AssociatedClasses);
+ QualType T1, T2;
+ if (Operator) {
+ T1 = Args[0]->getType();
+ if (NumArgs >= 2)
+ T2 = Args[1]->getType();
+ }
+
// C++ [basic.lookup.argdep]p3:
// Let X be the lookup set produced by unqualified lookup (3.4.1)
// and let Y be the lookup set produced by argument dependent
@@ -1608,7 +1623,10 @@ void Sema::ArgumentDependentLookup(DeclarationName Name,
continue;
}
- CollectFunctionDecl(Functions, D);
+ FunctionDecl *Fn;
+ if (!Operator || !(Fn = dyn_cast<FunctionDecl>(D)) ||
+ IsAcceptableNonMemberOperatorCandidate(Fn, T1, T2, Context))
+ CollectFunctionDecl(Functions, D);
}
}
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index ebcf3ad8e2bc..946e28269eb6 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -999,6 +999,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
// here. That is handled by CheckPointerConversion.
if (getLangOptions().CPlusPlus &&
FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
+ !RequireCompleteType(From->getLocStart(), FromPointeeType, PDiag()) &&
IsDerivedFrom(FromPointeeType, ToPointeeType)) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
@@ -2444,7 +2445,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object,
void
Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr *Object, Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@@ -2489,7 +2490,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
void
Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@@ -2761,7 +2762,7 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
if (S)
LookupOverloadedOperatorName(Op, S, T1, T2, Functions);
- ArgumentDependentLookup(OpName, Args, NumArgs, Functions);
+ ArgumentDependentLookup(OpName, /*Operator*/true, Args, NumArgs, Functions);
AddFunctionCandidates(Functions, Args, NumArgs, CandidateSet);
AddMemberOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet, OpRange);
AddBuiltinOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet);
@@ -3119,9 +3120,8 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
}
}
-/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers
-/// , if any, found in visible type conversion functions found in ArgExpr's
-/// type.
+/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers,
+/// if any, found in visible type conversion functions found in ArgExpr's type.
static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
Qualifiers VRQuals;
const RecordType *TyRec;
@@ -3139,7 +3139,7 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
OverloadedFunctionDecl *Conversions =
- ClassDecl->getVisibleConversionFunctions();
+ ClassDecl->getVisibleConversionFunctions();
for (OverloadedFunctionDecl::function_iterator Func
= Conversions->function_begin();
@@ -3887,7 +3887,7 @@ void
Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
Expr **Args, unsigned NumArgs,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
bool PartialOverloading) {
@@ -3908,7 +3908,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
}
// FIXME: Pass in the explicit template arguments?
- ArgumentDependentLookup(Name, Args, NumArgs, Functions);
+ ArgumentDependentLookup(Name, /*Operator*/false, Args, NumArgs, Functions);
// Erase all of the candidates we already knew about.
// FIXME: This is suboptimal. Is there a better way?
@@ -4279,7 +4279,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
}
bool HasExplicitTemplateArgs = false;
- const TemplateArgument *ExplicitTemplateArgs = 0;
+ const TemplateArgumentLoc *ExplicitTemplateArgs = 0;
unsigned NumExplicitTemplateArgs = 0;
// Try to dig out the overloaded function.
@@ -4287,10 +4287,15 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr)) {
Ovl = dyn_cast<OverloadedFunctionDecl>(DR->getDecl());
FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DR->getDecl());
+ HasExplicitTemplateArgs = DR->hasExplicitTemplateArgumentList();
+ ExplicitTemplateArgs = DR->getTemplateArgs();
+ NumExplicitTemplateArgs = DR->getNumTemplateArgs();
} else if (MemberExpr *ME = dyn_cast<MemberExpr>(OvlExpr)) {
Ovl = dyn_cast<OverloadedFunctionDecl>(ME->getMemberDecl());
FunctionTemplate = dyn_cast<FunctionTemplateDecl>(ME->getMemberDecl());
- // FIXME: Explicit template arguments
+ HasExplicitTemplateArgs = ME->hasExplicitTemplateArgumentList();
+ ExplicitTemplateArgs = ME->getTemplateArgs();
+ NumExplicitTemplateArgs = ME->getNumTemplateArgs();
} else if (TemplateIdRefExpr *TIRE = dyn_cast<TemplateIdRefExpr>(OvlExpr)) {
TemplateName Name = TIRE->getTemplateName();
Ovl = Name.getAsOverloadedFunctionDecl();
@@ -4367,6 +4372,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// when converting to member pointer.
if (Method->isStatic() == IsMember)
continue;
+
+ // If we have explicit template arguments, skip non-templates.
+ if (HasExplicitTemplateArgs)
+ continue;
} else if (IsMember)
continue;
@@ -4443,7 +4452,7 @@ static void AddOverloadedCallCandidate(Sema &S,
AnyFunctionDecl Callee,
bool &ArgumentDependentLookup,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
@@ -4475,7 +4484,7 @@ void Sema::AddOverloadedCallCandidates(NamedDecl *Callee,
DeclarationName &UnqualifiedName,
bool &ArgumentDependentLookup,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
@@ -4543,7 +4552,7 @@ void Sema::AddOverloadedCallCandidates(NamedDecl *Callee,
FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
DeclarationName UnqualifiedName,
bool HasExplicitTemplateArgs,
- const TemplateArgument *ExplicitTemplateArgs,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
@@ -4934,6 +4943,134 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
}
+Action::OwningExprResult
+Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+ SourceLocation RLoc,
+ ExprArg Base, ExprArg Idx) {
+ Expr *Args[2] = { static_cast<Expr*>(Base.get()),
+ static_cast<Expr*>(Idx.get()) };
+ DeclarationName OpName =
+ Context.DeclarationNames.getCXXOperatorName(OO_Subscript);
+
+ // If either side is type-dependent, create an appropriate dependent
+ // expression.
+ if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
+
+ OverloadedFunctionDecl *Overloads
+ = OverloadedFunctionDecl::Create(Context, CurContext, OpName);
+
+ DeclRefExpr *Fn = new (Context) DeclRefExpr(Overloads, Context.OverloadTy,
+ LLoc, false, false);
+
+ Base.release();
+ Idx.release();
+ return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn,
+ Args, 2,
+ Context.DependentTy,
+ RLoc));
+ }
+
+ // Build an empty overload set.
+ OverloadCandidateSet CandidateSet;
+
+ // Subscript can only be overloaded as a member function.
+
+ // Add operator candidates that are member functions.
+ AddMemberOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet);
+
+ // Add builtin operator candidates.
+ AddBuiltinOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet);
+
+ // Perform overload resolution.
+ OverloadCandidateSet::iterator Best;
+ switch (BestViableFunction(CandidateSet, LLoc, Best)) {
+ case OR_Success: {
+ // We found a built-in operator or an overloaded operator.
+ FunctionDecl *FnDecl = Best->Function;
+
+ if (FnDecl) {
+ // We matched an overloaded operator. Build a call to that
+ // operator.
+
+ // Convert the arguments.
+ CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
+ if (PerformObjectArgumentInitialization(Args[0], Method) ||
+ PerformCopyInitialization(Args[1],
+ FnDecl->getParamDecl(0)->getType(),
+ "passing"))
+ return ExprError();
+
+ // Determine the result type
+ QualType ResultTy
+ = FnDecl->getType()->getAs<FunctionType>()->getResultType();
+ ResultTy = ResultTy.getNonReferenceType();
+
+ // Build the actual expression node.
+ Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
+ LLoc);
+ UsualUnaryConversions(FnExpr);
+
+ Base.release();
+ Idx.release();
+ ExprOwningPtr<CXXOperatorCallExpr>
+ TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
+ FnExpr, Args, 2,
+ ResultTy, RLoc));
+
+ if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall.get(),
+ FnDecl))
+ return ExprError();
+
+ return MaybeBindToTemporary(TheCall.release());
+ } else {
+ // We matched a built-in operator. Convert the arguments, then
+ // break out so that we will build the appropriate built-in
+ // operator node.
+ if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
+ Best->Conversions[0], "passing") ||
+ PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
+ Best->Conversions[1], "passing"))
+ return ExprError();
+
+ break;
+ }
+ }
+
+ case OR_No_Viable_Function: {
+ // No viable function; try to create a built-in operation, which will
+ // produce an error. Then, show the non-viable candidates.
+ OwningExprResult Result =
+ CreateBuiltinArraySubscriptExpr(move(Base), LLoc, move(Idx), RLoc);
+ assert(Result.isInvalid() &&
+ "C++ subscript operator overloading is missing candidates!");
+ if (Result.isInvalid())
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false,
+ "[]", LLoc);
+ return move(Result);
+ }
+
+ case OR_Ambiguous:
+ Diag(LLoc, diag::err_ovl_ambiguous_oper)
+ << "[]" << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true,
+ "[]", LLoc);
+ return ExprError();
+
+ case OR_Deleted:
+ Diag(LLoc, diag::err_ovl_deleted_oper)
+ << Best->Function->isDeleted() << "[]"
+ << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ return ExprError();
+ }
+
+ // We matched a built-in operator; build it.
+ Base.release();
+ Idx.release();
+ return CreateBuiltinArraySubscriptExpr(Owned(Args[0]), LLoc,
+ Owned(Args[1]), RLoc);
+}
+
/// BuildCallToMemberFunction - Build a call to a member
/// function. MemExpr is the expression that refers to the member
/// function (and includes the object parameter), Args/NumArgs are the
@@ -4967,10 +5104,15 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
for (OverloadIterator Func(MemExpr->getMemberDecl()), FuncEnd;
Func != FuncEnd; ++Func) {
- if ((Method = dyn_cast<CXXMethodDecl>(*Func)))
+ if ((Method = dyn_cast<CXXMethodDecl>(*Func))) {
+ // If explicit template arguments were provided, we can't call a
+ // non-template member function.
+ if (MemExpr->hasExplicitTemplateArgumentList())
+ continue;
+
AddMethodCandidate(Method, ObjectArg, Args, NumArgs, CandidateSet,
/*SuppressUserConversions=*/false);
- else
+ } else
AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func),
MemExpr->hasExplicitTemplateArgumentList(),
MemExpr->getTemplateArgs(),
@@ -5361,8 +5503,14 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
Expr *NewExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn);
- NewExpr->setType(PE->getSubExpr()->getType());
- return NewExpr;
+ PE->setSubExpr(NewExpr);
+ PE->setType(NewExpr->getType());
+ } else if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ Expr *NewExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Fn);
+ assert(Context.hasSameType(ICE->getSubExpr()->getType(),
+ NewExpr->getType()) &&
+ "Implicit cast type cannot be determined from overload");
+ ICE->setSubExpr(NewExpr);
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {
assert(UnOp->getOpcode() == UnaryOperator::AddrOf &&
"Can only take the address of an overloaded function");
@@ -5370,18 +5518,19 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
if (Method->isStatic()) {
// Do nothing: static member functions aren't any different
// from non-member functions.
- } else if (QualifiedDeclRefExpr *DRE
- = dyn_cast<QualifiedDeclRefExpr>(UnOp->getSubExpr())) {
- // We have taken the address of a pointer to member
- // function. Perform the computation here so that we get the
- // appropriate pointer to member type.
- DRE->setDecl(Fn);
- DRE->setType(Fn->getType());
- QualType ClassType
- = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
- E->setType(Context.getMemberPointerType(Fn->getType(),
- ClassType.getTypePtr()));
- return E;
+ } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr())) {
+ if (DRE->getQualifier()) {
+ // We have taken the address of a pointer to member
+ // function. Perform the computation here so that we get the
+ // appropriate pointer to member type.
+ DRE->setDecl(Fn);
+ DRE->setType(Fn->getType());
+ QualType ClassType
+ = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
+ E->setType(Context.getMemberPointerType(Fn->getType(),
+ ClassType.getTypePtr()));
+ return E;
+ }
}
// FIXME: TemplateIdRefExpr referring to a member function template
// specialization!
@@ -5393,26 +5542,35 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
return UnOp;
} else if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
assert((isa<OverloadedFunctionDecl>(DR->getDecl()) ||
- isa<FunctionTemplateDecl>(DR->getDecl())) &&
- "Expected overloaded function or function template");
+ isa<FunctionTemplateDecl>(DR->getDecl()) ||
+ isa<FunctionDecl>(DR->getDecl())) &&
+ "Expected function or function template");
DR->setDecl(Fn);
E->setType(Fn->getType());
} else if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) {
MemExpr->setMemberDecl(Fn);
E->setType(Fn->getType());
} else if (TemplateIdRefExpr *TID = dyn_cast<TemplateIdRefExpr>(E)) {
- // FIXME: We should capture the template arguments here.
- if (NestedNameSpecifier *Qualifier = TID->getQualifier())
- E = new (Context) QualifiedDeclRefExpr(Fn, Fn->getType(),
- TID->getTemplateNameLoc(),
- /*FIXME?*/false, /*FIXME?*/false,
- TID->getQualifierRange(),
- Qualifier);
- else
- E = new (Context) DeclRefExpr(Fn, Fn->getType(),
- TID->getTemplateNameLoc());
+ E = DeclRefExpr::Create(Context,
+ TID->getQualifier(), TID->getQualifierRange(),
+ Fn, TID->getTemplateNameLoc(),
+ true,
+ TID->getLAngleLoc(),
+ TID->getTemplateArgs(),
+ TID->getNumTemplateArgs(),
+ TID->getRAngleLoc(),
+ Fn->getType(),
+ /*FIXME?*/false, /*FIXME?*/false);
- TID->Destroy(Context);
+ // FIXME: Don't destroy TID here, since we need its template arguments
+ // to survive.
+ // TID->Destroy(Context);
+ } else if (isa<UnresolvedFunctionNameExpr>(E)) {
+ return DeclRefExpr::Create(Context,
+ /*Qualifier=*/0,
+ /*QualifierRange=*/SourceRange(),
+ Fn, E->getLocStart(),
+ Fn->getType(), false, false);
} else {
assert(false && "Invalid reference to overloaded function");
}
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 145342438503..6a65bd1dd1ec 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -70,7 +70,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
SourceLocation Loc;
SourceRange R1, R2;
- if (!E->isUnusedResultAWarning(Loc, R1, R2))
+ if (!E->isUnusedResultAWarning(Loc, R1, R2, Context))
return;
// Okay, we have an unused result. Depending on what the base expression is,
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 0f223208a938..3c56358d5a94 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -98,29 +98,43 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context, NamedDecl *D) {
}
TemplateNameKind Sema::isTemplateName(Scope *S,
- const IdentifierInfo &II,
- SourceLocation IdLoc,
- const CXXScopeSpec *SS,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectTypePtr,
bool EnteringContext,
TemplateTy &TemplateResult) {
+ DeclarationName TName;
+
+ switch (Name.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ TName = DeclarationName(Name.Identifier);
+ break;
+
+ case UnqualifiedId::IK_OperatorFunctionId:
+ TName = Context.DeclarationNames.getCXXOperatorName(
+ Name.OperatorFunctionId.Operator);
+ break;
+
+ default:
+ return TNK_Non_template;
+ }
+
// Determine where to perform name lookup
DeclContext *LookupCtx = 0;
bool isDependent = false;
if (ObjectTypePtr) {
// This nested-name-specifier occurs in a member access expression, e.g.,
// x->B::f, and we are looking into the type of the object.
- assert((!SS || !SS->isSet()) &&
- "ObjectType and scope specifier cannot coexist");
+ assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
LookupCtx = computeDeclContext(ObjectType);
isDependent = ObjectType->isDependentType();
- } else if (SS && SS->isSet()) {
+ } else if (SS.isSet()) {
// This nested-name-specifier occurs after another nested-name-specifier,
// so long into the context associated with the prior nested-name-specifier.
- LookupCtx = computeDeclContext(*SS, EnteringContext);
- isDependent = isDependentScopeSpecifier(*SS);
+ LookupCtx = computeDeclContext(SS, EnteringContext);
+ isDependent = isDependentScopeSpecifier(SS);
}
LookupResult Found;
@@ -132,10 +146,10 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
// nested-name-specifier.
// The declaration context must be complete.
- if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS))
+ if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS))
return TNK_Non_template;
- LookupQualifiedName(Found, LookupCtx, &II, LookupOrdinaryName);
+ LookupQualifiedName(Found, LookupCtx, TName, LookupOrdinaryName);
if (ObjectTypePtr && Found.getKind() == LookupResult::NotFound) {
// C++ [basic.lookup.classref]p1:
@@ -150,7 +164,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
//
// FIXME: When we're instantiating a template, do we actually have to
// look in the scope of the template? Seems fishy...
- LookupName(Found, S, &II, LookupOrdinaryName);
+ LookupName(Found, S, TName, LookupOrdinaryName);
ObjectTypeSearchedInScope = true;
}
} else if (isDependent) {
@@ -158,7 +172,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
return TNK_Non_template;
} else {
// Perform unqualified name lookup in the current scope.
- LookupName(Found, S, &II, LookupOrdinaryName);
+ LookupName(Found, S, TName, LookupOrdinaryName);
}
// FIXME: Cope with ambiguous name-lookup results.
@@ -177,7 +191,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
// postfix-expression and [...]
//
LookupResult FoundOuter;
- LookupName(FoundOuter, S, &II, LookupOrdinaryName);
+ LookupName(FoundOuter, S, TName, LookupOrdinaryName);
// FIXME: Handle ambiguities in this lookup better
NamedDecl *OuterTemplate
= isAcceptableTemplateName(Context, FoundOuter.getAsSingleDecl(Context));
@@ -194,8 +208,10 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
// entity as the one found in the class of the object expression,
// otherwise the program is ill-formed.
if (OuterTemplate->getCanonicalDecl() != Template->getCanonicalDecl()) {
- Diag(IdLoc, diag::err_nested_name_member_ref_lookup_ambiguous)
- << &II;
+ Diag(Name.getSourceRange().getBegin(),
+ diag::err_nested_name_member_ref_lookup_ambiguous)
+ << TName
+ << Name.getSourceRange();
Diag(Template->getLocation(), diag::note_ambig_member_ref_object_type)
<< QualType::getFromOpaquePtr(ObjectTypePtr);
Diag(OuterTemplate->getLocation(), diag::note_ambig_member_ref_scope);
@@ -206,9 +222,9 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
}
}
- if (SS && SS->isSet() && !SS->isInvalid()) {
+ if (SS.isSet() && !SS.isInvalid()) {
NestedNameSpecifier *Qualifier
- = static_cast<NestedNameSpecifier *>(SS->getScopeRep());
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
if (OverloadedFunctionDecl *Ovl
= dyn_cast<OverloadedFunctionDecl>(Template))
TemplateResult
@@ -321,8 +337,11 @@ void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam,
TypeTy *DefaultT) {
TemplateTypeParmDecl *Parm
= cast<TemplateTypeParmDecl>(TypeParam.getAs<Decl>());
- // FIXME: Preserve type source info.
- QualType Default = GetTypeFromParser(DefaultT);
+
+ DeclaratorInfo *DefaultDInfo;
+ GetTypeFromParser(DefaultT, &DefaultDInfo);
+
+ assert(DefaultDInfo && "expected source information for type");
// C++0x [temp.param]p9:
// A default template-argument may be specified for any kind of
@@ -337,12 +356,12 @@ void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam,
// FIXME: Implement this check! Needs a recursive walk over the types.
// Check the template argument itself.
- if (CheckTemplateArgument(Parm, Default, DefaultLoc)) {
+ if (CheckTemplateArgument(Parm, DefaultDInfo)) {
Parm->setInvalidDecl();
return;
}
- Parm->setDefaultArgument(Default, DefaultLoc, false);
+ Parm->setDefaultArgument(DefaultDInfo, false);
}
/// \brief Check that the type of a non-type template parameter is
@@ -610,11 +629,19 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
SemanticContext = PrevDecl->getDeclContext();
} else {
// Declarations in outer scopes don't matter. However, the outermost
- // context we computed is the semntic context for our new
+ // context we computed is the semantic context for our new
// declaration.
PrevDecl = 0;
SemanticContext = OutermostContext;
}
+
+ if (CurContext->isDependentContext()) {
+ // If this is a dependent context, we don't want to link the friend
+ // class template to the template in scope, because that would perform
+ // checking of the template parameter lists that can't be performed
+ // until the outer context is instantiated.
+ PrevDecl = 0;
+ }
} else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
PrevDecl = 0;
@@ -843,7 +870,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
SawParameterPack = true;
ParameterPackLoc = NewTypeParm->getLocation();
} else if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
- NewTypeParm->hasDefaultArgument()) {
+ NewTypeParm->hasDefaultArgument()) {
OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
SawDefaultArgument = true;
@@ -853,8 +880,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// Merge the default argument from the old declaration to the
// new declaration.
SawDefaultArgument = true;
- NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgument(),
- OldTypeParm->getDefaultArgumentLoc(),
+ NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgumentInfo(),
true);
PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc();
} else if (NewTypeParm->hasDefaultArgument()) {
@@ -1096,24 +1122,28 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
/// into template arguments used by semantic analysis.
void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
SourceLocation *TemplateArgLocs,
- llvm::SmallVector<TemplateArgument, 16> &TemplateArgs) {
+ llvm::SmallVector<TemplateArgumentLoc, 16> &TemplateArgs) {
TemplateArgs.reserve(TemplateArgsIn.size());
void **Args = TemplateArgsIn.getArgs();
bool *ArgIsType = TemplateArgsIn.getArgIsType();
for (unsigned Arg = 0, Last = TemplateArgsIn.size(); Arg != Last; ++Arg) {
- TemplateArgs.push_back(
- ArgIsType[Arg]? TemplateArgument(TemplateArgLocs[Arg],
- //FIXME: Preserve type source info.
- Sema::GetTypeFromParser(Args[Arg]))
- : TemplateArgument(reinterpret_cast<Expr *>(Args[Arg])));
+ if (ArgIsType[Arg]) {
+ DeclaratorInfo *DI;
+ QualType T = Sema::GetTypeFromParser(Args[Arg], &DI);
+ if (!DI) DI = Context.getTrivialDeclaratorInfo(T, TemplateArgLocs[Arg]);
+ TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(T), DI));
+ } else {
+ Expr *E = reinterpret_cast<Expr *>(Args[Arg]);
+ TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(E), E));
+ }
}
}
QualType Sema::CheckTemplateIdType(TemplateName Name,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc) {
TemplateDecl *Template = Name.getAsTemplateDecl();
@@ -1155,7 +1185,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
Converted.flatSize());
// FIXME: CanonType is not actually the canonical type, and unfortunately
- // it is a TemplateTypeSpecializationType that we will never use again.
+ // it is a TemplateSpecializationType that we will never use again.
// In the future, we need to teach getTemplateSpecializationType to only
// build the canonical type and return that to us.
CanonType = Context.getCanonicalType(CanonType);
@@ -1190,7 +1220,6 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// Build the fully-sugared type for this class template
// specialization, which refers back to the class template
// specialization we created or found.
- //FIXME: Preserve type source info.
return Context.getTemplateSpecializationType(Name, TemplateArgs,
NumTemplateArgs, CanonType);
}
@@ -1199,13 +1228,13 @@ Action::TypeResult
Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation *TemplateArgLocs,
+ SourceLocation *TemplateArgLocsIn,
SourceLocation RAngleLoc) {
TemplateName Template = TemplateD.getAsVal<TemplateName>();
// Translate the parser's template argument list in our AST format.
- llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
- translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
+ llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
+ translateTemplateArguments(TemplateArgsIn, TemplateArgLocsIn, TemplateArgs);
QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc,
TemplateArgs.data(),
@@ -1216,7 +1245,16 @@ Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
if (Result.isNull())
return true;
- return Result.getAsOpaquePtr();
+ DeclaratorInfo *DI = Context.CreateDeclaratorInfo(Result);
+ TemplateSpecializationTypeLoc TL
+ = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc());
+ TL.setTemplateNameLoc(TemplateLoc);
+ TL.setLAngleLoc(LAngleLoc);
+ TL.setRAngleLoc(RAngleLoc);
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+ TL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
+
+ return CreateLocInfoType(Result, DI).getAsOpaquePtr();
}
Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult,
@@ -1226,7 +1264,9 @@ Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult,
if (TypeResult.isInvalid())
return Sema::TypeResult();
- QualType Type = QualType::getFromOpaquePtr(TypeResult.get());
+ // FIXME: preserve source info, ideally without copying the DI.
+ DeclaratorInfo *DI;
+ QualType Type = GetTypeFromParser(TypeResult.get(), &DI);
// Verify the tag specifier.
TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec);
@@ -1256,7 +1296,7 @@ Sema::OwningExprResult Sema::BuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
TemplateName Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc) {
// FIXME: Can we do any checking at this point? I guess we could check the
@@ -1296,13 +1336,13 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation *TemplateArgLocs,
+ SourceLocation *TemplateArgSLs,
SourceLocation RAngleLoc) {
TemplateName Template = TemplateD.getAsVal<TemplateName>();
// Translate the parser's template argument list in our AST format.
- llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
- translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
+ llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
+ translateTemplateArguments(TemplateArgsIn, TemplateArgSLs, TemplateArgs);
TemplateArgsIn.release();
return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(),
@@ -1312,41 +1352,6 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS,
RAngleLoc);
}
-Sema::OwningExprResult
-Sema::ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- TemplateTy TemplateD,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation *TemplateArgLocs,
- SourceLocation RAngleLoc) {
- TemplateName Template = TemplateD.getAsVal<TemplateName>();
-
- // FIXME: We're going to end up looking up the template based on its name,
- // twice!
- DeclarationName Name;
- if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl())
- Name = ActualTemplate->getDeclName();
- else if (OverloadedFunctionDecl *Ovl = Template.getAsOverloadedFunctionDecl())
- Name = Ovl->getDeclName();
- else
- Name = Template.getAsDependentTemplateName()->getName();
-
- // Translate the parser's template argument list in our AST format.
- llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
- translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
- TemplateArgsIn.release();
-
- // Do we have the save the actual template name? We might need it...
- return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, TemplateNameLoc,
- Name, true, LAngleLoc,
- TemplateArgs.data(), TemplateArgs.size(),
- RAngleLoc, DeclPtrTy(), &SS);
-}
-
/// \brief Form a dependent template name.
///
/// This action forms a dependent template name given the template
@@ -1356,9 +1361,8 @@ Sema::ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
/// of the "template" keyword, and "apply" is the \p Name.
Sema::TemplateTy
Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
- const IdentifierInfo &Name,
- SourceLocation NameLoc,
const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType) {
if ((ObjectType &&
computeDeclContext(QualType::getFromOpaquePtr(ObjectType))) ||
@@ -1380,11 +1384,13 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
// "template" keyword is now permitted). We follow the C++0x
// rules, even in C++03 mode, retroactively applying the DR.
TemplateTy Template;
- TemplateNameKind TNK = isTemplateName(0, Name, NameLoc, &SS, ObjectType,
+ TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType,
false, Template);
if (TNK == TNK_Non_template) {
- Diag(NameLoc, diag::err_template_kw_refers_to_non_template)
- << &Name;
+ Diag(Name.getSourceRange().getBegin(),
+ diag::err_template_kw_refers_to_non_template)
+ << GetNameFromUnqualifiedId(Name)
+ << Name.getSourceRange();
return TemplateTy();
}
@@ -1393,12 +1399,32 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
NestedNameSpecifier *Qualifier
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
- return TemplateTy::make(Context.getDependentTemplateName(Qualifier, &Name));
+
+ switch (Name.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ return TemplateTy::make(Context.getDependentTemplateName(Qualifier,
+ Name.Identifier));
+
+ case UnqualifiedId::IK_OperatorFunctionId:
+ return TemplateTy::make(Context.getDependentTemplateName(Qualifier,
+ Name.OperatorFunctionId.Operator));
+
+ default:
+ break;
+ }
+
+ Diag(Name.getSourceRange().getBegin(),
+ diag::err_template_kw_refers_to_non_template)
+ << GetNameFromUnqualifiedId(Name)
+ << Name.getSourceRange();
+ return TemplateTy();
}
bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
- const TemplateArgument &Arg,
+ const TemplateArgumentLoc &AL,
TemplateArgumentListBuilder &Converted) {
+ const TemplateArgument &Arg = AL.getArgument();
+
// Check template type parameter.
if (Arg.getKind() != TemplateArgument::Type) {
// C++ [temp.arg.type]p1:
@@ -1407,19 +1433,19 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
// We have a template type parameter but the template argument
// is not a type.
- Diag(Arg.getLocation(), diag::err_template_arg_must_be_type);
+ SourceRange SR = AL.getSourceRange();
+ Diag(SR.getBegin(), diag::err_template_arg_must_be_type) << SR;
Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
- if (CheckTemplateArgument(Param, Arg.getAsType(), Arg.getLocation()))
+ if (CheckTemplateArgument(Param, AL.getSourceDeclaratorInfo()))
return true;
// Add the converted template type argument.
Converted.Append(
- TemplateArgument(Arg.getLocation(),
- Context.getCanonicalType(Arg.getAsType())));
+ TemplateArgument(Context.getCanonicalType(Arg.getAsType())));
return false;
}
@@ -1428,7 +1454,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc,
bool PartialTemplateArgs,
@@ -1474,7 +1500,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
break;
// Decode the template argument
- TemplateArgument Arg;
+ TemplateArgumentLoc Arg;
+
if (ArgIdx >= NumArgs) {
// Retrieve the default template argument from the template
// parameter.
@@ -1489,11 +1516,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (!TTP->hasDefaultArgument())