aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-11-05 17:18:09 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-11-05 17:18:09 +0000
commit8f57cb0305232cb53fff00ef151ca716766f3437 (patch)
tree8b316eca843681b024034db1125707173b9adb4a /lib
parent51fb8b013e7734b795139f49d3b1f77c539be20a (diff)
downloadsrc-8f57cb0305232cb53fff00ef151ca716766f3437.tar.gz
src-8f57cb0305232cb53fff00ef151ca716766f3437.zip
Update clang to r86140.
Notes
Notes: svn path=/vendor/clang/dist/; revision=198954
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTContext.cpp5
-rw-r--r--lib/AST/DeclarationName.cpp50
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp69
-rw-r--r--lib/AST/RecordLayoutBuilder.h9
-rw-r--r--lib/AST/Type.cpp6
-rw-r--r--lib/Analysis/GRExprEngine.cpp43
-rw-r--r--lib/Analysis/UndefinedAssignmentChecker.cpp33
-rw-r--r--lib/Analysis/VLASizeChecker.cpp6
-rw-r--r--lib/CodeGen/CGCXX.cpp30
-rw-r--r--lib/CodeGen/CGDecl.cpp10
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp16
-rw-r--r--lib/CodeGen/CodeGenFunction.h37
-rw-r--r--lib/Frontend/AnalysisConsumer.cpp60
-rw-r--r--lib/Frontend/HTMLDiagnostics.cpp92
-rw-r--r--lib/Frontend/HTMLPrint.cpp36
-rw-r--r--lib/Frontend/InitPreprocessor.cpp10
-rw-r--r--lib/Frontend/PlistDiagnostics.cpp59
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp1
-rw-r--r--lib/Headers/stdint.h158
-rw-r--r--lib/Lex/Preprocessor.cpp8
-rw-r--r--lib/Parse/DeclSpec.cpp8
-rw-r--r--lib/Parse/MinimalAction.cpp6
-rw-r--r--lib/Parse/ParseDecl.cpp6
-rw-r--r--lib/Parse/ParseDeclCXX.cpp49
-rw-r--r--lib/Parse/ParseExprCXX.cpp135
-rw-r--r--lib/Parse/ParseTemplate.cpp9
-rw-r--r--lib/Parse/ParseTentative.cpp3
-rw-r--r--lib/Rewrite/HTMLRewrite.cpp44
-rw-r--r--lib/Sema/Sema.h15
-rw-r--r--lib/Sema/SemaCXXCast.cpp3
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp131
-rw-r--r--lib/Sema/SemaDeclCXX.cpp148
-rw-r--r--lib/Sema/SemaExpr.cpp81
-rw-r--r--lib/Sema/SemaExprCXX.cpp10
-rw-r--r--lib/Sema/SemaOverload.cpp33
-rw-r--r--lib/Sema/SemaTemplate.cpp2
-rw-r--r--lib/Sema/SemaType.cpp75
-rw-r--r--lib/Sema/TreeTransform.h50
38 files changed, 838 insertions, 708 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index aef3d2989415..8562249479ca 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1374,7 +1374,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) {
// If the pointee or class type isn't canonical, this won't be a canonical
// type either, so fill in the canonical type field.
QualType Canonical;
- if (!T.isCanonical()) {
+ if (!T.isCanonical() || !Cls->isCanonicalUnqualified()) {
Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls));
// Get the new insert position for the node we care about.
@@ -1395,7 +1395,8 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
const llvm::APInt &ArySizeIn,
ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals) {
- assert((EltTy->isDependentType() || EltTy->isConstantSizeType()) &&
+ assert((EltTy->isDependentType() ||
+ EltTy->isIncompleteType() || EltTy->isConstantSizeType()) &&
"Constant array of VLAs is illegal!");
// Convert the array size into a canonical width matching the pointer size for
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 56a597570dd0..8664c508615f 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TypeOrdering.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/DenseMap.h"
@@ -49,11 +50,50 @@ public:
};
bool operator<(DeclarationName LHS, DeclarationName RHS) {
- if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
- if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
- return LhsId->getName() < RhsId->getName();
-
- return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();
+ if (LHS.getNameKind() != RHS.getNameKind())
+ return LHS.getNameKind() < RHS.getNameKind();
+
+ switch (LHS.getNameKind()) {
+ case DeclarationName::Identifier:
+ return LHS.getAsIdentifierInfo()->getName() <
+ RHS.getAsIdentifierInfo()->getName();
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector: {
+ Selector LHSSelector = LHS.getObjCSelector();
+ Selector RHSSelector = RHS.getObjCSelector();
+ for (unsigned I = 0,
+ N = std::min(LHSSelector.getNumArgs(), RHSSelector.getNumArgs());
+ I != N; ++I) {
+ IdentifierInfo *LHSId = LHSSelector.getIdentifierInfoForSlot(I);
+ IdentifierInfo *RHSId = RHSSelector.getIdentifierInfoForSlot(I);
+ if (!LHSId || !RHSId)
+ return LHSId && !RHSId;
+
+ switch (LHSId->getName().compare(RHSId->getName())) {
+ case -1: return true;
+ case 1: return false;
+ default: break;
+ }
+ }
+
+ return LHSSelector.getNumArgs() < RHSSelector.getNumArgs();
+ }
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ return QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType());
+
+ case DeclarationName::CXXOperatorName:
+ return LHS.getCXXOverloadedOperator() < RHS.getCXXOverloadedOperator();
+
+ case DeclarationName::CXXUsingDirective:
+ return false;
+ }
+
+ return false;
}
} // end namespace clang
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 0b159c3a7bd8..021c53e9514f 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -174,9 +174,24 @@ void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
LayoutBaseNonVirtually(RD, true);
}
-void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
+uint64_t ASTRecordLayoutBuilder::getBaseOffset(const CXXRecordDecl *Base) {
+ for (size_t i = 0; i < Bases.size(); ++i) {
+ if (Bases[i].first == Base)
+ return Bases[i].second;
+ }
+ for (size_t i = 0; i < VBases.size(); ++i) {
+ if (VBases[i].first == Base)
+ return VBases[i].second;
+ }
+ assert(0 && "missing base");
+ return 0;
+}
+
+
+void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class,
+ const CXXRecordDecl *RD,
const CXXRecordDecl *PB,
- int64_t Offset,
+ uint64_t Offset,
llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
@@ -185,20 +200,7 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
"Cannot layout class with dependent bases.");
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
-#if 0
- const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base);
- const CXXRecordDecl *PB = L.getPrimaryBase();
- if (PB && L.getPrimaryBaseWasVirtual()
- && IndirectPrimary.count(PB)) {
- int64_t BaseOffset;
- // FIXME: calculate this.
- BaseOffset = (1<<63) | (1<<31);
- VBases.push_back(PB);
- VBaseOffsets.push_back(BaseOffset);
- }
-#endif
- int64_t BaseOffset = Offset;;
- // FIXME: Calculate BaseOffset.
+ uint64_t BaseOffset = Offset;
if (i->isVirtual()) {
if (Base == PB) {
// Only lay things out once.
@@ -220,11 +222,20 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
LayoutVirtualBase(Base);
BaseOffset = VBases.back().second;
}
+ } else {
+ if (RD == Class)
+ BaseOffset = getBaseOffset(Base);
+ else {
+ const ASTRecordLayout &Layout
+ = Ctx.getASTRecordLayout(RD);
+ BaseOffset = Offset + Layout.getBaseClassOffset(Base);
+ }
}
+
if (Base->getNumVBases()) {
const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base);
const CXXRecordDecl *PB = L.getPrimaryBase();
- LayoutVirtualBases(Base, PB, BaseOffset, mark, IndirectPrimary);
+ LayoutVirtualBases(Class, Base, PB, BaseOffset, mark, IndirectPrimary);
}
}
}
@@ -295,7 +306,7 @@ bool ASTRecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD,
const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD);
uint64_t NumElements = Ctx.getConstantArrayElementCount(AT);
- unsigned ElementOffset = Offset;
+ uint64_t ElementOffset = Offset;
for (uint64_t I = 0; I != NumElements; ++I) {
if (!canPlaceRecordAtOffset(RD, ElementOffset))
return false;
@@ -366,7 +377,7 @@ ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const FieldDecl *FD,
const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD);
uint64_t NumElements = Ctx.getConstantArrayElementCount(AT);
- unsigned ElementOffset = Offset;
+ uint64_t ElementOffset = Offset;
for (uint64_t I = 0; I != NumElements; ++I) {
UpdateEmptyClassOffsets(RD, ElementOffset);
@@ -419,29 +430,13 @@ uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD,
bool IsVirtualBase) {
// Layout the base.
- unsigned Offset = LayoutBase(RD);
+ uint64_t Offset = LayoutBase(RD);
// Add base class offsets.
if (IsVirtualBase)
VBases.push_back(std::make_pair(RD, Offset));
else
Bases.push_back(std::make_pair(RD, Offset));
-
-#if 0
- // And now add offsets for all our primary virtual bases as well, so
- // they all have offsets.
- const ASTRecordLayout *L = &BaseInfo;
- const CXXRecordDecl *PB = L->getPrimaryBase();
- while (PB) {
- if (L->getPrimaryBaseWasVirtual()) {
- VBases.push_back(PB);
- VBaseOffsets.push_back(Size);
- }
- PB = L->getPrimaryBase();
- if (PB)
- L = &Ctx.getASTRecordLayout(PB);
- }
-#endif
}
void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
@@ -476,7 +471,7 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
if (RD) {
llvm::SmallSet<const CXXRecordDecl*, 32> mark;
- LayoutVirtualBases(RD, PrimaryBase, 0, mark, IndirectPrimaryBases);
+ LayoutVirtualBases(RD, RD, PrimaryBase, 0, mark, IndirectPrimaryBases);
}
// Finally, round the size of the total struct up to the alignment of the
diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h
index b57b37d0df4d..077072343b1b 100644
--- a/lib/AST/RecordLayoutBuilder.h
+++ b/lib/AST/RecordLayoutBuilder.h
@@ -99,9 +99,9 @@ class ASTRecordLayoutBuilder {
void LayoutNonVirtualBases(const CXXRecordDecl *RD);
void LayoutBaseNonVirtually(const CXXRecordDecl *RD, bool IsVBase);
void LayoutVirtualBase(const CXXRecordDecl *RD);
- void LayoutVirtualBases(const CXXRecordDecl *RD, const CXXRecordDecl *PB,
- int64_t Offset,
- llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
+ void LayoutVirtualBases(const CXXRecordDecl *Class, const CXXRecordDecl *RD,
+ const CXXRecordDecl *PB, uint64_t Offset,
+ llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary);
/// canPlaceRecordAtOffset - Return whether a record (either a base class
@@ -124,6 +124,9 @@ class ASTRecordLayoutBuilder {
/// given offset.
void UpdateEmptyClassOffsets(const FieldDecl *FD, uint64_t Offset);
+ /// getBaseOffset - Get the offset of a direct base class.
+ uint64_t getBaseOffset(const CXXRecordDecl *Base);
+
/// FinishLayout - Finalize record layout. Adjust record size based on the
/// alignment.
void FinishLayout();
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 3608d34c691d..779f6808b6c1 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -550,6 +550,12 @@ bool Type::isIncompleteType() const {
// A tagged type (struct/union/enum/class) is incomplete if the decl is a
// forward declaration, but not a full definition (C99 6.2.5p22).
return !cast<TagType>(CanonicalType)->getDecl()->isDefinition();
+ case ConstantArray:
+ // An array is incomplete if its element type is incomplete
+ // (C++ [dcl.array]p1).
+ // We don't handle variable arrays (they're not allowed in C++) or
+ // dependent-sized arrays (dependent types are never treated as incomplete).
+ return cast<ArrayType>(CanonicalType)->getElementType()->isIncompleteType();
case IncompleteArray:
// An array of unknown size is an incomplete type (C99 6.2.5p22).
return true;
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index c71882e4d888..212fea3a6bcc 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -141,7 +141,8 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
// FIXME: This is largely copy-paste from CheckerVisit(). Need to
// unify.
-void GRExprEngine::CheckerVisitBind(Stmt *S, ExplodedNodeSet &Dst,
+void GRExprEngine::CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
+ ExplodedNodeSet &Dst,
ExplodedNodeSet &Src,
SVal location, SVal val, bool isPrevisit) {
@@ -164,8 +165,8 @@ void GRExprEngine::CheckerVisitBind(Stmt *S, ExplodedNodeSet &Dst,
for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
NI != NE; ++NI)
- checker->GR_VisitBind(*CurrSet, *Builder, *this, S, *NI, tag, location,
- val, isPrevisit);
+ checker->GR_VisitBind(*CurrSet, *Builder, *this, AssignE, StoreE,
+ *NI, tag, location, val, isPrevisit);
// Update which NodeSet is the current one.
PrevSet = CurrSet;
@@ -1125,7 +1126,8 @@ 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, Stmt* Ex, ExplodedNode* Pred,
+void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE,
+ Stmt* StoreE, ExplodedNode* Pred,
const GRState* state, SVal location, SVal Val,
bool atDeclInit) {
@@ -1133,7 +1135,7 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred,
// Do a previsit of the bind.
ExplodedNodeSet CheckedSet, Src;
Src.Add(Pred);
- CheckerVisitBind(Ex, CheckedSet, Src, location, Val, true);
+ CheckerVisitBind(AssignE, StoreE, CheckedSet, Src, location, Val, true);
for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
I!=E; ++I) {
@@ -1166,7 +1168,7 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred,
// 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,
+ GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, StoreE,
newState != state);
getTF().EvalBind(BuilderRef, location, Val);
@@ -1179,14 +1181,16 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred,
/// @param state The current simulation state
/// @param location The location to store the value
/// @param Val The value to be stored
-void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
+void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr *AssignE,
+ Expr* StoreE,
+ ExplodedNode* Pred,
const GRState* state, SVal location, SVal Val,
const void *tag) {
- assert (Builder && "GRStmtNodeBuilder must be defined.");
+ assert(Builder && "GRStmtNodeBuilder must be defined.");
// Evaluate the location (checks for bad dereferences).
- Pred = EvalLocation(Ex, Pred, state, location, tag);
+ Pred = EvalLocation(StoreE, Pred, state, location, tag);
if (!Pred)
return;
@@ -1199,7 +1203,7 @@ void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
SaveAndRestore<const void*> OldTag(Builder->Tag);
Builder->PointKind = ProgramPoint::PostStoreKind;
Builder->Tag = tag;
- EvalBind(Dst, Ex, Pred, state, location, Val);
+ EvalBind(Dst, AssignE, StoreE, Pred, state, location, Val);
}
void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
@@ -1231,17 +1235,6 @@ void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
}
}
-void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr* Ex, Expr* StoreE,
- ExplodedNode* Pred, const GRState* state,
- SVal location, SVal Val, const void *tag) {
-
- ExplodedNodeSet TmpDst;
- EvalStore(TmpDst, StoreE, Pred, state, location, Val, tag);
-
- for (ExplodedNodeSet::iterator I=TmpDst.begin(), E=TmpDst.end(); I!=E; ++I)
- MakeNode(Dst, Ex, *I, (*I)->getState(), ProgramPoint::PostStmtKind, tag);
-}
-
ExplodedNode* GRExprEngine::EvalLocation(Stmt* Ex, ExplodedNode* Pred,
const GRState* state, SVal location,
const void *tag) {
@@ -1402,7 +1395,7 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet& Dst,
newValueExpr->getType());
}
- Engine.EvalStore(TmpStore, theValueExpr, N, stateEqual, location,
+ Engine.EvalStore(TmpStore, NULL, theValueExpr, N, stateEqual, location,
val, OSAtomicStoreTag);
// Now bind the result of the comparison.
@@ -2147,8 +2140,8 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
Builder->getCurrentBlockCount());
}
- EvalBind(Dst, DS, *I, state, loc::MemRegionVal(state->getRegion(VD, LC)),
- InitVal, true);
+ EvalBind(Dst, DS, DS, *I, state,
+ loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
}
else {
state = state->bindDeclWithNoInit(state->getRegion(VD, LC));
@@ -2570,7 +2563,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
state = state->BindExpr(U, U->isPostfix() ? V2 : Result);
// Perform the store.
- EvalStore(Dst, U, *I2, state, V1, Result);
+ EvalStore(Dst, NULL, U, *I2, state, V1, Result);
}
}
}
diff --git a/lib/Analysis/UndefinedAssignmentChecker.cpp b/lib/Analysis/UndefinedAssignmentChecker.cpp
index c5b2401f47ce..2e3ac34913ab 100644
--- a/lib/Analysis/UndefinedAssignmentChecker.cpp
+++ b/lib/Analysis/UndefinedAssignmentChecker.cpp
@@ -22,14 +22,15 @@ void *UndefinedAssignmentChecker::getTag() {
return &x;
}
-void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
- const Stmt *S,
+void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
+ const Stmt *AssignE,
+ const Stmt *StoreE,
SVal location,
SVal val) {
if (!val.isUndef())
return;
- ExplodedNode *N = C.GenerateNode(S, true);
+ ExplodedNode *N = C.GenerateNode(StoreE, true);
if (!N)
return;
@@ -40,20 +41,20 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
// 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);
+ if (AssignE) {
+ const Expr *ex = 0;
+
+ if (const BinaryOperator *B = dyn_cast<BinaryOperator>(AssignE))
+ ex = B->getRHS();
+ else if (const DeclStmt *DS = dyn_cast<DeclStmt>(AssignE)) {
+ 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
index 76e4477449ed..0e731902f4bb 100644
--- a/lib/Analysis/VLASizeChecker.cpp
+++ b/lib/Analysis/VLASizeChecker.cpp
@@ -38,8 +38,8 @@ ExplodedNode *UndefSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
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");
+ BT = new BugType("Declared variable-length array (VLA) uses a garbage"
+ " value as its size", "Logic error");
EnhancedBugReport *R =
new EnhancedBugReport(*BT, BT->getName().c_str(), N);
@@ -81,7 +81,7 @@ ExplodedNode *ZeroSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
if (ExplodedNode* N = Builder.generateNode(S, zeroState, Pred)) {
N->markAsSink();
if (!BT)
- BT = new BugType("Declare variable-length array (VLA) of zero size",
+ BT = new BugType("Declared variable-length array (VLA) has zero size",
"Logic error");
EnhancedBugReport *R =
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 3e854ca279b6..cf172b1a1cb6 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -291,7 +291,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E) {
const FunctionProtoType *FPT =
MPT->getPointeeType()->getAs<FunctionProtoType>();
const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(cast<RecordType>(MPT->getClass())->getDecl());
+ cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
const llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
@@ -810,8 +810,32 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
Callee, CallArgs, MD);
if (nv_r || v_r) {
+ bool CanBeZero = !(ResultType->isReferenceType()
+ // FIXME: attr nonnull can't be zero either
+ /* || ResultType->hasAttr<NonNullAttr>() */ );
// Do the return result adjustment.
- RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r));
+ if (CanBeZero) {
+ llvm::BasicBlock *NonZeroBlock = createBasicBlock();
+ llvm::BasicBlock *ZeroBlock = createBasicBlock();
+ llvm::BasicBlock *ContBlock = createBasicBlock();
+
+ const llvm::Type *Ty = RV.getScalarVal()->getType();
+ llvm::Value *Zero = llvm::Constant::getNullValue(Ty);
+ Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero),
+ NonZeroBlock, ZeroBlock);
+ EmitBlock(NonZeroBlock);
+ llvm::Value *NZ = DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r);
+ EmitBranch(ContBlock);
+ EmitBlock(ZeroBlock);
+ llvm::Value *Z = RV.getScalarVal();
+ EmitBlock(ContBlock);
+ llvm::PHINode *RVOrZero = Builder.CreatePHI(Ty);
+ RVOrZero->reserveOperandSpace(2);
+ RVOrZero->addIncoming(NZ, NonZeroBlock);
+ RVOrZero->addIncoming(Z, ZeroBlock);
+ RV = RValue::get(RVOrZero);
+ } else
+ RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r));
}
if (!ResultType->isVoidType())
@@ -1421,6 +1445,8 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
if (FieldType->isReferenceType())
RHS = EmitReferenceBindingToExpr(RhsExpr, FieldType,
/*IsInitializer=*/true);
+ else if (FieldType->isMemberFunctionPointerType())
+ RHS = RValue::get(CGM.EmitConstantExpr(RhsExpr, FieldType, this));
else
RHS = RValue::get(EmitScalarExpr(RhsExpr, true));
EmitStoreThroughLValue(RHS, LHS, FieldType);
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index b1ceb4627712..2021ced31683 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -515,18 +515,22 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
const CXXDestructorDecl *D = ClassDecl->getDestructor(getContext());
assert(D && "EmitLocalBlockVarDecl - destructor is nul");
- CleanupScope scope(*this);
if (const ConstantArrayType *Array =
getContext().getAsConstantArrayType(Ty)) {
+ CleanupScope Scope(*this);
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
+
+ // Make sure to jump to the exit block.
+ EmitBranch(Scope.getCleanupExitBlock());
+ } else {
+ CleanupScope Scope(*this);
EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
+ }
}
}
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 88beadf33140..4be341311ce4 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -665,8 +665,9 @@ llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) {
return EmitLValue(E).getAddress();
}
-void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupBlock) {
- CleanupEntries.push_back(CleanupEntry(CleanupBlock));
+void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
+ llvm::BasicBlock *CleanupExitBlock) {
+ CleanupEntries.push_back(CleanupEntry(CleanupEntryBlock, CleanupExitBlock));
}
void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) {
@@ -680,7 +681,7 @@ void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) {
CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
CleanupEntry &CE = CleanupEntries.back();
- llvm::BasicBlock *CleanupBlock = CE.CleanupBlock;
+ llvm::BasicBlock *CleanupEntryBlock = CE.CleanupEntryBlock;
std::vector<llvm::BasicBlock *> Blocks;
std::swap(Blocks, CE.Blocks);
@@ -711,10 +712,11 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
}
}
- llvm::BasicBlock *SwitchBlock = 0;
+ llvm::BasicBlock *SwitchBlock = CE.CleanupExitBlock;
llvm::BasicBlock *EndBlock = 0;
if (!BranchFixups.empty()) {
- SwitchBlock = createBasicBlock("cleanup.switch");
+ if (!SwitchBlock)
+ SwitchBlock = createBasicBlock("cleanup.switch");
EndBlock = createBasicBlock("cleanup.end");
llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
@@ -745,7 +747,7 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
llvm::BasicBlock *Dest = BI->getSuccessor(0);
// Fixup the branch instruction to point to the cleanup block.
- BI->setSuccessor(0, CleanupBlock);
+ BI->setSuccessor(0, CleanupEntryBlock);
if (CleanupEntries.empty()) {
llvm::ConstantInt *ID;
@@ -802,7 +804,7 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
BlockScopes.erase(Blocks[i]);
}
- return CleanupBlockInfo(CleanupBlock, SwitchBlock, EndBlock);
+ return CleanupBlockInfo(CleanupEntryBlock, SwitchBlock, EndBlock);
}
void CodeGenFunction::EmitCleanupBlock() {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 9bb219642ab4..fe8113e95332 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -108,11 +108,12 @@ public:
/// PushCleanupBlock - Push a new cleanup entry on the stack and set the
/// passed in block as the cleanup block.
- void PushCleanupBlock(llvm::BasicBlock *CleanupBlock);
+ void PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
+ llvm::BasicBlock *CleanupExitBlock = 0);
/// CleanupBlockInfo - A struct representing a popped cleanup block.
struct CleanupBlockInfo {
- /// CleanupBlock - the cleanup block
+ /// CleanupEntryBlock - the cleanup entry block
llvm::BasicBlock *CleanupBlock;
/// SwitchBlock - the block (if any) containing the switch instruction used
@@ -138,17 +139,24 @@ public:
class CleanupScope {
CodeGenFunction& CGF;
llvm::BasicBlock *CurBB;
- llvm::BasicBlock *CleanupBB;
-
+ llvm::BasicBlock *CleanupEntryBB;
+ llvm::BasicBlock *CleanupExitBB;
+
public:
CleanupScope(CodeGenFunction &cgf)
- : CGF(cgf), CurBB(CGF.Builder.GetInsertBlock()) {
- CleanupBB = CGF.createBasicBlock("cleanup");
- CGF.Builder.SetInsertPoint(CleanupBB);
+ : CGF(cgf), CurBB(CGF.Builder.GetInsertBlock()),
+ CleanupEntryBB(CGF.createBasicBlock("cleanup")), CleanupExitBB(0) {
+ CGF.Builder.SetInsertPoint(CleanupEntryBB);
}
+ llvm::BasicBlock *getCleanupExitBlock() {
+ if (!CleanupExitBB)
+ CleanupExitBB = CGF.createBasicBlock("cleanup.exit");
+ return CleanupExitBB;
+ }
+
~CleanupScope() {
- CGF.PushCleanupBlock(CleanupBB);
+ CGF.PushCleanupBlock(CleanupEntryBB, CleanupExitBB);
// FIXME: This is silly, move this into the builder.
if (CurBB)
CGF.Builder.SetInsertPoint(CurBB);
@@ -250,9 +258,12 @@ private:
bool DidCallStackSave;
struct CleanupEntry {
- /// CleanupBlock - The block of code that does the actual cleanup.
- llvm::BasicBlock *CleanupBlock;
+ /// CleanupEntryBlock - The block of code that does the actual cleanup.
+ llvm::BasicBlock *CleanupEntryBlock;
+ /// CleanupExitBlock - The cleanup exit block.
+ llvm::BasicBlock *CleanupExitBlock;
+
/// Blocks - Basic blocks that were emitted in the current cleanup scope.
std::vector<llvm::BasicBlock *> Blocks;
@@ -260,8 +271,10 @@ private:
/// inserted into the current function yet.
std::vector<llvm::BranchInst *> BranchFixups;
- explicit CleanupEntry(llvm::BasicBlock *cb)
- : CleanupBlock(cb) {}
+ explicit CleanupEntry(llvm::BasicBlock *CleanupEntryBlock,
+ llvm::BasicBlock *CleanupExitBlock)
+ : CleanupEntryBlock(CleanupEntryBlock),
+ CleanupExitBlock(CleanupExitBlock) {}
};
/// CleanupEntries - Stack of cleanup entries.
diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp
index 049f3bd3ea14..d2831fae566a 100644
--- a/lib/Frontend/AnalysisConsumer.cpp
+++ b/lib/Frontend/AnalysisConsumer.cpp
@@ -12,23 +12,24 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/AnalysisConsumer.h"
-#include "clang/Frontend/PathDiagnosticClients.h"
-#include "clang/Frontend/ManagerRegistry.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
-#include "clang/Analysis/CFG.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/PathDiagnostic.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/AST/ParentMap.h"
#include "clang/Analysis/PathSensitive/AnalysisManager.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
-#include "clang/Analysis/Analyses/LiveVariables.h"
-#include "clang/Analysis/LocalCheckers.h"
-#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/ManagerRegistry.h"
+#include "clang/Frontend/PathDiagnosticClients.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
@@ -52,12 +53,11 @@ namespace {
//===----------------------------------------------------------------------===//
static PathDiagnosticClient*
-CreatePlistHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP,
- PreprocessorFactory* PPF) {
+CreatePlistHTMLDiagnosticClient(const std::string& prefix,
+ const Preprocessor &PP) {
llvm::sys::Path F(prefix);
- PathDiagnosticClientFactory *PF =
- CreateHTMLDiagnosticClientFactory(F.getDirname(), PP, PPF);
- return CreatePlistDiagnosticClient(prefix, PP, PPF, PF);
+ PathDiagnosticClient *PD = CreateHTMLDiagnosticClient(F.getDirname(), PP);
+ return CreatePlistDiagnosticClient(prefix, PP, PD);
}
//===----------------------------------------------------------------------===//
@@ -74,11 +74,8 @@ namespace {
Actions TranslationUnitActions;
public:
- const LangOptions& LOpts;
- Diagnostic &Diags;
ASTContext* Ctx;
- Preprocessor* PP;
- PreprocessorFactory* PPF;
+ const Preprocessor &PP;
const std::string OutDir;
AnalyzerOptions Opts;
@@ -91,14 +88,11 @@ namespace {
llvm::OwningPtr<AnalysisManager> Mgr;
- AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
- PreprocessorFactory* ppf,
- const LangOptions& lopts,
+ AnalysisConsumer(const Preprocessor& pp,
const std::string& outdir,
const AnalyzerOptions& opts)
- : LOpts(lopts), Diags(diags),
- Ctx(0), PP(pp), PPF(ppf),
- OutDir(outdir), Opts(opts), PD(0) {
+ : Ctx(0), PP(pp), OutDir(outdir),
+ Opts(opts), PD(0) {
DigestAnalyzerOptions();
}
@@ -108,7 +102,7 @@ namespace {
switch (Opts.AnalysisDiagOpt) {
default:
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
- case PD_##NAME: PD = CREATEFN(OutDir, PP, PPF); break;
+ case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
#include "clang/Frontend/Analyses.def"
}
}
@@ -155,7 +149,8 @@ namespace {
virtual void Initialize(ASTContext &Context) {
Ctx = &Context;
- Mgr.reset(new AnalysisManager(*Ctx, Diags, LOpts, PD,
+ Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
+ PP.getLangOptions(), PD,
CreateStoreMgr, CreateConstraintMgr,
Opts.AnalyzerDisplayProgress,
Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
@@ -263,7 +258,7 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
// Don't run the actions if an error has occured with parsing the file.
- if (Diags.hasErrorOccurred())
+ if (PP.getDiagnostics().hasErrorOccurred())
return;
// Don't run the actions on declarations in header files unless
@@ -443,15 +438,10 @@ static void ActionInlineCall(AnalysisManager &mgr, Decl *D) {
// AnalysisConsumer creation.
//===----------------------------------------------------------------------===//
-ASTConsumer* clang::CreateAnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
- PreprocessorFactory* ppf,
- const LangOptions& lopts,
+ASTConsumer* clang::CreateAnalysisConsumer(const Preprocessor& pp,
const std::string& OutDir,
const AnalyzerOptions& Opts) {
-
- llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(diags, pp, ppf,
- lopts, OutDir,
- Opts));
+ llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(pp, OutDir, Opts));
for (unsigned i = 0; i < Opts.AnalysisList.size(); ++i)
switch (Opts.AnalysisList[i]) {
@@ -464,7 +454,7 @@ ASTConsumer* clang::CreateAnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
}
// Last, disable the effects of '-Werror' when using the AnalysisConsumer.
- diags.setWarningsAsErrors(false);
+ pp.getDiagnostics().setWarningsAsErrors(false);
return C.take();
}
diff --git a/lib/Frontend/HTMLDiagnostics.cpp b/lib/Frontend/HTMLDiagnostics.cpp
index 9d6f96c69f5d..145d53f3fc6e 100644
--- a/lib/Frontend/HTMLDiagnostics.cpp
+++ b/lib/Frontend/HTMLDiagnostics.cpp
@@ -37,18 +37,20 @@ namespace {
class VISIBILITY_HIDDEN HTMLDiagnostics : public PathDiagnosticClient {
llvm::sys::Path Directory, FilePrefix;
bool createdDir, noDir;
- Preprocessor* PP;
+ const Preprocessor &PP;
std::vector<const PathDiagnostic*> BatchedDiags;
- llvm::SmallVectorImpl<std::string> *FilesMade;
public:
- HTMLDiagnostics(const std::string& prefix, Preprocessor* pp,
- llvm::SmallVectorImpl<std::string> *filesMade = 0);
-
- virtual ~HTMLDiagnostics();
-
- virtual void SetPreprocessor(Preprocessor *pp) { PP = pp; }
+ HTMLDiagnostics(const std::string& prefix, const Preprocessor &pp);
+
+ virtual ~HTMLDiagnostics() { FlushDiagnostics(NULL); }
+
+ virtual void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade);
virtual void HandlePathDiagnostic(const PathDiagnostic* D);
+
+ virtual llvm::StringRef getName() const {
+ return "HTMLDiagnostics";
+ }
unsigned ProcessMacroPiece(llvm::raw_ostream& os,
const PathDiagnosticMacroPiece& P,
@@ -61,59 +63,24 @@ public:
const char *HighlightStart = "<span class=\"mrange\">",
const char *HighlightEnd = "</span>");
- void ReportDiag(const PathDiagnostic& D);
+ void ReportDiag(const PathDiagnostic& D,
+ llvm::SmallVectorImpl<std::string> *FilesMade);
};
} // end anonymous namespace
-HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix, Preprocessor* pp,
- llvm::SmallVectorImpl<std::string>* filesMade)
+HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix,
+ const Preprocessor &pp)
: Directory(prefix), FilePrefix(prefix), createdDir(false), noDir(false),
- PP(pp), FilesMade(filesMade) {
-
+ PP(pp) {
// All html files begin with "report"
FilePrefix.appendComponent("report");
}
PathDiagnosticClient*
-clang::CreateHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP,
- PreprocessorFactory*,
- llvm::SmallVectorImpl<std::string>* FilesMade)
-{
- return new HTMLDiagnostics(prefix, PP, FilesMade);
-}
-
-//===----------------------------------------------------------------------===//
-// Factory for HTMLDiagnosticClients
-//===----------------------------------------------------------------------===//
-
-namespace {
-class VISIBILITY_HIDDEN HTMLDiagnosticsFactory
- : public PathDiagnosticClientFactory {
-
- std::string Prefix;
- Preprocessor *PP;
-public:
- HTMLDiagnosticsFactory(const std::string& prefix, Preprocessor* pp)
- : Prefix(prefix), PP(pp) {}
-
- virtual ~HTMLDiagnosticsFactory() {}
-
- const char *getName() const { return "HTMLDiagnostics"; }
-
- PathDiagnosticClient*
- createPathDiagnosticClient(llvm::SmallVectorImpl<std::string> *FilesMade) {
-
- return new HTMLDiagnostics(Prefix, PP, FilesMade);
- }
-};
-} // end anonymous namespace
-
-PathDiagnosticClientFactory*
-clang::CreateHTMLDiagnosticClientFactory(const std::string& prefix,
- Preprocessor* PP,
- PreprocessorFactory*) {
- return new HTMLDiagnosticsFactory(prefix, PP);
+clang::CreateHTMLDiagnosticClient(const std::string& prefix,
+ const Preprocessor &PP) {
+ return new HTMLDiagnostics(prefix, PP);
}
//===----------------------------------------------------------------------===//
@@ -133,16 +100,19 @@ void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
BatchedDiags.push_back(D);
}
-HTMLDiagnostics::~HTMLDiagnostics() {
+void
+HTMLDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade)
+{
while (!BatchedDiags.empty()) {
const PathDiagnostic* D = BatchedDiags.back();
BatchedDiags.pop_back();
- ReportDiag(*D);
+ ReportDiag(*D, FilesMade);
delete D;
}
}
-void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) {
+void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
+ llvm::SmallVectorImpl<std::string> *FilesMade){
// Create the HTML directory if it is missing.
if (!createdDir) {
createdDir = true;
@@ -195,7 +165,7 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) {
return; // FIXME: Emit a warning?
// Create a new rewriter to generate HTML.
- Rewriter R(const_cast<SourceManager&>(SMgr), PP->getLangOptions());
+ Rewriter R(const_cast<SourceManager&>(SMgr), PP.getLangOptions());
// Process the path.
unsigned n = D.size();
@@ -215,14 +185,8 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) {
// We might not have a preprocessor if we come from a deserialized AST file,
// for example.
- if (PP) html::SyntaxHighlight(R, FID, *PP);
-
- // FIXME: We eventually want to use PPF to create a fresh Preprocessor,
- // once we have worked out the bugs.
- //
- // if (PPF) html::HighlightMacros(R, FID, *PPF);
- //
- if (PP) html::HighlightMacros(R, FID, *PP);
+ html::SyntaxHighlight(R, FID, PP);
+ html::HighlightMacros(R, FID, PP);
// Get the full directory name of the analyzed file.
@@ -476,7 +440,7 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
assert(L.isFileID());
std::pair<const char*, const char*> BufferInfo = L.getBufferData();
const char* MacroName = L.getDecomposedLoc().second + BufferInfo.first;
- Lexer rawLexer(L, PP->getLangOptions(), BufferInfo.first,
+ Lexer rawLexer(L, PP.getLangOptions(), BufferInfo.first,
MacroName, BufferInfo.second);
Token TheTok;
diff --git a/lib/Frontend/HTMLPrint.cpp b/lib/Frontend/HTMLPrint.cpp
index 8d93d70e83f4..75e6184572e5 100644
--- a/lib/Frontend/HTMLPrint.cpp
+++ b/lib/Frontend/HTMLPrint.cpp
@@ -13,13 +13,14 @@
#include "clang/Frontend/ASTConsumers.h"
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
-#include "clang/Rewrite/Rewriter.h"
-#include "clang/Rewrite/HTMLRewrite.h"
#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
-#include "clang/AST/ASTContext.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Rewrite/HTMLRewrite.h"
+#include "clang/Rewrite/Rewriter.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -32,13 +33,14 @@ namespace {
class HTMLPrinter : public ASTConsumer {
Rewriter R;
llvm::raw_ostream *Out;
- Diagnostic &Diags;
- Preprocessor *PP;
- PreprocessorFactory *PPF;
+ Preprocessor &PP;
+ bool SyntaxHighlight, HighlightMacros;
+
public:
- HTMLPrinter(llvm::raw_ostream *OS, Diagnostic &D, Preprocessor *pp,
- PreprocessorFactory* ppf)
- : Out(OS), Diags(D), PP(pp), PPF(ppf) {}
+ HTMLPrinter(llvm::raw_ostream *OS, Preprocessor &pp,
+ bool _SyntaxHighlight, bool _HighlightMacros)
+ : Out(OS), PP(pp), SyntaxHighlight(_SyntaxHighlight),
+ HighlightMacros(_HighlightMacros) {}
virtual ~HTMLPrinter();
void Initialize(ASTContext &context);
@@ -46,10 +48,10 @@ namespace {
}
ASTConsumer* clang::CreateHTMLPrinter(llvm::raw_ostream *OS,
- Diagnostic &D, Preprocessor *PP,
- PreprocessorFactory* PPF) {
-
- return new HTMLPrinter(OS, D, PP, PPF);
+ Preprocessor &PP,
+ bool SyntaxHighlight,
+ bool HighlightMacros) {
+ return new HTMLPrinter(OS, PP, SyntaxHighlight, HighlightMacros);
}
void HTMLPrinter::Initialize(ASTContext &context) {
@@ -57,7 +59,7 @@ void HTMLPrinter::Initialize(ASTContext &context) {
}
HTMLPrinter::~HTMLPrinter() {
- if (Diags.hasErrorOccurred())
+ if (PP.getDiagnostics().hasErrorOccurred())
return;
// Format the file.
@@ -79,8 +81,8 @@ HTMLPrinter::~HTMLPrinter() {
// We might not have a preprocessor if we come from a deserialized AST file,
// for example.
- if (PP) html::SyntaxHighlight(R, FID, *PP);
- if (PPF) html::HighlightMacros(R, FID, *PP);
+ if (SyntaxHighlight) html::SyntaxHighlight(R, FID, PP);
+ if (HighlightMacros) html::HighlightMacros(R, FID, PP);
html::EscapeText(R, FID, false, true);
// Emit the HTML.
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index ec5c1061bb93..7139e55f0b60 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -442,9 +442,8 @@ 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 clang::InitializePreprocessor(Preprocessor &PP,
- const PreprocessorInitOptions &InitOpts,
- bool undef_macros) {
+void clang::InitializePreprocessor(Preprocessor &PP,
+ const PreprocessorInitOptions &InitOpts) {
std::vector<char> PredefineBuffer;
const char *LineDirective = "# 1 \"<built-in>\" 3\n";
@@ -452,7 +451,7 @@ bool clang::InitializePreprocessor(Preprocessor &PP,
LineDirective, LineDirective+strlen(LineDirective));
// Install things like __POWERPC__, __GNUC__, etc into the macro table.
- if (!undef_macros)
+ if (InitOpts.getUsePredefines())
InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(),
PredefineBuffer);
@@ -489,7 +488,4 @@ bool clang::InitializePreprocessor(Preprocessor &PP,
// Null terminate PredefinedBuffer and add it.
PredefineBuffer.push_back(0);
PP.setPredefines(&PredefineBuffer[0]);
-
- // Once we've read this, we're done.
- return false;
}
diff --git a/lib/Frontend/PlistDiagnostics.cpp b/lib/Frontend/PlistDiagnostics.cpp
index a83dca0a5ffa..1be9ea8b8c41 100644
--- a/lib/Frontend/PlistDiagnostics.cpp
+++ b/lib/Frontend/PlistDiagnostics.cpp
@@ -29,7 +29,6 @@ typedef llvm::DenseMap<FileID, unsigned> FIDMap;
namespace clang {
class Preprocessor;
- class PreprocessorFactory;
}
namespace {
@@ -37,14 +36,20 @@ namespace {
std::vector<const PathDiagnostic*> BatchedDiags;
const std::string OutputFile;
const LangOptions &LangOpts;
- llvm::OwningPtr<PathDiagnosticClientFactory> PF;
- llvm::OwningPtr<PathDiagnosticClient> SubPDC;
- llvm::SmallVector<std::string, 1> FilesMade;
+ llvm::OwningPtr<PathDiagnosticClient> SubPD;
public:
PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts,
- PathDiagnosticClientFactory *pf);
- ~PlistDiagnostics();
+ PathDiagnosticClient *subPD);
+
+ ~PlistDiagnostics() { FlushDiagnostics(NULL); }
+
+ void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade);
+
void HandlePathDiagnostic(const PathDiagnostic* D);
+
+ virtual llvm::StringRef getName() const {
+ return "PlistDiagnostics";
+ }
PathGenerationScheme getGenerationScheme() const;
bool supportsLogicalOpControlFlow() const { return true; }
@@ -55,23 +60,18 @@ namespace {
PlistDiagnostics::PlistDiagnostics(const std::string& output,
const LangOptions &LO,
- PathDiagnosticClientFactory *pf)
- : OutputFile(output), LangOpts(LO), PF(pf) {
-
- if (PF)
- SubPDC.reset(PF->createPathDiagnosticClient(&FilesMade));
-}
+ PathDiagnosticClient *subPD)
+ : OutputFile(output), LangOpts(LO), SubPD(subPD) {}
PathDiagnosticClient*
-clang::CreatePlistDiagnosticClient(const std::string& s,
- Preprocessor *PP, PreprocessorFactory*,
- PathDiagnosticClientFactory *PF) {
- return new PlistDiagnostics(s, PP->getLangOptions(), PF);
+clang::CreatePlistDiagnosticClient(const std::string& s, const Preprocessor &PP,
+ PathDiagnosticClient *subPD) {
+ return new PlistDiagnostics(s, PP.getLangOptions(), subPD);
}
PathDiagnosticClient::PathGenerationScheme
PlistDiagnostics::getGenerationScheme() const {
- if (const PathDiagnosticClient *PD = SubPDC.get())
+ if (const PathDiagnosticClient *PD = SubPD.get())
return PD->getGenerationScheme();
return Extensive;
@@ -308,7 +308,8 @@ void PlistDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
BatchedDiags.push_back(D);
}
-PlistDiagnostics::~PlistDiagnostics() {
+void PlistDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string>
+ *FilesMade) {
// Build up a set of FIDs that we use by scanning the locations and
// ranges of the diagnostics.
@@ -397,19 +398,16 @@ PlistDiagnostics::~PlistDiagnostics() {
EmitLocation(o, *SM, LangOpts, D->getLocation(), FM, 2);
// Output the diagnostic to the sub-diagnostic client, if any.
- if (PF) {
- if (!SubPDC.get())
- SubPDC.reset(PF->createPathDiagnosticClient(&FilesMade));
-
- FilesMade.clear();
- SubPDC->HandlePathDiagnostic(OwnedD.take());
- SubPDC.reset(0);
+ if (SubPD) {
+ SubPD->HandlePathDiagnostic(OwnedD.take());
+ llvm::SmallVector<std::string, 1> SubFilesMade;
+ SubPD->FlushDiagnostics(SubFilesMade);
- if (!FilesMade.empty()) {
- o << " <key>" << PF->getName() << "_files</key>\n";
+ if (!SubFilesMade.empty()) {
+ o << " <key>" << SubPD->getName() << "_files</key>\n";
o << " <array>\n";
- for (size_t i = 0, n = FilesMade.size(); i < n ; ++i)
- o << " <string>" << FilesMade[i] << "</string>\n";
+ for (size_t i = 0, n = SubFilesMade.size(); i < n ; ++i)
+ o << " <string>" << SubFilesMade[i] << "</string>\n";
o << " </array>\n";
}
}
@@ -422,4 +420,7 @@ PlistDiagnostics::~PlistDiagnostics() {
// Finish.
o << "</dict>\n</plist>";
+
+ if (FilesMade)
+ FilesMade->push_back(OutputFile);
}
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index b1d8800369e5..4f8c804844b0 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -268,6 +268,7 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
const CodeModificationHint *Hints,
unsigned NumHints,
unsigned Columns) {
+ assert(LangOpts && "Unexpected diagnostic outside source file processing");
assert(!Loc.isInvalid() && "must have a valid source location here");
// If this is a macro ID, first emit information about where this was
diff --git a/lib/Headers/stdint.h b/lib/Headers/stdint.h
index f79a0f4af557..f03c1777ab01 100644
--- a/lib/Headers/stdint.h
+++ b/lib/Headers/stdint.h
@@ -42,28 +42,23 @@
* Since we only support pow-2 targets, these map directly to exact width types.
*/
-#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
-#define __int8_t_defined
-typedef signed __INT8_TYPE__ int8_t;
-typedef __INT16_TYPE__ int16_t;
-typedef __INT32_TYPE__ int32_t;
+/* Some 16-bit targets do not have a 64-bit datatype. Only define the 64-bit
+ * typedefs if there is something to typedef them to.
+ */
#ifdef __INT64_TYPE__
+#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
typedef __INT64_TYPE__ int64_t;
#endif
+typedef unsigned __INT64_TYPE__ uint64_t;
+typedef int64_t int_least64_t;
+typedef uint64_t uint_least64_t;
+typedef int64_t int_fast64_t;
+typedef uint64_t uint_fast64_t;
#endif
-typedef unsigned __INT8_TYPE__ uint8_t;
-typedef int8_t int_least8_t;
-typedef uint8_t uint_least8_t;
-typedef int8_t int_fast8_t;
-typedef uint8_t uint_fast8_t;
-
-typedef unsigned __INT16_TYPE__ uint16_t;
-typedef int16_t int_least16_t;
-typedef uint16_t uint_least16_t;
-typedef int16_t int_fast16_t;
-typedef uint16_t uint_fast16_t;
-
+#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
+typedef __INT32_TYPE__ int32_t;
+#endif
#ifndef __uint32_t_defined /* more glibc compatibility */
#define __uint32_t_defined
typedef unsigned __INT32_TYPE__ uint32_t;
@@ -73,18 +68,31 @@ typedef uint32_t uint_least32_t;
typedef int32_t int_fast32_t;
typedef uint32_t uint_fast32_t;
-/* Some 16-bit targets do not have a 64-bit datatype. Only define the 64-bit
- * typedefs if there is something to typedef them to.
- */
-#ifdef __INT64_TYPE__
-typedef unsigned __INT64_TYPE__ uint64_t;
-typedef int64_t int_least64_t;
-typedef uint64_t uint_least64_t;
-typedef int64_t int_fast64_t;
-typedef uint64_t uint_fast64_t;
+
+#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
+typedef __INT16_TYPE__ int16_t;
#endif
+typedef unsigned __INT16_TYPE__ uint16_t;
+typedef int16_t int_least16_t;
+typedef uint16_t uint_least16_t;
+typedef int16_t int_fast16_t;
+typedef uint16_t uint_fast16_t;
+#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
+typedef signed __INT8_TYPE__ int8_t;
+#endif
+typedef unsigned __INT8_TYPE__ uint8_t;
+typedef int8_t int_least8_t;
+typedef uint8_t uint_least8_t;
+typedef int8_t int_fast8_t;
+typedef uint8_t uint_fast8_t;
+
+/* prevent glibc sys/types.h from defining conflicting types */
+#ifndef __int8_t_defined
+# define __int8_t_defined
+#endif /* __int8_t_defined */
+
/* C99 7.18.1.4 Integer types capable of holding object pointers.
*/
#ifndef __intptr_t_defined
@@ -98,6 +106,25 @@ typedef unsigned __INTPTR_TYPE__ uintptr_t;
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;
+/* C99 7.18.4 Macros for minimum-width integer constants.
+ *
+ * Note that C++ should not check __STDC_CONSTANT_MACROS here, contrary to the
+ * claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]).
+ */
+
+/* Only define the 64-bit size macros if we have 64-bit support. */
+#ifdef __INT64_TYPE__
+#define INT64_C(v) (v##LL)
+#define UINT64_C(v) (v##ULL)
+#endif
+
+#define INT32_C(v) (v)
+#define UINT32_C(v) (v##U)
+#define INT16_C(v) (v)
+#define UINT16_C(v) (v##U)
+#define INT8_C(v) (v)
+#define UINT8_C(v) (v##U)
+
/* C99 7.18.2.1 Limits of exact-width integer types.
* Fixed sized values have fixed size max/min.
* C99 7.18.2.2 Limits of minimum-width integer types.
@@ -108,36 +135,6 @@ typedef __UINTMAX_TYPE__ uintmax_t;
* claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]).
*/
-#define INT8_MAX 127
-#define INT8_MIN (-128)
-#define UINT8_MAX 255
-#define INT_LEAST8_MIN INT8_MIN
-#define INT_LEAST8_MAX INT8_MAX
-#define UINT_LEAST8_MAX UINT8_MAX
-#define INT_FAST8_MIN INT8_MIN
-#define INT_FAST8_MAX INT8_MAX
-#define UINT_FAST8_MAX UINT8_MAX
-
-#define INT16_MAX 32767
-#define INT16_MIN (-32768)
-#define UINT16_MAX 65535
-#define INT_LEAST16_MIN INT16_MIN
-#define INT_LEAST16_MAX INT16_MAX
-#define UINT_LEAST16_MAX UINT16_MAX
-#define INT_FAST16_MIN INT16_MIN
-#define INT_FAST16_MAX INT16_MAX
-#define UINT_FAST16_MAX UINT16_MAX
-
-#define INT32_MAX 2147483647
-#define INT32_MIN (-2147483647-1)
-#define UINT32_MAX 4294967295U
-#define INT_LEAST32_MIN INT32_MIN
-#define INT_LEAST32_MAX INT32_MAX
-#define UINT_LEAST32_MAX UINT32_MAX
-#define INT_FAST32_MIN INT32_MIN
-#define INT_FAST32_MAX INT32_MAX
-#define UINT_FAST32_MAX UINT32_MAX
-
/* If we do not have 64-bit support, don't define the 64-bit size macros. */
#ifdef __INT64_TYPE__
#define INT64_MAX 9223372036854775807LL
@@ -151,6 +148,36 @@ typedef __UINTMAX_TYPE__ uintmax_t;
#define UINT_FAST64_MAX UINT64_MAX
#endif
+#define INT32_MAX 2147483647
+#define INT32_MIN (-2147483647-1)
+#define UINT32_MAX 4294967295U
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST32_MAX INT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define INT16_MAX 32767
+#define INT16_MIN (-32768)
+#define UINT16_MAX 65535
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define INT_FAST16_MIN INT16_MIN
+#define INT_FAST16_MAX INT16_MAX
+#define UINT_FAST16_MAX UINT16_MAX
+
+#define INT8_MAX 127
+#define INT8_MIN (-128)
+#define UINT8_MAX 255
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define UINT_LEAST8_MAX UINT8_MAX
+#define INT_FAST8_MIN INT8_MIN
+#define INT_FAST8_MAX INT8_MAX
+#define UINT_FAST8_MAX UINT8_MAX
+
/* C99 7.18.2.4 Limits of integer types capable of holding object pointers. */
/* C99 7.18.3 Limits of other integer types. */
@@ -206,25 +233,6 @@ typedef __UINTMAX_TYPE__ uintmax_t;
#define WCHAR_MIN (-__WCHAR_MAX__-1)
#endif
-/* C99 7.18.4 Macros for minimum-width integer constants.
- *
- * Note that C++ should not check __STDC_CONSTANT_MACROS here, contrary to the
- * claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]).
- */
-
-#define INT8_C(v) (v)
-#define UINT8_C(v) (v##U)
-#define INT16_C(v) (v)
-#define UINT16_C(v) (v##U)
-#define INT32_C(v) (v)
-#define UINT32_C(v) (v##U)
-
-/* Only define the 64-bit size macros if we have 64-bit support. */
-#ifdef __INT64_TYPE__
-#define INT64_C(v) (v##LL)
-#define UINT64_C(v) (v##ULL)
-#endif
-
/* 7.18.4.2 Macros for greatest-width integer constants. */
#define INTMAX_C(v) (v##LL)
#define UINTMAX_C(v) (v##ULL)
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 7f3afc60764c..487b9d63c169 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -43,8 +43,6 @@ using namespace clang;
//===----------------------------------------------------------------------===//
-PreprocessorFactory::~PreprocessorFactory() {}
-
Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
TargetInfo &target, SourceManager &SM,
HeaderSearch &Headers,
@@ -403,7 +401,7 @@ void Preprocessor::EnterMainSourceFile() {
/// LookUpIdentifierInfo - Given a tok::identifier token, look up the
/// identifier information for the token and install it into the token.
IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier,
- const char *BufPtr) {
+ const char *BufPtr) const {
assert(Identifier.is(tok::identifier) && "Not an identifier!");
assert(Identifier.getIdentifierInfo() == 0 && "Identinfo already exists!");
@@ -411,14 +409,14 @@ IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier,
IdentifierInfo *II;
if (BufPtr && !Identifier.needsCleaning()) {
// No cleaning needed, just use the characters from the lexed buffer.
- II = getIdentifierInfo(BufPtr, BufPtr+Identifier.getLength());
+ II = getIdentifierInfo(llvm::StringRef(BufPtr, Identifier.getLength()));
} else {
// Cleaning needed, alloca a buffer, clean into it, then use the buffer.
llvm::SmallVector<char, 64> IdentifierBuffer;
IdentifierBuffer.resize(Identifier.getLength());
const char *TmpBuf = &IdentifierBuffer[0];
unsigned Size = getSpelling(Identifier, TmpBuf);
- II = getIdentifierInfo(TmpBuf, TmpBuf+Size);
+ II = getIdentifierInfo(llvm::StringRef(TmpBuf, Size));
}
Identifier.setIdentifierInfo(II);
return II;
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 3436900027e4..0a4e036e4399 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -334,6 +334,14 @@ bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
return false;
}
+bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
+ // 'constexpr constexpr' is ok.
+ Constexpr_specified = true;
+ ConstexprLoc = Loc;
+ return false;
+}
+
void DeclSpec::setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos,
unsigned NP,
SourceLocation *ProtoLocs,
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index 1e7d397fdf37..bf05b2baccd4 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -42,14 +42,12 @@ Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope,
return DeclPtrTy();
}
-// Defined out-of-line here because of dependecy on AttributeList
+// Defined out-of-line here because of dependency on AttributeList
Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
AccessSpecifier AS,
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *TargetName,
- OverloadedOperatorKind Op,
+ UnqualifiedId &Name,
AttributeList *AttrList,
bool IsTypeName) {
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index e905553fd818..99752b59507f 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -769,6 +769,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
/// [C++] 'virtual'
/// [C++] 'explicit'
/// 'friend': [C++ dcl.friend]
+/// 'constexpr': [C++0x dcl.constexpr]
///
void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
@@ -1070,6 +1071,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
}
break;
+ // constexpr
+ case tok::kw_constexpr:
+ isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID);
+ break;
+
// type-specifier
case tok::kw_short:
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec,
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 91f86864f81f..154c2923486e 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -285,6 +285,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
bool IsTypeName;
// Ignore optional 'typename'.
+ // FIXME: This is wrong; we should parse this as a typename-specifier.
if (Tok.is(tok::kw_typename)) {
ConsumeToken();
IsTypeName = true;
@@ -302,41 +303,21 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
SkipUntil(tok::semi);
return DeclPtrTy();
}
- if (Tok.is(tok::annot_template_id)) {
- // C++0x N2914 [namespace.udecl]p5:
- // A using-declaration shall not name a template-id.
- Diag(Tok, diag::err_using_decl_can_not_refer_to_template_spec);
- SkipUntil(tok::semi);
- return DeclPtrTy();
- }
-
- IdentifierInfo *TargetName = 0;
- OverloadedOperatorKind Op = OO_None;
- SourceLocation IdentLoc;
- if (Tok.is(tok::kw_operator)) {
- IdentLoc = Tok.getLocation();
-
- Op = TryParseOperatorFunctionId();
- if (!Op) {
- // If there was an invalid operator, skip to end of decl, and eat ';'.
- SkipUntil(tok::semi);
- return DeclPtrTy();
- }
- // FIXME: what about conversion functions?
- } else if (Tok.is(tok::identifier)) {
- // Parse identifier.
- TargetName = Tok.getIdentifierInfo();
- IdentLoc = ConsumeToken();
- } else {
- // FIXME: Use a better diagnostic here.
- Diag(Tok, diag::err_expected_ident_in_using);
-
- // If there was invalid identifier, skip to end of decl, and eat ';'.
+ // Parse the unqualified-id. We allow parsing of both constructor and
+ // destructor names and allow the action module to diagnose any semantic
+ // errors.
+ UnqualifiedId Name;
+ if (ParseUnqualifiedId(SS,
+ /*EnteringContext=*/false,
+ /*AllowDestructorName=*/true,
+ /*AllowConstructorName=*/true,
+ /*ObjectType=*/0,
+ Name)) {
SkipUntil(tok::semi);
return DeclPtrTy();
}
-
+
// Parse (optional) attributes (most likely GNU strong-using extension).
if (Tok.is(tok::kw___attribute))
AttrList = ParseAttributes();
@@ -344,10 +325,10 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
// Eat ';'.
DeclEnd = Tok.getLocation();
ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- AttrList ? "attributes list" : "namespace name", tok::semi);
+ AttrList ? "attributes list" : "using declaration",
+ tok::semi);
- return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS,
- IdentLoc, TargetName, Op,
+ return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, Name,
AttrList, IsTypeName);
}
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index a7ca0c54dbe6..a00dfb0b4c36 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1196,141 +1196,6 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
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
-/// operator. Otherwise, returns NULL and does not consume any tokens.
-///
-/// operator-function-id: [C++ 13.5]
-/// 'operator' operator
-///
-/// operator: one of
-/// new delete new[] delete[]
-/// + - * / % ^ & | ~
-/// ! = < > += -= *= /= %=
-/// ^= &= |= << >> >>= <<= == !=
-/// <= >= && || ++ -- , ->* ->
-/// () []
-OverloadedOperatorKind
-Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) {
- assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
- SourceLocation Loc;
-
- OverloadedOperatorKind Op = OO_None;
- switch (NextToken().getKind()) {
- case tok::kw_new:
- ConsumeToken(); // 'operator'
- Loc = ConsumeToken(); // 'new'
- if (Tok.is(tok::l_square)) {
- ConsumeBracket(); // '['
- Loc = Tok.getLocation();
- ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
- Op = OO_Array_New;
- } else {
- Op = OO_New;
- }
- if (EndLoc)
- *EndLoc = Loc;
- return Op;
-
- case tok::kw_delete:
- ConsumeToken(); // 'operator'
- Loc = ConsumeToken(); // 'delete'
- if (Tok.is(tok::l_square)) {
- ConsumeBracket(); // '['
- Loc = Tok.getLocation();
- ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
- Op = OO_Array_Delete;
- } else {
- Op = OO_Delete;
- }
- if (EndLoc)
- *EndLoc = Loc;
- return Op;
-
-#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
- case tok::Token: Op = OO_##Name; break;
-#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
-#include "clang/Basic/OperatorKinds.def"
-
- case tok::l_paren:
- ConsumeToken(); // 'operator'
- ConsumeParen(); // '('
- Loc = Tok.getLocation();
- ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
- if (EndLoc)
- *EndLoc = Loc;
- return OO_Call;
-
- case tok::l_square:
- ConsumeToken(); // 'operator'
- ConsumeBracket(); // '['
- Loc = Tok.getLocation();
- ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
- if (EndLoc)
- *EndLoc = Loc;
- return OO_Subscript;
-
- case tok::code_completion: {
- // Code completion for the operator name.
- Actions.CodeCompleteOperatorName(CurScope);
-
- // Consume the 'operator' token, then replace the code-completion token
- // with an 'operator' token and try again.
- SourceLocation OperatorLoc = ConsumeToken();
- Tok.setLocation(OperatorLoc);
- Tok.setKind(tok::kw_operator);
- return TryParseOperatorFunctionId(EndLoc);
- }
-
- default:
- return OO_None;
- }
-
- ConsumeToken(); // 'operator'
- Loc = ConsumeAnyToken(); // the operator itself
- if (EndLoc)
- *EndLoc = Loc;
- return Op;
-}
-
-/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
-/// which expresses the name of a user-defined conversion operator
-/// (C++ [class.conv.fct]p1). Returns the type that this operator is
-/// specifying a conversion for, or NULL if there was an error.
-///
-/// 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]
-Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) {
- assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
- ConsumeToken(); // 'operator'
-
- // Parse the type-specifier-seq.
- DeclSpec DS;
- if (ParseCXXTypeSpecifierSeq(DS))
- return 0;
-
- // Parse the conversion-declarator, which is merely a sequence of
- // ptr-operators.
- Declarator D(DS, Declarator::TypeNameContext);
- ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
- if (EndLoc)
- *EndLoc = D.getSourceRange().getEnd();
-
- // Finish up the type.
- Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
- if (Result.isInvalid())
- return 0;
- else
- return Result.get();
-}
-
/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
/// memory in a typesafe manner and call constructors.
///
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 045acd86ad0f..99578837c21c 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -809,12 +809,11 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
Tok.setAnnotationValue(Type.isInvalid()? 0 : Type.get());
if (SS && SS->isNotEmpty()) // it was a C++ qualified type name.
Tok.setLocation(SS->getBeginLoc());
+ Tok.setAnnotationEndLoc(TemplateId->TemplateNameLoc);
- // We might be backtracking, in which case we need to replace the
- // template-id annotation token with the type annotation within the
- // set of cached tokens. That way, we won't try to form the same
- // class template specialization again.
- PP.ReplaceLastTokenWithAnnotation(Tok);
+ // Replace the template-id annotation token, and possible the scope-specifier
+ // that precedes it, with the typename annotation token.
+ PP.AnnotateCachedTokens(Tok);
TemplateId->Destroy();
}
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index eb6e93540566..7ac297710965 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -503,6 +503,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
/// function-specifier
/// 'friend'
/// 'typedef'
+/// [C++0x] 'constexpr'
/// [GNU] attributes declaration-specifiers[opt]
///
/// storage-class-specifier:
@@ -615,9 +616,11 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
// function-specifier
// 'friend'
// 'typedef'
+ // 'constexpr'
case tok::kw_friend:
case tok::kw_typedef:
+ case tok::kw_constexpr:
// storage-class-specifier
case tok::kw_register:
case tok::kw_static:
diff --git a/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp
index 7326890ded76..b4bf419bc5f4 100644
--- a/lib/Rewrite/HTMLRewrite.cpp
+++ b/lib/Rewrite/HTMLRewrite.cpp
@@ -349,7 +349,7 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
/// information about keywords, macro expansions etc. This uses the macro
/// table state from the end of the file, so it won't be perfectly perfect,
/// but it will be reasonably close.
-void html::SyntaxHighlight(Rewriter &R, FileID FID, Preprocessor &PP) {
+void html::SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP) {
RewriteBuffer &RB = R.getEditBuffer(FID);
const SourceManager &SM = PP.getSourceManager();
@@ -375,7 +375,8 @@ void html::SyntaxHighlight(Rewriter &R, FileID FID, Preprocessor &PP) {
case tok::identifier: {
// Fill in Result.IdentifierInfo, looking up the identifier in the
// identifier table.
- IdentifierInfo *II = PP.LookUpIdentifierInfo(Tok, BufferStart+TokOffs);
+ const IdentifierInfo *II =
+ PP.LookUpIdentifierInfo(Tok, BufferStart+TokOffs);
// If this is a pp-identifier, for a keyword, highlight it as such.
if (II->getTokenID() != tok::identifier)
@@ -438,7 +439,7 @@ class IgnoringDiagClient : public DiagnosticClient {
/// file, to re-expand macros and insert (into the HTML) information about the
/// macro expansions. This won't be perfectly perfect, but it will be
/// reasonably close.
-void html::HighlightMacros(Rewriter &R, FileID FID, Preprocessor& PP) {
+void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) {
// Re-lex the raw token stream into a token buffer.
const SourceManager &SM = PP.getSourceManager();
std::vector<Token> TokenStream;
@@ -481,25 +482,29 @@ void html::HighlightMacros(Rewriter &R, FileID FID, Preprocessor& PP) {
IgnoringDiagClient TmpDC;
Diagnostic TmpDiags(&TmpDC);
- Diagnostic *OldDiags = &PP.getDiagnostics();
- PP.setDiagnostics(TmpDiags);
+ // FIXME: This is a huge hack; we reuse the input preprocessor because we want
+ // its state, but we aren't actually changing it (we hope). This should really
+ // construct a copy of the preprocessor.
+ Preprocessor &TmpPP = const_cast<Preprocessor&>(PP);
+ Diagnostic *OldDiags = &TmpPP.getDiagnostics();
+ TmpPP.setDiagnostics(TmpDiags);
// Inform the preprocessor that we don't want comments.
- PP.SetCommentRetentionState(false, false);
+ TmpPP.SetCommentRetentionState(false, false);
// Enter the tokens we just lexed. This will cause them to be macro expanded
// but won't enter sub-files (because we removed #'s).
- PP.EnterTokenStream(&TokenStream[0], TokenStream.size(), false, false);
+ TmpPP.EnterTokenStream(&TokenStream[0], TokenStream.size(), false, false);
- TokenConcatenation ConcatInfo(PP);
+ TokenConcatenation ConcatInfo(TmpPP);
// Lex all the tokens.
Token Tok;
- PP.Lex(Tok);
+ TmpPP.Lex(Tok);
while (Tok.isNot(tok::eof)) {
// Ignore non-macro tokens.
if (!Tok.getLocation().isMacroID()) {
- PP.Lex(Tok);
+ TmpPP.Lex(Tok);
continue;
}
@@ -511,19 +516,19 @@ void html::HighlightMacros(Rewriter &R, FileID FID, Preprocessor& PP) {
// Ignore tokens whose instantiation location was not the main file.
if (SM.getFileID(LLoc.first) != FID) {
- PP.Lex(Tok);
+ TmpPP.Lex(Tok);
continue;
}
assert(SM.getFileID(LLoc.second) == FID &&
"Start and end of expansion must be in the same ultimate file!");
- std::string Expansion = EscapeText(PP.getSpelling(Tok));
+ std::string Expansion = EscapeText(TmpPP.getSpelling(Tok));
unsigned LineLen = Expansion.size();
Token PrevTok = Tok;
// Okay, eat this token, getting the next one.
- PP.Lex(Tok);
+ TmpPP.Lex(Tok);
// Skip all the rest of the tokens that are part of this macro
// instantiation. It would be really nice to pop up a window with all the
@@ -545,11 +550,11 @@ void html::HighlightMacros(Rewriter &R, FileID FID, Preprocessor& PP) {
Expansion += ' ';
// Escape any special characters in the token text.
- Expansion += EscapeText(PP.getSpelling(Tok));
+ Expansion += EscapeText(TmpPP.getSpelling(Tok));
LineLen += Expansion.size();
PrevTok = Tok;
- PP.Lex(Tok);
+ TmpPP.Lex(Tok);
}
@@ -562,12 +567,5 @@ void html::HighlightMacros(Rewriter &R, FileID FID, Preprocessor& PP) {
}
// Restore diagnostics object back to its own thing.
- PP.setDiagnostics(*OldDiags);
-}
-
-void html::HighlightMacros(Rewriter &R, FileID FID,
- PreprocessorFactory &PPF) {
-
- llvm::OwningPtr<Preprocessor> PP(PPF.CreatePreprocessor());
- HighlightMacros(R, FID, *PP);
+ TmpPP.setDiagnostics(*OldDiags);
}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 0f84b46ed405..c4de6be9eb2e 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1609,6 +1609,9 @@ public:
void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
Expr **Args, unsigned NumArgs);
+ void CheckSignCompare(Expr *LHS, Expr *RHS, SourceLocation Loc,
+ const PartialDiagnostic &PD);
+
virtual ExpressionEvaluationContext
PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext);
@@ -1667,6 +1670,8 @@ public:
OwningExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc,
unsigned OpcIn,
ExprArg InputArg);
+ OwningExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+ UnaryOperator::Opcode Opc, ExprArg input);
virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
tok::TokenKind Op, ExprArg Input);
@@ -1792,6 +1797,9 @@ public:
virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
tok::TokenKind Kind,
ExprArg LHS, ExprArg RHS);
+ OwningExprResult BuildBinOp(Scope *S, SourceLocation OpLoc,
+ BinaryOperator::Opcode Opc,
+ Expr *lhs, Expr *rhs);
OwningExprResult CreateBuiltinBinOp(SourceLocation TokLoc,
unsigned Opc, Expr *lhs, Expr *rhs);
@@ -1893,9 +1901,7 @@ public:
AccessSpecifier AS,
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *TargetName,
- OverloadedOperatorKind Op,
+ UnqualifiedId &Name,
AttributeList *AttrList,
bool IsTypeName);
@@ -3645,7 +3651,8 @@ public:
Ref_Compatible
};
- ReferenceCompareResult CompareReferenceRelationship(QualType T1, QualType T2,
+ ReferenceCompareResult CompareReferenceRelationship(SourceLocation Loc,
+ QualType T1, QualType T2,
bool& DerivedToBase);
bool CheckReferenceInit(Expr *&simpleInit_or_initList, QualType declType,
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 8bb334855d02..76faddaa0384 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -527,7 +527,8 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
// this is the only cast possibility, so we issue an error if we fail now.
// FIXME: Should allow casting away constness if CStyle.
bool DerivedToBase;
- if (Self.CompareReferenceRelationship(SrcExpr->getType(), R->getPointeeType(),
+ if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
+ SrcExpr->getType(), R->getPointeeType(),
DerivedToBase) <
Sema::Ref_Compatible_With_Added_Qualification) {
msg = diag::err_bad_lvalue_to_rvalue_cast;
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 10c138c7558f..ce3fb5f83c8f 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -22,6 +22,72 @@
#include "llvm/Support/raw_ostream.h"
using namespace clang;
+/// \brief Find the current instantiation that associated with the given type.
+static CXXRecordDecl *
+getCurrentInstantiationOf(ASTContext &Context, DeclContext *CurContext,
+ QualType T) {
+ if (T.isNull())
+ return 0;
+
+ T = Context.getCanonicalType(T);
+
+ for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getParent()) {
+ // If we've hit a namespace or the global scope, then the
+ // nested-name-specifier can't refer to the current instantiation.
+ if (Ctx->isFileContext())
+ return 0;
+
+ // Skip non-class contexts.
+ CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx);
+ if (!Record)
+ continue;
+
+ // If this record type is not dependent,
+ if (!Record->isDependentType())
+ return 0;
+
+ // C++ [temp.dep.type]p1:
+ //
+ // In the definition of a class template, a nested class of a
+ // class template, a member of a class template, or a member of a
+ // nested class of a class template, a name refers to the current
+ // instantiation if it is
+ // -- the injected-class-name (9) of the class template or
+ // nested class,
+ // -- in the definition of a primary class template, the name
+ // of the class template followed by the template argument
+ // list of the primary template (as described below)
+ // enclosed in <>,
+ // -- in the definition of a nested class of a class template,
+ // the name of the nested class referenced as a member of
+ // the current instantiation, or
+ // -- in the definition of a partial specialization, the name
+ // of the class template followed by the template argument
+ // list of the partial specialization enclosed in <>. If
+ // the nth template parameter is a parameter pack, the nth
+ // template argument is a pack expansion (14.6.3) whose
+ // pattern is the name of the parameter pack.
+ // (FIXME: parameter packs)
+ //
+ // All of these options come down to having the
+ // nested-name-specifier type that is equivalent to the
+ // injected-class-name of one of the types that is currently in
+ // our context.
+ if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T)
+ return Record;
+
+ if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
+ QualType InjectedClassName
+ = Template->getInjectedClassNameType(Context);
+ if (T == Context.getCanonicalType(InjectedClassName))
+ return Template->getTemplatedDecl();
+ }
+ // FIXME: check for class template partial specializations
+ }
+
+ return 0;
+}
+
/// \brief Compute the DeclContext that is associated with the given type.
///
/// \param T the type for which we are attempting to find a DeclContext.
@@ -33,7 +99,7 @@ DeclContext *Sema::computeDeclContext(QualType T) {
if (const TagType *Tag = T->getAs<TagType>())
return Tag->getDecl();
- return 0;
+ return ::getCurrentInstantiationOf(Context, CurContext, T);
}
/// \brief Compute the DeclContext that is associated with the given
@@ -156,68 +222,7 @@ CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) {
return 0;
QualType T = QualType(NNS->getAsType(), 0);
- // If the nested name specifier does not refer to a type, then it
- // does not refer to the current instantiation.
- if (T.isNull())
- return 0;
-
- T = Context.getCanonicalType(T);
-
- for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getParent()) {
- // If we've hit a namespace or the global scope, then the
- // nested-name-specifier can't refer to the current instantiation.
- if (Ctx->isFileContext())
- return 0;
-
- // Skip non-class contexts.
- CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx);
- if (!Record)
- continue;
-
- // If this record type is not dependent,
- if (!Record->isDependentType())
- return 0;
-
- // C++ [temp.dep.type]p1:
- //
- // In the definition of a class template, a nested class of a
- // class template, a member of a class template, or a member of a
- // nested class of a class template, a name refers to the current
- // instantiation if it is
- // -- the injected-class-name (9) of the class template or
- // nested class,
- // -- in the definition of a primary class template, the name
- // of the class template followed by the template argument
- // list of the primary template (as described below)
- // enclosed in <>,
- // -- in the definition of a nested class of a class template,
- // the name of the nested class referenced as a member of
- // the current instantiation, or
- // -- in the definition of a partial specialization, the name
- // of the class template followed by the template argument
- // list of the partial specialization enclosed in <>. If
- // the nth template parameter is a parameter pack, the nth
- // template argument is a pack expansion (14.6.3) whose
- // pattern is the name of the parameter pack.
- // (FIXME: parameter packs)
- //
- // All of these options come down to having the
- // nested-name-specifier type that is equivalent to the
- // injected-class-name of one of the types that is currently in
- // our context.
- if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T)
- return Record;
-
- if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
- QualType InjectedClassName
- = Template->getInjectedClassNameType(Context);
- if (T == Context.getCanonicalType(InjectedClassName))
- return Template->getTemplatedDecl();
- }
- // FIXME: check for class template partial specializations
- }
-
- return 0;
+ return ::getCurrentInstantiationOf(Context, CurContext, T);
}
/// \brief Require that the context specified by SS be complete.
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index bc255137fccf..b8977cfa142d 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -971,10 +971,70 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
RParenLoc, ClassDecl);
}
+/// Checks an initializer expression for use of uninitialized fields, such as
+/// containing the field that is being initialized. Returns true if there is an
+/// uninitialized field was used an updates the SourceLocation parameter; false
+/// otherwise.
+static bool InitExprContainsUninitializedFields(const Stmt* S,
+ const FieldDecl* LhsField,
+ SourceLocation* L) {
+ const MemberExpr* ME = dyn_cast<MemberExpr>(S);
+ if (ME) {
+ const NamedDecl* RhsField = ME->getMemberDecl();
+ if (RhsField == LhsField) {
+ // Initializing a field with itself. Throw a warning.
+ // But wait; there are exceptions!
+ // Exception #1: The field may not belong to this record.
+ // e.g. Foo(const Foo& rhs) : A(rhs.A) {}
+ const Expr* base = ME->getBase();
+ if (base != NULL && !isa<CXXThisExpr>(base->IgnoreParenCasts())) {
+ // Even though the field matches, it does not belong to this record.
+ return false;
+ }
+ // None of the exceptions triggered; return true to indicate an
+ // uninitialized field was used.
+ *L = ME->getMemberLoc();
+ return true;
+ }
+ }
+ bool found = false;
+ for (Stmt::const_child_iterator it = S->child_begin();
+ it != S->child_end() && found == false;
+ ++it) {
+ if (isa<CallExpr>(S)) {
+ // Do not descend into function calls or constructors, as the use
+ // of an uninitialized field may be valid. One would have to inspect
+ // the contents of the function/ctor to determine if it is safe or not.
+ // i.e. Pass-by-value is never safe, but pass-by-reference and pointers
+ // may be safe, depending on what the function/ctor does.
+ continue;
+ }
+ found = InitExprContainsUninitializedFields(*it, LhsField, L);
+ }
+ return found;
+}
+
Sema::MemInitResult
Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
unsigned NumArgs, SourceLocation IdLoc,
SourceLocation RParenLoc) {
+ // Diagnose value-uses of fields to initialize themselves, e.g.
+ // foo(foo)
+ // where foo is not also a parameter to the constructor.
+ // TODO: implement -Wuninitialized and fold this into that framework.
+ for (unsigned i = 0; i < NumArgs; ++i) {
+ SourceLocation L;
+ if (InitExprContainsUninitializedFields(Args[i], Member, &L)) {
+ // FIXME: Return true in the case when other fields are used before being
+ // uninitialized. For example, let this field be the i'th field. When
+ // initializing the i'th field, throw a warning if any of the >= i'th
+ // fields are used, as they are not yet initialized.
+ // Right now we are only handling the case where the i'th field uses
+ // itself in its initializer.
+ Diag(L, diag::warn_field_is_uninit);
+ }
+ }
+
bool HasDependentArg = false;
for (unsigned i = 0; i < NumArgs; i++)
HasDependentArg |= Args[i]->isTypeDependent();
@@ -985,7 +1045,9 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
FieldType = Array->getElementType();
if (FieldType->isDependentType()) {
// Can't check init for dependent type.
- } else if (FieldType->getAs<RecordType>()) {
+ } else if (FieldType->isRecordType()) {
+ // Member is a record (struct/union/class), so pass the initializer
+ // arguments down to the record's constructor.
if (!HasDependentArg) {
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
@@ -1005,6 +1067,8 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
}
}
} else if (NumArgs != 1 && NumArgs != 0) {
+ // The member type is not a record type (or an array of record
+ // types), so it can be only be default- or copy-initialized.
return Diag(IdLoc, diag::err_mem_initializer_mismatch)
<< Member->getDeclName() << SourceRange(IdLoc, RParenLoc);
} else if (!HasDependentArg) {
@@ -1158,7 +1222,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
// On seeing one dependent type, we should essentially exit this routine
// while preserving user-declared initializer list. When this routine is
// called during instantiatiation process, this routine will rebuild the
- // oderdered initializer list correctly.
+ // ordered initializer list correctly.
// If we have a dependent base initialization, we can't determine the
// association between initializers and bases; just dump the known
@@ -1293,11 +1357,16 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
continue;
}
+ if ((*Field)->getType()->isDependentType()) {
+ Fields.push_back(*Field);
+ continue;
+ }
+
QualType FT = Context.getBaseElementType((*Field)->getType());
if (const RecordType* RT = FT->getAs<RecordType>()) {
CXXConstructorDecl *Ctor =
cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context);
- if (!Ctor && !FT->isDependentType()) {
+ if (!Ctor) {
Fields.push_back(*Field);
continue;
}
@@ -1357,12 +1426,16 @@ Sema::BuildBaseOrMemberInitializers(ASTContext &C,
SetBaseOrMemberInitializers(Constructor,
Initializers, NumInitializers, Bases, Members);
- for (unsigned int i = 0; i < Bases.size(); i++)
- Diag(Bases[i]->getSourceRange().getBegin(),
- diag::err_missing_default_constructor) << 0 << Bases[i]->getType();
- for (unsigned int i = 0; i < Members.size(); i++)
- Diag(Members[i]->getLocation(), diag::err_missing_default_constructor)
- << 1 << Members[i]->getType();
+ for (unsigned int i = 0; i < Bases.size(); i++) {
+ if (!Bases[i]->getType()->isDependentType())
+ Diag(Bases[i]->getSourceRange().getBegin(),
+ diag::err_missing_default_constructor) << 0 << Bases[i]->getType();
+ }
+ for (unsigned int i = 0; i < Members.size(); i++) {
+ if (!Members[i]->getType()->isDependentType())
+ Diag(Members[i]->getLocation(), diag::err_missing_default_constructor)
+ << 1 << Members[i]->getType();
+ }
}
static void *GetKeyForTopLevelField(FieldDecl *Field) {
@@ -1405,6 +1478,7 @@ static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member,
return GetKeyForBase(QualType(Member->getBaseClass(), 0));
}
+/// ActOnMemInitializers - Handle the member initializers for a constructor.
void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SourceLocation ColonLoc,
MemInitTy **MemInits, unsigned NumMemInits) {
@@ -2700,22 +2774,37 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
AccessSpecifier AS,
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *TargetName,
- OverloadedOperatorKind Op,
+ UnqualifiedId &Name,
AttributeList *AttrList,
bool IsTypeName) {
- assert((TargetName || Op) && "Invalid TargetName.");
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
- DeclarationName Name;
- if (TargetName)
- Name = TargetName;
- else
- Name = Context.DeclarationNames.getCXXOperatorName(Op);
-
- NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, IdentLoc,
- Name, AttrList, IsTypeName);
+ switch (Name.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedId::IK_ConversionFunctionId:
+ break;
+
+ case UnqualifiedId::IK_ConstructorName:
+ Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_constructor)
+ << SS.getRange();
+ return DeclPtrTy();
+
+ case UnqualifiedId::IK_DestructorName:
+ Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_destructor)
+ << SS.getRange();
+ return DeclPtrTy();
+
+ case UnqualifiedId::IK_TemplateId:
+ Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_template_id)
+ << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
+ return DeclPtrTy();
+ }
+
+ DeclarationName TargetName = GetNameFromUnqualifiedId(Name);
+ NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS,
+ Name.getSourceRange().getBegin(),
+ TargetName, AttrList, IsTypeName);
if (UD) {
PushOnScopeChains(UD, S);
UD->setAccess(AS);
@@ -3515,14 +3604,15 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
/// type, and the first type (T1) is the pointee type of the reference
/// type being initialized.
Sema::ReferenceCompareResult
-Sema::CompareReferenceRelationship(QualType T1, QualType T2,
+Sema::CompareReferenceRelationship(SourceLocation Loc,
+ QualType OrigT1, QualType OrigT2,
bool& DerivedToBase) {
- assert(!T1->isReferenceType() &&
+ assert(!OrigT1->isReferenceType() &&
"T1 must be the pointee type of the reference type");
- assert(!T2->isReferenceType() && "T2 cannot be a reference type");
+ assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type");
- T1 = Context.getCanonicalType(T1);
- T2 = Context.getCanonicalType(T2);
+ QualType T1 = Context.getCanonicalType(OrigT1);
+ QualType T2 = Context.getCanonicalType(OrigT2);
QualType UnqualT1 = T1.getUnqualifiedType();
QualType UnqualT2 = T2.getUnqualifiedType();
@@ -3532,7 +3622,9 @@ Sema::CompareReferenceRelationship(QualType T1, QualType T2,
// T1 is a base class of T2.
if (UnqualT1 == UnqualT2)
DerivedToBase = false;
- else if (IsDerivedFrom(UnqualT2, UnqualT1))
+ else if (!RequireCompleteType(Loc, OrigT1, PDiag()) &&
+ !RequireCompleteType(Loc, OrigT2, PDiag()) &&
+ IsDerivedFrom(UnqualT2, UnqualT1))
DerivedToBase = true;
else
return Ref_Incompatible;
@@ -3608,7 +3700,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
Expr::isLvalueResult InitLvalue = ForceRValue ? Expr::LV_InvalidExpression :
Init->isLvalue(Context);
ReferenceCompareResult RefRelationship
- = CompareReferenceRelationship(T1, T2, DerivedToBase);
+ = CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase);
// Most paths end in a failed conversion.
if (ICS)
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index ac7cced2eaef..f1d6f2bb17ce 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3340,6 +3340,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (getLangOptions().CPlusPlus)
return CXXCheckConditionalOperands(Cond, LHS, RHS, QuestionLoc);
+ CheckSignCompare(LHS, RHS, QuestionLoc, diag::warn_mixed_sign_conditional);
+
UsualUnaryConversions(Cond);
UsualUnaryConversions(LHS);
UsualUnaryConversions(RHS);
@@ -4427,6 +4429,41 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
return LHSTy;
}
+/// Implements -Wsign-compare.
+void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
+ const PartialDiagnostic &PD) {
+ QualType lt = lex->getType(), rt = rex->getType();
+
+ // Only warn if both operands are integral.
+ if (!lt->isIntegerType() || !rt->isIntegerType())
+ return;
+
+ // The rule is that the signed operand becomes unsigned, so isolate the
+ // signed operand.
+ Expr *signedOperand;
+ if (lt->isSignedIntegerType()) {
+ if (rt->isSignedIntegerType()) return;
+ signedOperand = lex;
+ } else {
+ if (!rt->isSignedIntegerType()) return;
+ signedOperand = rex;
+ }
+
+ // If the value is a non-negative integer constant, then the
+ // signed->unsigned conversion won't change it.
+ llvm::APSInt value;
+ if (signedOperand->isIntegerConstantExpr(value, Context)) {
+ assert(value.isSigned() && "result of signed expression not signed");
+
+ if (value.isNonNegative())
+ return;
+ }
+
+ Diag(OpLoc, PD)
+ << lex->getType() << rex->getType()
+ << lex->getSourceRange() << rex->getSourceRange();
+}
+
// C99 6.5.8, C++ [expr.rel]
QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
unsigned OpaqueOpc, bool isRelational) {
@@ -4435,6 +4472,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
return CheckVectorCompareOperands(lex, rex, Loc, isRelational);
+ CheckSignCompare(lex, rex, Loc, diag::warn_mixed_sign_comparison);
+
// C99 6.5.8p3 / C99 6.5.9p4
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
UsualArithmeticConversions(lex, rex);
@@ -5472,6 +5511,12 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
// Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
DiagnoseBinOpPrecedence(*this, Opc, TokLoc, lhs, rhs);
+ return BuildBinOp(S, TokLoc, Opc, lhs, rhs);
+}
+
+Action::OwningExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
+ BinaryOperator::Opcode Opc,
+ Expr *lhs, Expr *rhs) {
if (getLangOptions().CPlusPlus &&
(lhs->getType()->isOverloadableType() ||
rhs->getType()->isOverloadableType())) {
@@ -5482,21 +5527,22 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
FunctionSet Functions;
OverloadedOperatorKind OverOp = BinaryOperator::getOverloadedOperator(Opc);
if (OverOp != OO_None) {
- LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
- Functions);
+ if (S)
+ LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
+ Functions);
Expr *Args[2] = { lhs, rhs };
DeclarationName OpName
= Context.DeclarationNames.getCXXOperatorName(OverOp);
ArgumentDependentLookup(OpName, /*Operator*/true, Args, 2, Functions);
}
-
+
// Build the (potentially-overloaded, potentially-dependent)
// binary operation.
- return CreateOverloadedBinOp(TokLoc, Opc, Functions, lhs, rhs);
+ return CreateOverloadedBinOp(OpLoc, Opc, Functions, lhs, rhs);
}
-
+
// Build a built-in binary operation.
- return CreateBuiltinBinOp(TokLoc, Opc, lhs, rhs);
+ return CreateBuiltinBinOp(OpLoc, Opc, lhs, rhs);
}
Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
@@ -5587,12 +5633,10 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
return Owned(new (Context) UnaryOperator(Input, Opc, resultType, OpLoc));
}
-// Unary Operators. 'Tok' is the token for the operator.
-Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Op, ExprArg input) {
+Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+ UnaryOperator::Opcode Opc,
+ ExprArg input) {
Expr *Input = (Expr*)input.get();
- UnaryOperator::Opcode Opc = ConvertTokenKindToUnaryOpcode(Op);
-
if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType()) {
// Find all of the overloaded operators visible from this
// point. We perform both an operator-name lookup from the local
@@ -5601,19 +5645,26 @@ Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
FunctionSet Functions;
OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc);
if (OverOp != OO_None) {
- LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
- Functions);
+ if (S)
+ LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
+ Functions);
DeclarationName OpName
= Context.DeclarationNames.getCXXOperatorName(OverOp);
ArgumentDependentLookup(OpName, /*Operator*/true, &Input, 1, Functions);
}
-
+
return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input));
}
-
+
return CreateBuiltinUnaryOp(OpLoc, Opc, move(input));
}
+// Unary Operators. 'Tok' is the token for the operator.
+Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Op, ExprArg input) {
+ return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), move(input));
+}
+
/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
Sema::OwningExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
SourceLocation LabLoc,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 4868c14835f4..dc5768157356 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1603,6 +1603,8 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (LHS->isTypeDependent() || RHS->isTypeDependent())
return Context.DependentTy;
+ CheckSignCompare(LHS, RHS, QuestionLoc, diag::warn_mixed_sign_conditional);
+
// C++0x 5.16p2
// If either the second or the third operand has type (cv) void, ...
QualType LTy = LHS->getType();
@@ -2030,7 +2032,13 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
QualType BaseType = BaseExpr->getType();
if (BaseType->isDependentType()) {
- // FIXME: member of the current instantiation
+ // If we have a pointer to a dependent type and are using the -> operator,
+ // the object type is the type that the pointer points to. We might still
+ // have enough information about that type to do something useful.
+ if (OpKind == tok::arrow)
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+ BaseType = Ptr->getPointeeType();
+
ObjectType = BaseType.getAsOpaquePtr();
return move(Base);
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 946e28269eb6..3e6778bc4770 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1387,8 +1387,10 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion(
bool AllowExplicit, bool ForceRValue,
bool UserCast) {
if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) {
- if (CXXRecordDecl *ToRecordDecl
- = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
+ if (RequireCompleteType(From->getLocStart(), ToType, PDiag())) {
+ // We're not going to find any constructors.
+ } else if (CXXRecordDecl *ToRecordDecl
+ = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
// C++ [over.match.ctor]p1:
// When objects of class type are direct-initialized (8.5), or
// copy-initialized from an expression of the same or a
@@ -2097,8 +2099,8 @@ Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) {
// First check the qualifiers. We don't care about lvalue-vs-rvalue
// with the implicit object parameter (C++ [over.match.funcs]p5).
QualType FromTypeCanon = Context.getCanonicalType(FromType);
- if (ImplicitParamType.getCVRQualifiers() != FromType.getCVRQualifiers() &&
- !ImplicitParamType.isAtLeastAsQualifiedAs(FromType))
+ if (ImplicitParamType.getCVRQualifiers() != FromTypeCanon.getCVRQualifiers() &&
+ !ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon))
return ICS;
// Check that we have either the same type or a derived type. It
@@ -3050,6 +3052,10 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
// We don't care about qualifiers on the type.
Ty = Ty.getUnqualifiedType();
+ // If we're dealing with an array type, decay to the pointer.
+ if (Ty->isArrayType())
+ Ty = SemaRef.Context.getArrayDecayedType(Ty);
+
if (const PointerType *PointerTy = Ty->getAs<PointerType>()) {
QualType PointeeTy = PointerTy->getPointeeType();
@@ -4787,11 +4793,20 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// If either side is type-dependent, create an appropriate dependent
// expression.
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
- // .* cannot be overloaded.
- if (Opc == BinaryOperator::PtrMemD)
- return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
- Context.DependentTy, OpLoc));
-
+ if (Functions.empty()) {
+ // If there are no functions to store, just build a dependent
+ // BinaryOperator or CompoundAssignment.
+ if (Opc <= BinaryOperator::Assign || Opc > BinaryOperator::OrAssign)
+ return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
+ Context.DependentTy, OpLoc));
+
+ return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,
+ Context.DependentTy,
+ Context.DependentTy,
+ Context.DependentTy,
+ OpLoc));
+ }
+
OverloadedFunctionDecl *Overloads
= OverloadedFunctionDecl::Create(Context, CurContext, OpName);
for (FunctionSet::iterator Func = Functions.begin(),
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 3c56358d5a94..5ef370104dd9 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1995,7 +1995,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
ArgType = Context.getCanonicalType(ArgType).getUnqualifiedType();
// Try to convert the argument to the parameter's type.
- if (ParamType == ArgType) {
+ if (Context.hasSameType(ParamType, ArgType)) {
// Okay: no conversion necessary
} else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
!ParamType->isEnumeralType()) {
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 0003b1b0c419..f003127f149f 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -22,6 +22,7 @@
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace clang;
/// \brief Perform adjustment on the parameter type of a function.
@@ -562,9 +563,17 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
SourceLocation Loc = Brackets.getBegin();
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
// reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
- if (RequireCompleteType(Loc, T,
- diag::err_illegal_decl_array_incomplete_type))
- return QualType();
+ // Not in C++, though. There we only dislike void.
+ if (getLangOptions().CPlusPlus) {
+ if (T->isVoidType()) {
+ Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
+ return QualType();
+ }
+ } else {
+ if (RequireCompleteType(Loc, T,
+ diag::err_illegal_decl_array_incomplete_type))
+ return QualType();
+ }
if (T->isFunctionType()) {
Diag(Loc, diag::err_illegal_decl_array_of_functions)
@@ -612,24 +621,24 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
} else if (ArraySize->isValueDependent()) {
T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
} else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
- (!T->isDependentType() && !T->isConstantSizeType())) {
+ (!T->isDependentType() && !T->isIncompleteType() &&
+ !T->isConstantSizeType())) {
// Per C99, a variable array is an array with either a non-constant
// size or an element type that has a non-constant-size
T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
} else {
// C99 6.7.5.2p1: If the expression is a constant expression, it shall
// have a value greater than zero.
- if (ConstVal.isSigned()) {
- if (ConstVal.isNegative()) {
- Diag(ArraySize->getLocStart(),
- diag::err_typecheck_negative_array_size)
- << ArraySize->getSourceRange();
- return QualType();
- } else if (ConstVal == 0) {
- // GCC accepts zero sized static arrays.
- Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size)
- << ArraySize->getSourceRange();
- }
+ if (ConstVal.isSigned() && ConstVal.isNegative()) {
+ Diag(ArraySize->getLocStart(),
+ diag::err_typecheck_negative_array_size)
+ << ArraySize->getSourceRange();
+ return QualType();
+ }
+ if (ConstVal == 0) {
+ // GCC accepts zero sized static arrays.
+ Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size)
+ << ArraySize->getSourceRange();
}
T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
}
@@ -1162,15 +1171,29 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
// The scope spec must refer to a class, or be dependent.
QualType ClsType;
- if (isDependentScopeSpecifier(DeclType.Mem.Scope())) {
+ if (isDependentScopeSpecifier(DeclType.Mem.Scope())
+ || dyn_cast_or_null<CXXRecordDecl>(
+ computeDeclContext(DeclType.Mem.Scope()))) {
NestedNameSpecifier *NNS
= (NestedNameSpecifier *)DeclType.Mem.Scope().getScopeRep();
- assert(NNS->getAsType() && "Nested-name-specifier must name a type");
- ClsType = QualType(NNS->getAsType(), 0);
- } else if (CXXRecordDecl *RD
- = dyn_cast_or_null<CXXRecordDecl>(
- computeDeclContext(DeclType.Mem.Scope()))) {
- ClsType = Context.getTagDeclType(RD);
+ NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ ClsType = Context.getTypenameType(NNSPrefix, NNS->getAsIdentifier());
+ break;
+
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::Global:
+ llvm::llvm_unreachable("Nested-name-specifier must name a type");
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ ClsType = QualType(NNS->getAsType(), 0);
+ if (NNSPrefix)
+ ClsType = Context.getQualifiedNameType(NNSPrefix, ClsType);
+ break;
+ }
} else {
Diag(DeclType.Mem.Scope().getBeginLoc(),
diag::err_illegal_decl_mempointer_in_nonclass)
@@ -1677,8 +1700,12 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
return false;
// If we have a class template specialization or a class member of a
- // class template specialization, try to instantiate it.
- if (const RecordType *Record = T->getAs<RecordType>()) {
+ // class template specialization, or an array with known size of such,
+ // try to instantiate it.
+ QualType MaybeTemplate = T;
+ if (const ConstantArrayType *Array = T->getAs<ConstantArrayType>())
+ MaybeTemplate = Array->getElementType();
+ if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
if (ClassTemplateSpecializationDecl *ClassTemplateSpec
= dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 5713da9fa590..767725a1f318 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -877,7 +877,7 @@ public:
OwningExprResult RebuildUnaryOperator(SourceLocation OpLoc,
UnaryOperator::Opcode Opc,
ExprArg SubExpr) {
- return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, move(SubExpr));
+ return getSema().BuildUnaryOp(/*Scope=*/0, OpLoc, Opc, move(SubExpr));
}
/// \brief Build a new sizeof or alignof expression with a type argument.
@@ -941,7 +941,13 @@ public:
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
SourceLocation MemberLoc,
- NamedDecl *Member) {
+ NamedDecl *Member,
+ bool HasExplicitTemplateArgs,
+ SourceLocation LAngleLoc,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
+ unsigned NumExplicitTemplateArgs,
+ SourceLocation RAngleLoc,
+ NamedDecl *FirstQualifierInScope) {
if (!Member->getDeclName()) {
// We have a reference to an unnamed field.
assert(!Qualifier && "Can't have an unnamed field with a qualifier!");
@@ -963,8 +969,14 @@ public:
isArrow? tok::arrow : tok::period,
MemberLoc,
Member->getDeclName(),
+ HasExplicitTemplateArgs,
+ LAngleLoc,
+ ExplicitTemplateArgs,
+ NumExplicitTemplateArgs,
+ RAngleLoc,
/*FIXME?*/Sema::DeclPtrTy::make((Decl*)0),
- &SS);
+ &SS,
+ FirstQualifierInScope);
}
/// \brief Build a new binary operator expression.
@@ -974,15 +986,8 @@ public:
OwningExprResult RebuildBinaryOperator(SourceLocation OpLoc,
BinaryOperator::Opcode Opc,
ExprArg LHS, ExprArg RHS) {
- OwningExprResult Result
- = getSema().CreateBuiltinBinOp(OpLoc, Opc, (Expr *)LHS.get(),
- (Expr *)RHS.get());
- if (Result.isInvalid())
- return SemaRef.ExprError();
-
- LHS.release();
- RHS.release();
- return move(Result);
+ return getSema().BuildBinOp(/*Scope=*/0, OpLoc, Opc,
+ LHS.takeAs<Expr>(), RHS.takeAs<Expr>());
}
/// \brief Build a new conditional operator expression.
@@ -3656,9 +3661,20 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E,
if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase() &&
Qualifier == E->getQualifier() &&
- Member == E->getMemberDecl())
+ Member == E->getMemberDecl() &&
+ !E->hasExplicitTemplateArgumentList())
return SemaRef.Owned(E->Retain());
+ llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs;
+ if (E->hasExplicitTemplateArgumentList()) {
+ TransArgs.resize(E->getNumTemplateArgs());
+ for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
+ if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I],
+ TransArgs[I]))
+ return SemaRef.ExprError();
+ }
+ }
+
// FIXME: Bogus source location for the operator
SourceLocation FakeOperatorLoc
= SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
@@ -3668,7 +3684,13 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E,
Qualifier,
E->getQualifierRange(),
E->getMemberLoc(),
- Member);
+ Member,
+ E->hasExplicitTemplateArgumentList(),
+ E->getLAngleLoc(),
+ TransArgs.data(),
+ TransArgs.size(),
+ E->getRAngleLoc(),
+ 0);
}
template<typename Derived>