summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp279
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp100
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp331
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp51
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp46
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Scope.cpp57
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Sema.cpp144
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp366
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp85
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp314
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp166
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp1222
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp361
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp710
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp105
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp304
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp2844
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp1068
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp219
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp240
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp53
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp46
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp801
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp494
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp726
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp125
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp117
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp236
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaType.cpp396
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TreeTransform.h1475
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h3
37 files changed, 9350 insertions, 4191 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 6a42224..e482172 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -24,12 +24,13 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/Analyses/ReachableCode.h"
#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
#include "clang/Analysis/CFGStmtMap.h"
-#include "clang/Analysis/Analyses/UninitializedValuesV2.h"
+#include "clang/Analysis/Analyses/UninitializedValues.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/Support/Casting.h"
@@ -129,12 +130,27 @@ static ControlFlowKind CheckFallThrough(AnalysisContext &AC) {
// normal. We need to look pass the destructors for the return
// statement (if it exists).
CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend();
+ bool hasNoReturnDtor = false;
+
for ( ; ri != re ; ++ri) {
CFGElement CE = *ri;
+
+ // FIXME: The right solution is to just sever the edges in the
+ // CFG itself.
+ if (const CFGImplicitDtor *iDtor = ri->getAs<CFGImplicitDtor>())
+ if (iDtor->isNoReturn(AC.getASTContext())) {
+ hasNoReturnDtor = true;
+ HasFakeEdge = true;
+ break;
+ }
+
if (isa<CFGStmt>(CE))
break;
}
+ if (hasNoReturnDtor)
+ continue;
+
// No more CFGElements in the block?
if (ri == re) {
if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
@@ -363,17 +379,145 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
//===----------------------------------------------------------------------===//
namespace {
+/// ContainsReference - A visitor class to search for references to
+/// a particular declaration (the needle) within any evaluated component of an
+/// expression (recursively).
+class ContainsReference : public EvaluatedExprVisitor<ContainsReference> {
+ bool FoundReference;
+ const DeclRefExpr *Needle;
+
+public:
+ ContainsReference(ASTContext &Context, const DeclRefExpr *Needle)
+ : EvaluatedExprVisitor<ContainsReference>(Context),
+ FoundReference(false), Needle(Needle) {}
+
+ void VisitExpr(Expr *E) {
+ // Stop evaluating if we already have a reference.
+ if (FoundReference)
+ return;
+
+ EvaluatedExprVisitor<ContainsReference>::VisitExpr(E);
+ }
+
+ void VisitDeclRefExpr(DeclRefExpr *E) {
+ if (E == Needle)
+ FoundReference = true;
+ else
+ EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E);
+ }
+
+ bool doesContainReference() const { return FoundReference; }
+};
+}
+
+/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
+/// uninitialized variable. This manages the different forms of diagnostic
+/// emitted for particular types of uses. Returns true if the use was diagnosed
+/// as a warning. If a pariticular use is one we omit warnings for, returns
+/// false.
+static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
+ const Expr *E, bool isAlwaysUninit) {
+ bool isSelfInit = false;
+
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (isAlwaysUninit) {
+ // Inspect the initializer of the variable declaration which is
+ // being referenced prior to its initialization. We emit
+ // specialized diagnostics for self-initialization, and we
+ // specifically avoid warning about self references which take the
+ // form of:
+ //
+ // int x = x;
+ //
+ // This is used to indicate to GCC that 'x' is intentionally left
+ // uninitialized. Proven code paths which access 'x' in
+ // an uninitialized state after this will still warn.
+ //
+ // TODO: Should we suppress maybe-uninitialized warnings for
+ // variables initialized in this way?
+ if (const Expr *Initializer = VD->getInit()) {
+ if (DRE == Initializer->IgnoreParenImpCasts())
+ return false;
+
+ ContainsReference CR(S.Context, DRE);
+ CR.Visit(const_cast<Expr*>(Initializer));
+ isSelfInit = CR.doesContainReference();
+ }
+ if (isSelfInit) {
+ S.Diag(DRE->getLocStart(),
+ diag::warn_uninit_self_reference_in_init)
+ << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
+ } else {
+ S.Diag(DRE->getLocStart(), diag::warn_uninit_var)
+ << VD->getDeclName() << DRE->getSourceRange();
+ }
+ } else {
+ S.Diag(DRE->getLocStart(), diag::warn_maybe_uninit_var)
+ << VD->getDeclName() << DRE->getSourceRange();
+ }
+ } else {
+ const BlockExpr *BE = cast<BlockExpr>(E);
+ S.Diag(BE->getLocStart(),
+ isAlwaysUninit ? diag::warn_uninit_var_captured_by_block
+ : diag::warn_maybe_uninit_var_captured_by_block)
+ << VD->getDeclName();
+ }
+
+ // Report where the variable was declared when the use wasn't within
+ // the initializer of that declaration.
+ if (!isSelfInit)
+ S.Diag(VD->getLocStart(), diag::note_uninit_var_def)
+ << VD->getDeclName();
+
+ return true;
+}
+
+static void SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
+ // Don't issue a fixit if there is already an initializer.
+ if (VD->getInit())
+ return;
+
+ // Suggest possible initialization (if any).
+ const char *initialization = 0;
+ QualType VariableTy = VD->getType().getCanonicalType();
+
+ if (VariableTy->getAs<ObjCObjectPointerType>()) {
+ // Check if 'nil' is defined.
+ if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil")))
+ initialization = " = nil";
+ else
+ initialization = " = 0";
+ }
+ else if (VariableTy->isRealFloatingType())
+ initialization = " = 0.0";
+ else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus)
+ initialization = " = false";
+ else if (VariableTy->isEnumeralType())
+ return;
+ else if (VariableTy->isScalarType())
+ initialization = " = 0";
+
+ if (initialization) {
+ SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd());
+ S.Diag(loc, diag::note_var_fixit_add_initialization)
+ << FixItHint::CreateInsertion(loc, initialization);
+ }
+}
+
+typedef std::pair<const Expr*, bool> UninitUse;
+
+namespace {
struct SLocSort {
- bool operator()(const Expr *a, const Expr *b) {
- SourceLocation aLoc = a->getLocStart();
- SourceLocation bLoc = b->getLocStart();
+ bool operator()(const UninitUse &a, const UninitUse &b) {
+ SourceLocation aLoc = a.first->getLocStart();
+ SourceLocation bLoc = b.first->getLocStart();
return aLoc.getRawEncoding() < bLoc.getRawEncoding();
}
};
class UninitValsDiagReporter : public UninitVariablesHandler {
Sema &S;
- typedef llvm::SmallVector<const Expr *, 2> UsesVec;
+ typedef llvm::SmallVector<UninitUse, 2> UsesVec;
typedef llvm::DenseMap<const VarDecl *, UsesVec*> UsesMap;
UsesMap *uses;
@@ -383,7 +527,8 @@ public:
flushDiagnostics();
}
- void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd) {
+ void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd,
+ bool isAlwaysUninit) {
if (!uses)
uses = new UsesMap();
@@ -391,7 +536,7 @@ public:
if (!vec)
vec = new UsesVec();
- vec->push_back(ex);
+ vec->push_back(std::make_pair(ex, isAlwaysUninit));
}
void flushDiagnostics() {
@@ -409,54 +554,19 @@ public:
// a stable ordering.
std::sort(vec->begin(), vec->end(), SLocSort());
- for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi)
- {
- if (const DeclRefExpr *dr = dyn_cast<DeclRefExpr>(*vi)) {
- S.Diag(dr->getLocStart(), diag::warn_uninit_var)
- << vd->getDeclName() << dr->getSourceRange();
- }
- else {
- const BlockExpr *be = cast<BlockExpr>(*vi);
- S.Diag(be->getLocStart(), diag::warn_uninit_var_captured_by_block)
- << vd->getDeclName();
- }
-
- // Report where the variable was declared.
- S.Diag(vd->getLocStart(), diag::note_uninit_var_def)
- << vd->getDeclName();
-
- // Only report the fixit once.
- if (fixitIssued)
+ for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve;
+ ++vi) {
+ if (!DiagnoseUninitializedUse(S, vd, vi->first,
+ /*isAlwaysUninit=*/vi->second))
continue;
-
- fixitIssued = true;
-
- // Suggest possible initialization (if any).
- const char *initialization = 0;
- QualType vdTy = vd->getType().getCanonicalType();
-
- if (vdTy->getAs<ObjCObjectPointerType>()) {
- // Check if 'nil' is defined.
- if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil")))
- initialization = " = nil";
- else
- initialization = " = 0";
- }
- else if (vdTy->isRealFloatingType())
- initialization = " = 0.0";
- else if (vdTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus)
- initialization = " = false";
- else if (vdTy->isEnumeralType())
- continue;
- else if (vdTy->isScalarType())
- initialization = " = 0";
-
- if (initialization) {
- SourceLocation loc = S.PP.getLocForEndOfToken(vd->getLocEnd());
- S.Diag(loc, diag::note_var_fixit_add_initialization)
- << FixItHint::CreateInsertion(loc, initialization);
+
+ // Suggest a fixit hint the first time we diagnose a use of a variable.
+ if (!fixitIssued) {
+ SuggestInitializationFixit(S, vd);
+ fixitIssued = true;
}
}
+
delete vec;
}
delete uses;
@@ -531,25 +641,41 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
// Emit delayed diagnostics.
if (!fscope->PossiblyUnreachableDiags.empty()) {
bool analyzed = false;
- if (CFGReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis())
- if (CFGStmtMap *csm = AC.getCFGStmtMap()) {
- analyzed = true;
- for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
- i = fscope->PossiblyUnreachableDiags.begin(),
- e = fscope->PossiblyUnreachableDiags.end();
- i != e; ++i) {
- const sema::PossiblyUnreachableDiag &D = *i;
- if (const CFGBlock *blk = csm->getBlock(D.stmt)) {
+
+ // Register the expressions with the CFGBuilder.
+ for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
+ i = fscope->PossiblyUnreachableDiags.begin(),
+ e = fscope->PossiblyUnreachableDiags.end();
+ i != e; ++i) {
+ if (const Stmt *stmt = i->stmt)
+ AC.registerForcedBlockExpression(stmt);
+ }
+
+ if (AC.getCFG()) {
+ analyzed = true;
+ for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
+ i = fscope->PossiblyUnreachableDiags.begin(),
+ e = fscope->PossiblyUnreachableDiags.end();
+ i != e; ++i)
+ {
+ const sema::PossiblyUnreachableDiag &D = *i;
+ bool processed = false;
+ if (const Stmt *stmt = i->stmt) {
+ const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt);
+ assert(block);
+ if (CFGReverseBlockReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) {
// Can this block be reached from the entrance?
- if (cra->isReachable(&AC.getCFG()->getEntry(), blk))
+ if (cra->isReachable(&AC.getCFG()->getEntry(), block))
S.Diag(D.Loc, D.PD);
- }
- else {
- // Emit the warning anyway if we cannot map to a basic block.
- S.Diag(D.Loc, D.PD);
+ processed = true;
}
}
+ if (!processed) {
+ // Emit the warning anyway if we cannot map to a basic block.
+ S.Diag(D.Loc, D.PD);
+ }
}
+ }
if (!analyzed)
flushDiagnostics(S, fscope);
@@ -569,25 +695,10 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
CheckUnreachable(S, AC);
if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart())
+ != Diagnostic::Ignored ||
+ Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart())
!= Diagnostic::Ignored) {
- ASTContext &ctx = D->getASTContext();
- llvm::OwningPtr<CFG> tmpCFG;
- bool useAlternateCFG = false;
- if (ctx.getLangOptions().CPlusPlus) {
- // Temporary workaround: implicit dtors in the CFG can confuse
- // the path-sensitivity in the uninitialized values analysis.
- // For now create (if necessary) a separate CFG without implicit dtors.
- // FIXME: We should not need to do this, as it results in multiple
- // CFGs getting constructed.
- CFG::BuildOptions B;
- B.AddEHEdges = false;
- B.AddImplicitDtors = false;
- B.AddInitializers = true;
- tmpCFG.reset(CFG::buildCFG(D, AC.getBody(), &ctx, B));
- useAlternateCFG = true;
- }
- CFG *cfg = useAlternateCFG ? tmpCFG.get() : AC.getCFG();
- if (cfg) {
+ if (CFG *cfg = AC.getCFG()) {
UninitValsDiagReporter reporter(S);
runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC,
reporter);
diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
index c0a3053..619a5b9 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
@@ -12,28 +12,89 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/AttributeList.h"
+#include "clang/AST/Expr.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
-AttributeList::AttributeList(llvm::BumpPtrAllocator &Alloc,
- IdentifierInfo *aName, SourceLocation aLoc,
- IdentifierInfo *sName, SourceLocation sLoc,
- IdentifierInfo *pName, SourceLocation pLoc,
- Expr **ExprList, unsigned numArgs,
- bool declspec, bool cxx0x)
- : AttrName(aName), AttrLoc(aLoc), ScopeName(sName),
- ScopeLoc(sLoc),
- ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(0),
- DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false) {
-
- if (numArgs == 0)
- Args = 0;
- else {
- // Allocate the Args array using the BumpPtrAllocator.
- Args = Alloc.Allocate<Expr*>(numArgs);
- memcpy(Args, ExprList, numArgs*sizeof(Args[0]));
+size_t AttributeList::allocated_size() const {
+ if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
+ return (sizeof(AttributeList) + NumArgs * sizeof(Expr*));
+}
+
+AttributeFactory::AttributeFactory() {
+ // Go ahead and configure all the inline capacity. This is just a memset.
+ FreeLists.resize(InlineFreeListsCapacity);
+}
+AttributeFactory::~AttributeFactory() {}
+
+static size_t getFreeListIndexForSize(size_t size) {
+ assert(size >= sizeof(AttributeList));
+ assert((size % sizeof(void*)) == 0);
+ return ((size - sizeof(AttributeList)) / sizeof(void*));
+}
+
+void *AttributeFactory::allocate(size_t size) {
+ // Check for a previously reclaimed attribute.
+ size_t index = getFreeListIndexForSize(size);
+ if (index < FreeLists.size()) {
+ if (AttributeList *attr = FreeLists[index]) {
+ FreeLists[index] = attr->NextInPool;
+ return attr;
+ }
}
+
+ // Otherwise, allocate something new.
+ return Alloc.Allocate(size, llvm::AlignOf<AttributeFactory>::Alignment);
+}
+
+void AttributeFactory::reclaimPool(AttributeList *cur) {
+ assert(cur && "reclaiming empty pool!");
+ do {
+ // Read this here, because we're going to overwrite NextInPool
+ // when we toss 'cur' into the appropriate queue.
+ AttributeList *next = cur->NextInPool;
+
+ size_t size = cur->allocated_size();
+ size_t freeListIndex = getFreeListIndexForSize(size);
+
+ // Expand FreeLists to the appropriate size, if required.
+ if (freeListIndex >= FreeLists.size())
+ FreeLists.resize(freeListIndex+1);
+
+ // Add 'cur' to the appropriate free-list.
+ cur->NextInPool = FreeLists[freeListIndex];
+ FreeLists[freeListIndex] = cur;
+
+ cur = next;
+ } while (cur);
+}
+
+void AttributePool::takePool(AttributeList *pool) {
+ assert(pool);
+
+ // Fast path: this pool is empty.
+ if (!Head) {
+ Head = pool;
+ return;
+ }
+
+ // Reverse the pool onto the current head. This optimizes for the
+ // pattern of pulling a lot of pools into a single pool.
+ do {
+ AttributeList *next = pool->NextInPool;
+ pool->NextInPool = Head;
+ Head = pool;
+ pool = next;
+ } while (pool);
+}
+
+AttributeList *
+AttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
+ SourceLocation TokLoc, int Arg) {
+ Expr *IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg),
+ C.IntTy, TokLoc);
+ return create(Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1, 0);
}
AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
@@ -83,6 +144,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("may_alias", AT_may_alias)
.Case("base_check", AT_base_check)
.Case("deprecated", AT_deprecated)
+ .Case("availability", AT_availability)
.Case("visibility", AT_visibility)
.Case("destructor", AT_destructor)
.Case("format_arg", AT_format_arg)
@@ -94,10 +156,12 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("unavailable", AT_unavailable)
.Case("overloadable", AT_overloadable)
.Case("address_space", AT_address_space)
+ .Case("opencl_image_access", AT_opencl_image_access)
.Case("always_inline", AT_always_inline)
.Case("returns_twice", IgnoredAttribute)
.Case("vec_type_hint", IgnoredAttribute)
.Case("objc_exception", AT_objc_exception)
+ .Case("objc_method_family", AT_objc_method_family)
.Case("ext_vector_type", AT_ext_vector_type)
.Case("neon_vector_type", AT_neon_vector_type)
.Case("neon_polyvector_type", AT_neon_polyvector_type)
@@ -137,5 +201,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("nocommon", AT_nocommon)
.Case("opencl_kernel_function", AT_opencl_kernel_function)
.Case("uuid", AT_uuid)
+ .Case("pcs", AT_pcs)
+ .Case("ms_struct", AT_MsStruct)
.Default(UnknownAttribute);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
index b7037ce..2334ab5 100644
--- a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -375,12 +375,21 @@ void CodeCompletionResult::computeCursorKindAndAvailability() {
switch (Kind) {
case RK_Declaration:
// Set the availability based on attributes.
- Availability = CXAvailability_Available;
- if (Declaration->getAttr<UnavailableAttr>())
- Availability = CXAvailability_NotAvailable;
- else if (Declaration->getAttr<DeprecatedAttr>())
+ switch (Declaration->getAvailability()) {
+ case AR_Available:
+ case AR_NotYetIntroduced:
+ Availability = CXAvailability_Available;
+ break;
+
+ case AR_Deprecated:
Availability = CXAvailability_Deprecated;
+ break;
+ case AR_Unavailable:
+ Availability = CXAvailability_NotAvailable;
+ break;
+ }
+
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration))
if (Function->isDeleted())
Availability = CXAvailability_NotAvailable;
diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
index 037594a..0f20d10 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
@@ -47,278 +47,130 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
EndLocation = TemplateId->RAngleLoc;
}
-CXXScopeSpec::CXXScopeSpec(const CXXScopeSpec &Other)
- : Range(Other.Range), ScopeRep(Other.ScopeRep), Buffer(0),
- BufferSize(Other.BufferSize), BufferCapacity(Other.BufferSize)
-{
- if (BufferSize) {
- Buffer = static_cast<char *>(malloc(BufferSize));
- memcpy(Buffer, Other.Buffer, BufferSize);
- }
-}
-
-CXXScopeSpec &CXXScopeSpec::operator=(const CXXScopeSpec &Other) {
- Range = Other.Range;
- ScopeRep = Other.ScopeRep;
- if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
- // Re-use our storage.
- BufferSize = Other.BufferSize;
- memcpy(Buffer, Other.Buffer, BufferSize);
- return *this;
- }
-
- if (BufferCapacity)
- free(Buffer);
- if (Other.Buffer) {
- BufferSize = Other.BufferSize;
- BufferCapacity = BufferSize;
- Buffer = static_cast<char *>(malloc(BufferSize));
- memcpy(Buffer, Other.Buffer, BufferSize);
- } else {
- Buffer = 0;
- BufferSize = 0;
- BufferCapacity = 0;
- }
- return *this;
-}
-
-CXXScopeSpec::~CXXScopeSpec() {
- if (BufferCapacity)
- free(Buffer);
-}
-
-namespace {
- void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
- unsigned &BufferCapacity) {
- if (BufferSize + (End - Start) > BufferCapacity) {
- // Reallocate the buffer.
- unsigned NewCapacity
- = std::max((unsigned)(BufferCapacity? BufferCapacity * 2
- : sizeof(void*) * 2),
- (unsigned)(BufferSize + (End - Start)));
- char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
- memcpy(NewBuffer, Buffer, BufferSize);
-
- if (BufferCapacity)
- free(Buffer);
- Buffer = NewBuffer;
- BufferCapacity = NewCapacity;
- }
-
- memcpy(Buffer + BufferSize, Start, End - Start);
- BufferSize += End-Start;
- }
-
- /// \brief Save a source location to the given buffer.
- void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
- unsigned &BufferSize, unsigned &BufferCapacity) {
- unsigned Raw = Loc.getRawEncoding();
- Append(reinterpret_cast<char *>(&Raw),
- reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
- Buffer, BufferSize, BufferCapacity);
- }
-
- /// \brief Save a pointer to the given buffer.
- void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
- unsigned &BufferCapacity) {
- Append(reinterpret_cast<char *>(&Ptr),
- reinterpret_cast<char *>(&Ptr) + sizeof(void *),
- Buffer, BufferSize, BufferCapacity);
- }
-}
void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc,
TypeLoc TL, SourceLocation ColonColonLoc) {
- ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep,
- TemplateKWLoc.isValid(),
- TL.getTypePtr());
+ Builder.Extend(Context, TemplateKWLoc, TL, ColonColonLoc);
if (Range.getBegin().isInvalid())
Range.setBegin(TL.getBeginLoc());
Range.setEnd(ColonColonLoc);
- // Push source-location info into the buffer.
- SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
- SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
-
- assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ assert(Range == Builder.getSourceRange() &&
"NestedNameSpecifierLoc range computation incorrect");
}
void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier,
SourceLocation IdentifierLoc,
SourceLocation ColonColonLoc) {
- ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Identifier);
+ Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc);
+
if (Range.getBegin().isInvalid())
Range.setBegin(IdentifierLoc);
Range.setEnd(ColonColonLoc);
- // Push source-location info into the buffer.
- SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
- SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
-
- assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ assert(Range == Builder.getSourceRange() &&
"NestedNameSpecifierLoc range computation incorrect");
}
void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
SourceLocation NamespaceLoc,
SourceLocation ColonColonLoc) {
- ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Namespace);
+ Builder.Extend(Context, Namespace, NamespaceLoc, ColonColonLoc);
+
if (Range.getBegin().isInvalid())
Range.setBegin(NamespaceLoc);
Range.setEnd(ColonColonLoc);
- // Push source-location info into the buffer.
- SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
- SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
-
- assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ assert(Range == Builder.getSourceRange() &&
"NestedNameSpecifierLoc range computation incorrect");
}
void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
SourceLocation AliasLoc,
SourceLocation ColonColonLoc) {
- ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Alias);
+ Builder.Extend(Context, Alias, AliasLoc, ColonColonLoc);
+
if (Range.getBegin().isInvalid())
Range.setBegin(AliasLoc);
Range.setEnd(ColonColonLoc);
- // Push source-location info into the buffer.
- SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
- SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
-
- assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ assert(Range == Builder.getSourceRange() &&
"NestedNameSpecifierLoc range computation incorrect");
}
void CXXScopeSpec::MakeGlobal(ASTContext &Context,
SourceLocation ColonColonLoc) {
- assert(!ScopeRep && "Already have a nested-name-specifier!?");
- ScopeRep = NestedNameSpecifier::GlobalSpecifier(Context);
- Range = SourceRange(ColonColonLoc);
+ Builder.MakeGlobal(Context, ColonColonLoc);
- // Push source-location info into the buffer.
- SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+ Range = SourceRange(ColonColonLoc);
- assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ assert(Range == Builder.getSourceRange() &&
"NestedNameSpecifierLoc range computation incorrect");
}
void CXXScopeSpec::MakeTrivial(ASTContext &Context,
NestedNameSpecifier *Qualifier, SourceRange R) {
- ScopeRep = Qualifier;
+ Builder.MakeTrivial(Context, Qualifier, R);
Range = R;
-
- // Construct bogus (but well-formed) source information for the
- // nested-name-specifier.
- BufferSize = 0;
- llvm::SmallVector<NestedNameSpecifier *, 4> Stack;
- for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
- Stack.push_back(NNS);
- while (!Stack.empty()) {
- NestedNameSpecifier *NNS = Stack.back();
- Stack.pop_back();
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
- break;
-
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate: {
- TypeSourceInfo *TSInfo
- = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
- R.getBegin());
- SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
- BufferCapacity);
- break;
- }
-
- case NestedNameSpecifier::Global:
- break;
- }
-
- // Save the location of the '::'.
- SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
- Buffer, BufferSize, BufferCapacity);
- }
}
void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) {
if (!Other) {
Range = SourceRange();
- ScopeRep = 0;
+ Builder.Clear();
return;
}
-
- if (BufferCapacity)
- free(Buffer);
-
- // Rather than copying the data (which is wasteful), "adopt" the
- // pointer (which points into the ASTContext) but set the capacity to zero to
- // indicate that we don't own it.
+
Range = Other.getSourceRange();
- ScopeRep = Other.getNestedNameSpecifier();
- Buffer = static_cast<char *>(Other.getOpaqueData());
- BufferSize = Other.getDataLength();
- BufferCapacity = 0;
+ Builder.Adopt(Other);
}
NestedNameSpecifierLoc
CXXScopeSpec::getWithLocInContext(ASTContext &Context) const {
- if (isEmpty() || isInvalid())
+ if (!Builder.getRepresentation())
return NestedNameSpecifierLoc();
- // If we adopted our data pointer from elsewhere in the AST context, there's
- // no need to copy the memory.
- if (BufferCapacity == 0)
- return NestedNameSpecifierLoc(ScopeRep, Buffer);
-
- void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>());
- memcpy(Mem, Buffer, BufferSize);
- return NestedNameSpecifierLoc(ScopeRep, Mem);
+ return Builder.getWithLocInContext(Context);
}
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
/// "TheDeclarator" is the declarator that this will be added to.
-DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs,
- bool hasProto, bool isVariadic,
+DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
SourceLocation EllipsisLoc,
ParamInfo *ArgInfo,
unsigned NumArgs,
unsigned TypeQuals,
bool RefQualifierIsLvalueRef,
SourceLocation RefQualifierLoc,
- bool hasExceptionSpec,
- SourceLocation ThrowLoc,
- bool hasAnyExceptionSpec,
+ ExceptionSpecificationType
+ ESpecType,
+ SourceLocation ESpecLoc,
ParsedType *Exceptions,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
- SourceLocation LPLoc,
- SourceLocation RPLoc,
+ Expr *NoexceptExpr,
+ SourceLocation LocalRangeBegin,
+ SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
ParsedType TrailingReturnType) {
DeclaratorChunk I;
- I.Kind = Function;
- I.Loc = LPLoc;
- I.EndLoc = RPLoc;
- I.Fun.AttrList = attrs.getList();
- I.Fun.hasPrototype = hasProto;
- I.Fun.isVariadic = isVariadic;
- I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
- I.Fun.DeleteArgInfo = false;
- I.Fun.TypeQuals = TypeQuals;
- I.Fun.NumArgs = NumArgs;
- I.Fun.ArgInfo = 0;
+ I.Kind = Function;
+ I.Loc = LocalRangeBegin;
+ I.EndLoc = LocalRangeEnd;
+ I.Fun.AttrList = 0;
+ I.Fun.hasPrototype = hasProto;
+ I.Fun.isVariadic = isVariadic;
+ I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
+ I.Fun.DeleteArgInfo = false;
+ I.Fun.TypeQuals = TypeQuals;
+ I.Fun.NumArgs = NumArgs;
+ I.Fun.ArgInfo = 0;
I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef;
- I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
- I.Fun.hasExceptionSpec = hasExceptionSpec;
- I.Fun.ThrowLoc = ThrowLoc.getRawEncoding();
- I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec;
- I.Fun.NumExceptions = NumExceptions;
- I.Fun.Exceptions = 0;
+ I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
+ I.Fun.ExceptionSpecType = ESpecType;
+ I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding();
+ I.Fun.NumExceptions = 0;
+ I.Fun.Exceptions = 0;
+ I.Fun.NoexceptExpr = 0;
I.Fun.TrailingReturnType = TrailingReturnType.getAsOpaquePtr();
// new[] an argument array if needed.
@@ -338,13 +190,25 @@ DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs,
}
memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
}
- // new[] an exception array if needed
- if (NumExceptions) {
- I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions];
- for (unsigned i = 0; i != NumExceptions; ++i) {
- I.Fun.Exceptions[i].Ty = Exceptions[i];
- I.Fun.Exceptions[i].Range = ExceptionRanges[i];
+
+ // Check what exception specification information we should actually store.
+ switch (ESpecType) {
+ default: break; // By default, save nothing.
+ case EST_Dynamic:
+ // new[] an exception array if needed
+ if (NumExceptions) {
+ I.Fun.NumExceptions = NumExceptions;
+ I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions];
+ for (unsigned i = 0; i != NumExceptions; ++i) {
+ I.Fun.Exceptions[i].Ty = Exceptions[i];
+ I.Fun.Exceptions[i].Range = ExceptionRanges[i];
+ }
}
+ break;
+
+ case EST_ComputedNoexcept:
+ I.Fun.NoexceptExpr = NoexceptExpr;
+ break;
}
return I;
}
@@ -445,6 +309,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
case DeclSpec::TST_typeofExpr: return "typeof";
case DeclSpec::TST_auto: return "auto";
case DeclSpec::TST_decltype: return "(decltype)";
+ case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
case DeclSpec::TST_error: return "(error)";
}
llvm_unreachable("Unknown typespec!");
@@ -515,12 +380,14 @@ bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc,
bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
const char *&PrevSpec,
unsigned &DiagID) {
- if (TypeSpecWidth != TSW_unspecified &&
- // Allow turning long -> long long.
- (W != TSW_longlong || TypeSpecWidth != TSW_long))
+ // Overwrite TSWLoc only if TypeSpecWidth was unspecified, so that
+ // for 'long long' we will keep the source location of the first 'long'.
+ if (TypeSpecWidth == TSW_unspecified)
+ TSWLoc = Loc;
+ // Allow turning long -> long long.
+ else if (W != TSW_longlong || TypeSpecWidth != TSW_long)
return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
TypeSpecWidth = W;
- TSWLoc = Loc;
if (TypeAltiVecVector && !TypeAltiVecBool &&
((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) {
PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
@@ -554,6 +421,14 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
const char *&PrevSpec,
unsigned &DiagID,
ParsedType Rep) {
+ return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep);
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
+ SourceLocation TagNameLoc,
+ const char *&PrevSpec,
+ unsigned &DiagID,
+ ParsedType Rep) {
assert(isTypeRep(T) && "T does not store a type");
assert(Rep && "no type provided!");
if (TypeSpecType != TST_unspecified) {
@@ -563,7 +438,8 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
}
TypeSpecType = T;
TypeRep = Rep;
- TSTLoc = Loc;
+ TSTLoc = TagKwLoc;
+ TSTNameLoc = TagNameLoc;
TypeSpecOwned = false;
return false;
}
@@ -582,6 +458,7 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
TypeSpecType = T;
ExprRep = Rep;
TSTLoc = Loc;
+ TSTNameLoc = Loc;
TypeSpecOwned = false;
return false;
}
@@ -590,6 +467,14 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
const char *&PrevSpec,
unsigned &DiagID,
Decl *Rep, bool Owned) {
+ return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Owned);
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
+ SourceLocation TagNameLoc,
+ const char *&PrevSpec,
+ unsigned &DiagID,
+ Decl *Rep, bool Owned) {
assert(isDeclRep(T) && "T does not store a decl");
// Unlike the other cases, we don't assert that we actually get a decl.
@@ -600,7 +485,8 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
}
TypeSpecType = T;
DeclRep = Rep;
- TSTLoc = Loc;
+ TSTLoc = TagKwLoc;
+ TSTNameLoc = TagNameLoc;
TypeSpecOwned = Owned;
return false;
}
@@ -615,13 +501,13 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
DiagID = diag::err_invalid_decl_spec_combination;
return true;
}
+ TSTLoc = Loc;
+ TSTNameLoc = Loc;
if (TypeAltiVecVector && (T == TST_bool) && !TypeAltiVecBool) {
TypeAltiVecBool = true;
- TSTLoc = Loc;
return false;
}
TypeSpecType = T;
- TSTLoc = Loc;
TypeSpecOwned = false;
if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) {
PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
@@ -653,6 +539,7 @@ bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
}
TypeAltiVecPixel = isAltiVecPixel;
TSTLoc = Loc;
+ TSTNameLoc = Loc;
return false;
}
@@ -660,6 +547,7 @@ bool DeclSpec::SetTypeSpecError() {
TypeSpecType = TST_error;
TypeSpecOwned = false;
TSTLoc = SourceLocation();
+ TSTNameLoc = SourceLocation();
return false;
}
@@ -929,6 +817,8 @@ void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc,
const char *&PrevSpec) {
+ LastLocation = Loc;
+
if (Specifiers & VS) {
PrevSpec = getSpecifierName(VS);
return true;
@@ -940,7 +830,6 @@ bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc,
default: assert(0 && "Unknown specifier!");
case VS_Override: VS_overrideLoc = Loc; break;
case VS_Final: VS_finalLoc = Loc; break;
- case VS_New: VS_newLoc = Loc; break;
}
return false;
@@ -951,33 +840,5 @@ const char *VirtSpecifiers::getSpecifierName(Specifier VS) {
default: assert(0 && "Unknown specifier");
case VS_Override: return "override";
case VS_Final: return "final";
- case VS_New: return "new";
}
}
-
-bool ClassVirtSpecifiers::SetSpecifier(Specifier CVS, SourceLocation Loc,
- const char *&PrevSpec) {
- if (Specifiers & CVS) {
- PrevSpec = getSpecifierName(CVS);
- return true;
- }
-
- Specifiers |= CVS;
-
- switch (CVS) {
- default: assert(0 && "Unknown specifier!");
- case CVS_Final: CVS_finalLoc = Loc; break;
- case CVS_Explicit: CVS_explicitLoc = Loc; break;
- }
-
- return false;
-}
-
-const char *ClassVirtSpecifiers::getSpecifierName(Specifier CVS) {
- switch (CVS) {
- default: assert(0 && "Unknown specifier");
- case CVS_Final: return "final";
- case CVS_Explicit: return "explicit";
- }
-}
-
diff --git a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
new file mode 100644
index 0000000..af548fe
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp
@@ -0,0 +1,51 @@
+//===--- DelayedDiagnostic.cpp - Delayed declarator diagnostics -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DelayedDiagnostic class implementation, which
+// is used to record diagnostics that are being conditionally produced
+// during declarator parsing.
+//
+// This file also defines AccessedEntity.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Sema/DelayedDiagnostic.h"
+#include <string.h>
+using namespace clang;
+using namespace sema;
+
+DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc,
+ const NamedDecl *D,
+ llvm::StringRef Msg) {
+ DelayedDiagnostic DD;
+ DD.Kind = Deprecation;
+ DD.Triggered = false;
+ DD.Loc = Loc;
+ DD.DeprecationData.Decl = D;
+ char *MessageData = 0;
+ if (Msg.size()) {
+ MessageData = new char [Msg.size()];
+ memcpy(MessageData, Msg.data(), Msg.size());
+ }
+
+ DD.DeprecationData.Message = MessageData;
+ DD.DeprecationData.MessageLen = Msg.size();
+ return DD;
+}
+
+void DelayedDiagnostic::Destroy() {
+ switch (Kind) {
+ case Access:
+ getAccessData().~AccessedEntity();
+ break;
+
+ case Deprecation:
+ delete [] DeprecationData.Message;
+ break;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
index 3f16ed7..95420a3 100644
--- a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
@@ -104,7 +104,8 @@ IdentifierResolver::~IdentifierResolver() {
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
- ASTContext &Context, Scope *S) const {
+ ASTContext &Context, Scope *S,
+ bool ExplicitInstantiationOrSpecialization) const {
Ctx = Ctx->getRedeclContext();
if (Ctx->isFunctionOrMethod()) {
@@ -135,7 +136,10 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
return false;
}
- return D->getDeclContext()->getRedeclContext()->Equals(Ctx);
+ DeclContext *DCtx = D->getDeclContext()->getRedeclContext();
+ return ExplicitInstantiationOrSpecialization
+ ? Ctx->InEnclosingNamespaceSetOf(DCtx)
+ : Ctx->Equals(DCtx);
}
/// AddDecl - Link the decl to its shadowed decl chain.
@@ -164,6 +168,44 @@ void IdentifierResolver::AddDecl(NamedDecl *D) {
IDI->AddDecl(D);
}
+void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) {
+ DeclarationName Name = D->getDeclName();
+ void *Ptr = Name.getFETokenInfo<void>();
+
+ if (!Ptr) {
+ AddDecl(D);
+ return;
+ }
+
+ if (isDeclPtr(Ptr)) {
+ // We only have a single declaration: insert before or after it,
+ // as appropriate.
+ if (Pos == iterator()) {
+ // Add the new declaration before the existing declaration.
+ NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+ RemoveDecl(PrevD);
+ AddDecl(D);
+ AddDecl(PrevD);
+ } else {
+ // Add new declaration after the existing declaration.
+ AddDecl(D);
+ }
+
+ return;
+ }
+
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ II->setIsFromAST(false);
+
+ // General case: insert the declaration at the appropriate point in the
+ // list, which already has at least two elements.
+ IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+ if (Pos.isIterator()) {
+ IDI->InsertDecl(Pos.getIterator() + 1, D);
+ } else
+ IDI->InsertDecl(IDI->decls_begin(), D);
+}
+
/// RemoveDecl - Unlink the decl from its shadowed decl chain.
/// The decl must already be part of the decl chain.
void IdentifierResolver::RemoveDecl(NamedDecl *D) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
index b73f0e9..867d78f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
@@ -149,6 +149,11 @@ static std::pair<unsigned,unsigned>
return std::make_pair((unsigned) diag::note_protected_by_vla_typedef, 0);
}
+ if (const TypeAliasDecl *TD = dyn_cast<TypeAliasDecl>(D)) {
+ if (TD->getUnderlyingType()->isVariablyModifiedType())
+ return std::make_pair((unsigned) diag::note_protected_by_vla_type_alias, 0);
+ }
+
return std::make_pair(0U, 0U);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/Scope.cpp b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp
new file mode 100644
index 0000000..833a59f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp
@@ -0,0 +1,57 @@
+//===- Scope.cpp - Lexical scope information --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Scope class, which is used for recording
+// information about a lexical scope.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/Scope.h"
+
+using namespace clang;
+
+void Scope::Init(Scope *parent, unsigned flags) {
+ AnyParent = parent;
+ Flags = flags;
+
+ if (parent) {
+ Depth = parent->Depth + 1;
+ PrototypeDepth = parent->PrototypeDepth;
+ PrototypeIndex = 0;
+ FnParent = parent->FnParent;
+ BreakParent = parent->BreakParent;
+ ContinueParent = parent->ContinueParent;
+ ControlParent = parent->ControlParent;
+ BlockParent = parent->BlockParent;
+ TemplateParamParent = parent->TemplateParamParent;
+ } else {
+ Depth = 0;
+ PrototypeDepth = 0;
+ PrototypeIndex = 0;
+ FnParent = BreakParent = ContinueParent = BlockParent = 0;
+ ControlParent = 0;
+ TemplateParamParent = 0;
+ }
+
+ // If this scope is a function or contains breaks/continues, remember it.
+ if (flags & FnScope) FnParent = this;
+ if (flags & BreakScope) BreakParent = this;
+ if (flags & ContinueScope) ContinueParent = this;
+ if (flags & ControlScope) ControlParent = this;
+ if (flags & BlockScope) BlockParent = this;
+ if (flags & TemplateParamScope) TemplateParamParent = this;
+
+ // If this is a prototype scope, record that.
+ if (flags & FunctionPrototypeScope) PrototypeDepth++;
+
+ DeclsInScope.clear();
+ UsingDirectives.clear();
+ Entity = 0;
+ ErrorTrap.reset();
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
index 0c39e13..7707fb1 100644
--- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
@@ -67,12 +67,14 @@ void Sema::ActOnTranslationUnitScope(Scope *S) {
TInfo = Context.getTrivialTypeSourceInfo(Context.Int128Ty);
PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
SourceLocation(),
+ SourceLocation(),
&Context.Idents.get("__int128_t"),
TInfo), TUScope);
TInfo = Context.getTrivialTypeSourceInfo(Context.UnsignedInt128Ty);
PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
SourceLocation(),
+ SourceLocation(),
&Context.Idents.get("__uint128_t"),
TInfo), TUScope);
Context.setInt128Installed();
@@ -87,7 +89,8 @@ void Sema::ActOnTranslationUnitScope(Scope *S) {
QualType SelT = Context.getPointerType(Context.ObjCBuiltinSelTy);
TypeSourceInfo *SelInfo = Context.getTrivialTypeSourceInfo(SelT);
TypedefDecl *SelTypedef
- = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+ = TypedefDecl::Create(Context, CurContext,
+ SourceLocation(), SourceLocation(),
&Context.Idents.get("SEL"), SelInfo);
PushOnScopeChains(SelTypedef, TUScope);
Context.setObjCSelType(Context.getTypeDeclType(SelTypedef));
@@ -109,7 +112,8 @@ void Sema::ActOnTranslationUnitScope(Scope *S) {
T = Context.getObjCObjectPointerType(T);
TypeSourceInfo *IdInfo = Context.getTrivialTypeSourceInfo(T);
TypedefDecl *IdTypedef
- = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+ = TypedefDecl::Create(Context, CurContext,
+ SourceLocation(), SourceLocation(),
&Context.Idents.get("id"), IdInfo);
PushOnScopeChains(IdTypedef, TUScope);
Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
@@ -121,7 +125,8 @@ void Sema::ActOnTranslationUnitScope(Scope *S) {
T = Context.getObjCObjectPointerType(T);
TypeSourceInfo *ClassInfo = Context.getTrivialTypeSourceInfo(T);
TypedefDecl *ClassTypedef
- = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+ = TypedefDecl::Create(Context, CurContext,
+ SourceLocation(), SourceLocation(),
&Context.Idents.get("Class"), ClassInfo);
PushOnScopeChains(ClassTypedef, TUScope);
Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
@@ -136,7 +141,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0),
- PackContext(0), VisContext(0),
+ PackContext(0), MSStructPragmaOn(false), VisContext(0),
+ LateTemplateParser(0), OpaqueParser(0),
IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
GlobalNewDeleteDeclared(false),
CompleteTranslationUnit(CompleteTranslationUnit),
@@ -178,7 +184,7 @@ Sema::~Sema() {
if (PackContext) FreePackedContext();
if (VisContext) FreeVisContext();
delete TheTargetAttributesSema;
-
+ MSStructPragmaOn = false;
// Kill all the active scopes.
for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
delete FunctionScopes[I];
@@ -195,39 +201,58 @@ Sema::~Sema() {
ExternalSema->ForgetSema();
}
+ASTMutationListener *Sema::getASTMutationListener() const {
+ return getASTConsumer().GetASTMutationListener();
+}
+
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
/// If there is already an implicit cast, merge into the existing one.
/// The result is of the given category.
-void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
- CastKind Kind, ExprValueKind VK,
- const CXXCastPath *BasePath) {
- QualType ExprTy = Context.getCanonicalType(Expr->getType());
+ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
+ CastKind Kind, ExprValueKind VK,
+ const CXXCastPath *BasePath) {
+ QualType ExprTy = Context.getCanonicalType(E->getType());
QualType TypeTy = Context.getCanonicalType(Ty);
if (ExprTy == TypeTy)
- return;
+ return Owned(E);
// If this is a derived-to-base cast to a through a virtual base, we
// need a vtable.
if (Kind == CK_DerivedToBase &&
BasePathInvolvesVirtualBase(*BasePath)) {
- QualType T = Expr->getType();
+ QualType T = E->getType();
if (const PointerType *Pointer = T->getAs<PointerType>())
T = Pointer->getPointeeType();
if (const RecordType *RecordTy = T->getAs<RecordType>())
- MarkVTableUsed(Expr->getLocStart(),
+ MarkVTableUsed(E->getLocStart(),
cast<CXXRecordDecl>(RecordTy->getDecl()));
}
- if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
+ if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
ImpCast->setType(Ty);
ImpCast->setValueKind(VK);
- return;
+ return Owned(E);
}
}
- Expr = ImplicitCastExpr::Create(Context, Ty, Kind, Expr, BasePath, VK);
+ return Owned(ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK));
+}
+
+/// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
+/// to the conversion from scalar type ScalarTy to the Boolean type.
+CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
+ switch (ScalarTy->getScalarTypeKind()) {
+ case Type::STK_Bool: return CK_NoOp;
+ case Type::STK_Pointer: return CK_PointerToBoolean;
+ case Type::STK_MemberPointer: return CK_MemberPointerToBoolean;
+ case Type::STK_Integral: return CK_IntegralToBoolean;
+ case Type::STK_Floating: return CK_FloatingToBoolean;
+ case Type::STK_IntegralComplex: return CK_IntegralComplexToBoolean;
+ case Type::STK_FloatingComplex: return CK_FloatingComplexToBoolean;
+ }
+ return CK_Invalid;
}
ExprValueKind Sema::CastCategory(Expr *E) {
@@ -352,22 +377,30 @@ void Sema::ActOnEndOfTranslationUnit() {
}
}
- // If DefinedUsedVTables ends up marking any virtual member functions it
- // might lead to more pending template instantiations, which we then need
- // to instantiate.
- DefineUsedVTables();
-
- // C++: Perform implicit template instantiations.
- //
- // FIXME: When we perform these implicit instantiations, we do not
- // carefully keep track of the point of instantiation (C++ [temp.point]).
- // This means that name lookup that occurs within the template
- // instantiation will always happen at the end of the translation unit,
- // so it will find some names that should not be found. Although this is
- // common behavior for C++ compilers, it is technically wrong. In the
- // future, we either need to be able to filter the results of name lookup
- // or we need to perform template instantiations earlier.
- PerformPendingInstantiations();
+ bool SomethingChanged;
+ do {
+ SomethingChanged = false;
+
+ // If DefinedUsedVTables ends up marking any virtual member functions it
+ // might lead to more pending template instantiations, which we then need
+ // to instantiate.
+ if (DefineUsedVTables())
+ SomethingChanged = true;
+
+ // C++: Perform implicit template instantiations.
+ //
+ // FIXME: When we perform these implicit instantiations, we do not
+ // carefully keep track of the point of instantiation (C++ [temp.point]).
+ // This means that name lookup that occurs within the template
+ // instantiation will always happen at the end of the translation unit,
+ // so it will find some names that should not be found. Although this is
+ // common behavior for C++ compilers, it is technically wrong. In the
+ // future, we either need to be able to filter the results of name lookup
+ // or we need to perform template instantiations earlier.
+ if (PerformPendingInstantiations())
+ SomethingChanged = true;
+
+ } while (SomethingChanged);
}
// Remove file scoped decls that turned out to be used.
@@ -451,16 +484,32 @@ void Sema::ActOnEndOfTranslationUnit() {
const FunctionDecl *DiagD;
if (!FD->hasBody(DiagD))
DiagD = FD;
- Diag(DiagD->getLocation(),
- isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function
- : diag::warn_unused_function)
- << DiagD->getDeclName();
+ if (DiagD->isDeleted())
+ continue; // Deleted functions are supposed to be unused.
+ if (DiagD->isReferenced()) {
+ if (isa<CXXMethodDecl>(DiagD))
+ Diag(DiagD->getLocation(), diag::warn_unneeded_member_function)
+ << DiagD->getDeclName();
+ else
+ Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
+ << /*function*/0 << DiagD->getDeclName();
+ } else {
+ Diag(DiagD->getLocation(),
+ isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function
+ : diag::warn_unused_function)
+ << DiagD->getDeclName();
+ }
} else {
const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
if (!DiagD)
DiagD = cast<VarDecl>(*I);
- Diag(DiagD->getLocation(), diag::warn_unused_variable)
- << DiagD->getDeclName();
+ if (DiagD->isReferenced()) {
+ Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
+ << /*variable*/1 << DiagD->getDeclName();
+ } else {
+ Diag(DiagD->getLocation(), diag::warn_unused_variable)
+ << DiagD->getDeclName();
+ }
}
}
@@ -585,6 +634,27 @@ Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) {
return Builder;
}
+/// \brief Looks through the macro-instantiation chain for the given
+/// location, looking for a macro instantiation with the given name.
+/// If one is found, returns true and sets the location to that
+/// instantiation loc.
+bool Sema::findMacroSpelling(SourceLocation &locref, llvm::StringRef name) {
+ SourceLocation loc = locref;
+ if (!loc.isMacroID()) return false;
+
+ // There's no good way right now to look at the intermediate
+ // instantiations, so just jump to the instantiation location.
+ loc = getSourceManager().getInstantiationLoc(loc);
+
+ // If that's written with the name, stop here.
+ llvm::SmallVector<char, 16> buffer;
+ if (getPreprocessor().getSpelling(loc, buffer) == name) {
+ locref = loc;
+ return true;
+ }
+ return false;
+}
+
/// \brief Determines the active Scope associated with the given declaration
/// context.
///
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
index 4f9bf1c..411d424 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
@@ -1011,16 +1011,16 @@ static void DiagnoseAccessPath(Sema &S,
// Find an original declaration.
while (D->isOutOfLine()) {
NamedDecl *PrevDecl = 0;
- if (isa<VarDecl>(D))
- PrevDecl = cast<VarDecl>(D)->getPreviousDeclaration();
- else if (isa<FunctionDecl>(D))
- PrevDecl = cast<FunctionDecl>(D)->getPreviousDeclaration();
- else if (isa<TypedefDecl>(D))
- PrevDecl = cast<TypedefDecl>(D)->getPreviousDeclaration();
- else if (isa<TagDecl>(D)) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(D))
+ PrevDecl = VD->getPreviousDeclaration();
+ else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ PrevDecl = FD->getPreviousDeclaration();
+ else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D))
+ PrevDecl = TND->getPreviousDeclaration();
+ else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
break;
- PrevDecl = cast<TagDecl>(D)->getPreviousDeclaration();
+ PrevDecl = TD->getPreviousDeclaration();
}
if (!PrevDecl) break;
D = PrevDecl;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
index 794b0b1..53dd297 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
@@ -129,6 +129,12 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
}
}
+void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
+ if (!MSStructPragmaOn)
+ return;
+ RD->addAttr(::new (Context) MsStructAttr(SourceLocation(), Context));
+}
+
void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
SourceLocation PragmaLoc,
SourceLocation KindLoc) {
@@ -263,6 +269,10 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
}
}
+void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
+ MSStructPragmaOn = (Kind == PMSST_ON);
+}
+
void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
SourceLocation PragmaLoc) {
@@ -297,7 +307,7 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) {
if (!VisContext)
return;
- if (D->hasAttr<VisibilityAttr>())
+ if (isa<NamedDecl>(D) && cast<NamedDecl>(D)->getExplicitVisibility())
return;
VisStack *Stack = static_cast<VisStack*>(VisContext);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp
index 506d261..ed54f0f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp
@@ -42,21 +42,21 @@ enum CastType {
-static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+static void CheckConstCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
ExprValueKind &VK,
const SourceRange &OpRange,
const SourceRange &DestRange);
-static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+static void CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
ExprValueKind &VK,
const SourceRange &OpRange,
const SourceRange &DestRange,
CastKind &Kind);
-static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+static void CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
ExprValueKind &VK,
const SourceRange &OpRange,
CastKind &Kind,
CXXCastPath &BasePath);
-static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+static void CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
ExprValueKind &VK,
const SourceRange &OpRange,
const SourceRange &DestRange,
@@ -100,7 +100,7 @@ static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
QualType OrigDestType, unsigned &msg,
CastKind &Kind,
CXXCastPath &BasePath);
-static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr,
+static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr,
QualType SrcType,
QualType DestType,bool CStyle,
const SourceRange &OpRange,
@@ -108,12 +108,12 @@ static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr,
CastKind &Kind,
CXXCastPath &BasePath);
-static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr,
+static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
CastKind &Kind);
-static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
+static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
@@ -121,24 +121,13 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
CXXCastPath &BasePath);
static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
bool CStyle, unsigned &msg);
-static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
+static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
CastKind &Kind);
-static ExprResult
-ResolveAndFixSingleFunctionTemplateSpecialization(
- Sema &Self, Expr *SrcExpr,
- bool DoFunctionPointerConverion = false,
- bool Complain = false,
- const SourceRange& OpRangeForComplaining = SourceRange(),
- QualType DestTypeForComplaining = QualType(),
- unsigned DiagIDForComplaining = 0);
-
-
-
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
ExprResult
Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
@@ -159,8 +148,9 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
ExprResult
Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
- TypeSourceInfo *DestTInfo, Expr *Ex,
+ TypeSourceInfo *DestTInfo, Expr *E,
SourceRange AngleBrackets, SourceRange Parens) {
+ ExprResult Ex = Owned(E);
QualType DestType = DestTInfo->getType();
SourceRange OpRange(OpLoc, Parens.getEnd());
@@ -168,11 +158,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
// If the type is dependent, we won't do the semantic analysis now.
// FIXME: should we check this in a more fine-grained manner?
- bool TypeDependent = DestType->isDependentType() || Ex->isTypeDependent();
-
- if (Ex->isBoundMemberFunction(Context))
- Diag(Ex->getLocStart(), diag::err_invalid_use_of_bound_member_func)
- << Ex->getSourceRange();
+ bool TypeDependent = DestType->isDependentType() || Ex.get()->isTypeDependent();
ExprValueKind VK = VK_RValue;
if (TypeDependent)
@@ -182,42 +168,54 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
default: llvm_unreachable("Unknown C++ cast!");
case tok::kw_const_cast:
- if (!TypeDependent)
+ if (!TypeDependent) {
CheckConstCast(*this, Ex, DestType, VK, OpRange, DestRange);
+ if (Ex.isInvalid())
+ return ExprError();
+ }
return Owned(CXXConstCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- VK, Ex, DestTInfo, OpLoc,
+ VK, Ex.take(), DestTInfo, OpLoc,
Parens.getEnd()));
case tok::kw_dynamic_cast: {
CastKind Kind = CK_Dependent;
CXXCastPath BasePath;
- if (!TypeDependent)
+ if (!TypeDependent) {
CheckDynamicCast(*this, Ex, DestType, VK, OpRange, DestRange,
Kind, BasePath);
+ if (Ex.isInvalid())
+ return ExprError();
+ }
return Owned(CXXDynamicCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- VK, Kind, Ex, &BasePath, DestTInfo,
+ VK, Kind, Ex.take(), &BasePath, DestTInfo,
OpLoc, Parens.getEnd()));
}
case tok::kw_reinterpret_cast: {
CastKind Kind = CK_Dependent;
- if (!TypeDependent)
+ if (!TypeDependent) {
CheckReinterpretCast(*this, Ex, DestType, VK, OpRange, DestRange, Kind);
+ if (Ex.isInvalid())
+ return ExprError();
+ }
return Owned(CXXReinterpretCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- VK, Kind, Ex, 0,
+ VK, Kind, Ex.take(), 0,
DestTInfo, OpLoc, Parens.getEnd()));
}
case tok::kw_static_cast: {
CastKind Kind = CK_Dependent;
CXXCastPath BasePath;
- if (!TypeDependent)
+ if (!TypeDependent) {
CheckStaticCast(*this, Ex, DestType, VK, OpRange, Kind, BasePath);
+ if (Ex.isInvalid())
+ return ExprError();
+ }
return Owned(CXXStaticCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- VK, Kind, Ex, &BasePath,
+ VK, Kind, Ex.take(), &BasePath,
DestTInfo, OpLoc, Parens.getEnd()));
}
}
@@ -303,6 +301,11 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
/// Diagnose a failed cast.
static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
SourceRange opRange, Expr *src, QualType destType) {
+ if (src->getType() == S.Context.BoundMemberTy) {
+ (void) S.CheckPlaceholderExpr(src); // will always fail
+ return;
+ }
+
if (msg == diag::err_bad_cxx_cast_generic &&
tryDiagnoseOverloadedCast(S, castType, opRange, src, destType))
return;
@@ -388,15 +391,17 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
UnwrappedDestType = Self.Context.getCanonicalType(DestType);
llvm::SmallVector<Qualifiers, 8> cv1, cv2;
- // Find the qualifications.
+ // Find the qualifiers. We only care about cvr-qualifiers for the
+ // purpose of this check, because other qualifiers (address spaces,
+ // Objective-C GC, etc.) are part of the type's identity.
while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
Qualifiers SrcQuals;
Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals);
- cv1.push_back(SrcQuals);
+ cv1.push_back(Qualifiers::fromCVRMask(SrcQuals.getCVRQualifiers()));
Qualifiers DestQuals;
Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals);
- cv2.push_back(DestQuals);
+ cv2.push_back(Qualifiers::fromCVRMask(DestQuals.getCVRQualifiers()));
}
if (cv1.empty())
return false;
@@ -424,11 +429,11 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
/// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime-
/// checked downcasts in class hierarchies.
static void
-CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
ExprValueKind &VK, const SourceRange &OpRange,
const SourceRange &DestRange, CastKind &Kind,
CXXCastPath &BasePath) {
- QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType();
+ QualType OrigDestType = DestType, OrigSrcType = SrcExpr.get()->getType();
DestType = Self.Context.getCanonicalType(DestType);
// C++ 5.2.7p1: T shall be a pointer or reference to a complete class type,
@@ -475,11 +480,11 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
SrcPointee = SrcPointer->getPointeeType();
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr)
- << OrigSrcType << SrcExpr->getSourceRange();
+ << OrigSrcType << SrcExpr.get()->getSourceRange();
return;
}
} else if (DestReference->isLValueReferenceType()) {
- if (!SrcExpr->isLValue()) {
+ if (!SrcExpr.get()->isLValue()) {
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
<< CT_Dynamic << OrigSrcType << OrigDestType << OpRange;
}
@@ -492,11 +497,11 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
if (SrcRecord) {
if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee,
Self.PDiag(diag::err_bad_dynamic_cast_incomplete)
- << SrcExpr->getSourceRange()))
+ << SrcExpr.get()->getSourceRange()))
return;
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
- << SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange();
+ << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange();
return;
}
@@ -508,7 +513,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
// C++ 5.2.7p1: The dynamic_cast operator shall not cast away constness.
if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) {
- Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away)
+ Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away)
<< CT_Dynamic << OrigSrcType << OrigDestType << OpRange;
return;
}
@@ -543,7 +548,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
assert(SrcDecl && "Definition missing");
if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic)
- << SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange();
+ << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange();
}
Self.MarkVTableUsed(OpRange.getBegin(),
cast<CXXRecordDecl>(SrcRecord->getDecl()));
@@ -558,17 +563,20 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
/// const char *str = "literal";
/// legacy_function(const_cast\<char*\>(str));
void
-CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, ExprValueKind &VK,
+CheckConstCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK,
const SourceRange &OpRange, const SourceRange &DestRange) {
VK = Expr::getValueKindForType(DestType);
- if (VK == VK_RValue)
- Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
+ if (VK == VK_RValue) {
+ SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+ if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
+ return;
+ }
unsigned msg = diag::err_bad_cxx_cast_generic;
- if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success
+ if (TryConstCast(Self, SrcExpr.get(), DestType, /*CStyle*/false, msg) != TC_Success
&& msg != 0)
Self.Diag(OpRange.getBegin(), msg) << CT_Const
- << SrcExpr->getType() << DestType << OpRange;
+ << SrcExpr.get()->getType() << DestType << OpRange;
}
/// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is
@@ -577,27 +585,32 @@ CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, ExprValueKind &VK,
/// like this:
/// char *bytes = reinterpret_cast\<char*\>(int_ptr);
void
-CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
ExprValueKind &VK, const SourceRange &OpRange,
const SourceRange &DestRange, CastKind &Kind) {
VK = Expr::getValueKindForType(DestType);
- if (VK == VK_RValue)
- Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
+ if (VK == VK_RValue) {
+ SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+ if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
+ return;
+ }
unsigned msg = diag::err_bad_cxx_cast_generic;
if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange,
msg, Kind)
!= TC_Success && msg != 0)
{
- if (SrcExpr->getType() == Self.Context.OverloadTy) {
+ if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
+ return;
+ if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
//FIXME: &f<int>; is overloaded and resolvable
Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload)
- << OverloadExpr::find(SrcExpr).Expression->getName()
+ << OverloadExpr::find(SrcExpr.get()).Expression->getName()
<< DestType << OpRange;
- Self.NoteAllOverloadCandidates(SrcExpr);
+ Self.NoteAllOverloadCandidates(SrcExpr.get());
} else {
- diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr, DestType);
+ diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), DestType);
}
}
}
@@ -607,23 +620,25 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
/// Refer to C++ 5.2.9 for details. Static casts are mostly used for making
/// implicit conversions explicit and getting rid of data loss warnings.
void
-CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
ExprValueKind &VK, const SourceRange &OpRange,
CastKind &Kind, CXXCastPath &BasePath) {
// This test is outside everything else because it's the only case where
// a non-lvalue-reference target type does not lead to decay.
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
if (DestType->isVoidType()) {
- Self.IgnoredValueConversions(SrcExpr);
- if (SrcExpr->getType() == Self.Context.OverloadTy) {
+ SrcExpr = Self.IgnoredValueConversions(SrcExpr.take());
+ if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
+ return;
+ if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
ExprResult SingleFunctionExpression =
- ResolveAndFixSingleFunctionTemplateSpecialization(Self, SrcExpr,
+ Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr.get(),
false, // Decay Function to ptr
true, // Complain
OpRange, DestType, diag::err_bad_static_cast_overload);
if (SingleFunctionExpression.isUsable())
{
- SrcExpr = SingleFunctionExpression.release();
+ SrcExpr = SingleFunctionExpression;
Kind = CK_ToVoid;
}
}
@@ -633,29 +648,35 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
}
VK = Expr::getValueKindForType(DestType);
- if (VK == VK_RValue && !DestType->isRecordType())
- Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
+ if (VK == VK_RValue && !DestType->isRecordType()) {
+ SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+ if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
+ return;
+ }
unsigned msg = diag::err_bad_cxx_cast_generic;
if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
Kind, BasePath) != TC_Success && msg != 0) {
- if (SrcExpr->getType() == Self.Context.OverloadTy) {
- OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
+ if (SrcExpr.isInvalid())
+ return;
+ if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
+ OverloadExpr* oe = OverloadExpr::find(SrcExpr.get()).Expression;
Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload)
- << oe->getName() << DestType << OpRange << oe->getQualifierRange();
- Self.NoteAllOverloadCandidates(SrcExpr);
+ << oe->getName() << DestType << OpRange
+ << oe->getQualifierLoc().getSourceRange();
+ Self.NoteAllOverloadCandidates(SrcExpr.get());
} else {
- diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr, DestType);
+ diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType);
}
}
else if (Kind == CK_BitCast)
- Self.CheckCastAlign(SrcExpr, DestType, OpRange);
+ Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
}
/// TryStaticCast - Check if a static cast can be performed, and do so if
/// possible. If @p CStyle, ignore access restrictions on hierarchy casting
/// and casting away constness.
-static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
+static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange, unsigned &msg,
CastKind &Kind,
@@ -680,7 +701,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
// C++ 5.2.9p5, reference downcast.
// See the function for details.
// DR 427 specifies that this is to be applied before paragraph 2.
- tcr = TryStaticReferenceDowncast(Self, SrcExpr, DestType, CStyle, OpRange,
+ tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle, OpRange,
msg, Kind, BasePath);
if (tcr != TC_NotApplicable)
return tcr;
@@ -688,7 +709,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
// C++0x [expr.static.cast]p3:
// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
// T2" if "cv2 T2" is reference-compatible with "cv1 T1".
- tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, CStyle, Kind, BasePath,
+ tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind, BasePath,
msg);
if (tcr != TC_NotApplicable)
return tcr;
@@ -697,6 +718,8 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
// [...] if the declaration "T t(e);" is well-formed, [...].
tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CStyle, OpRange, msg,
Kind);
+ if (SrcExpr.isInvalid())
+ return TC_Failed;
if (tcr != TC_NotApplicable)
return tcr;
@@ -708,7 +731,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
// In the CStyle case, the earlier attempt to const_cast should have taken
// care of reverse qualification conversions.
- QualType SrcType = Self.Context.getCanonicalType(SrcExpr->getType());
+ QualType SrcType = Self.Context.getCanonicalType(SrcExpr.get()->getType());
// C++0x 5.2.9p9: A value of a scoped enumeration type can be explicitly
// converted to an integral type. [...] A value of a scoped enumeration type
@@ -772,7 +795,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
// This is definitely the intended conversion, but it might fail due
// to a const violation.
if (!CStyle && !DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) {
- msg = diag::err_bad_cxx_cast_const_away;
+ msg = diag::err_bad_cxx_cast_qualifiers_away;
return TC_Failed;
}
Kind = CK_BitCast;
@@ -963,7 +986,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
// Must preserve cv, as always, unless we're in C-style mode.
if (!CStyle && !DestType.isAtLeastAsQualifiedAs(SrcType)) {
- msg = diag::err_bad_cxx_cast_const_away;
+ msg = diag::err_bad_cxx_cast_qualifiers_away;
return TC_Failed;
}
@@ -1038,7 +1061,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
/// where B is a base class of D [...].
///
TryCastResult
-TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
+TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg, CastKind &Kind,
@@ -1049,9 +1072,9 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
bool WasOverloadedFunction = false;
DeclAccessPair FoundOverload;
- if (SrcExpr->getType() == Self.Context.OverloadTy) {
+ if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
if (FunctionDecl *Fn
- = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false,
+ = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false,
FoundOverload)) {
CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
SrcType = Self.Context.getMemberPointerType(Fn->getType(),
@@ -1122,7 +1145,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
if (WasOverloadedFunction) {
// Resolve the address of the overloaded function again, this time
// allowing complaints if something goes wrong.
- FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr,
+ FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(),
DestType,
true,
FoundOverload);
@@ -1132,7 +1155,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
}
SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn);
- if (!SrcExpr) {
+ if (!SrcExpr.isUsable()) {
msg = 0;
return TC_Failed;
}
@@ -1149,7 +1172,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
/// An expression e can be explicitly converted to a type T using a
/// @c static_cast if the declaration "T t(e);" is well-formed [...].
TryCastResult
-TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
bool CStyle, const SourceRange &OpRange, unsigned &msg,
CastKind &Kind) {
if (DestType->isRecordType()) {
@@ -1163,7 +1186,8 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
InitializationKind InitKind
= InitializationKind::CreateCast(/*FIXME:*/OpRange, CStyle);
- InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExpr, 1);
+ Expr *SrcExprRaw = SrcExpr.get();
+ InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExprRaw, 1);
// At this point of CheckStaticCast, if the destination is a reference,
// or the expression is an overload expression this has to work.
@@ -1176,7 +1200,7 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
return TC_NotApplicable;
ExprResult Result
- = InitSeq.Perform(Self, Entity, InitKind, MultiExprArg(Self, &SrcExpr, 1));
+ = InitSeq.Perform(Self, Entity, InitKind, MultiExprArg(Self, &SrcExprRaw, 1));
if (Result.isInvalid()) {
msg = 0;
return TC_Failed;
@@ -1187,7 +1211,7 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
else
Kind = CK_NoOp;
- SrcExpr = Result.takeAs<Expr>();
+ SrcExpr = move(Result);
return TC_Success;
}
@@ -1240,16 +1264,21 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
// Unwrap the pointers. Ignore qualifiers. Terminate early if the types are
// completely equal.
- // FIXME: const_cast should probably not be able to convert between pointers
- // to different address spaces.
// C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers
// in multi-level pointers may change, but the level count must be the same,
// as must be the final pointee type.
while (SrcType != DestType &&
Self.Context.UnwrapSimilarPointerTypes(SrcType, DestType)) {
- Qualifiers Quals;
- SrcType = Self.Context.getUnqualifiedArrayType(SrcType, Quals);
- DestType = Self.Context.getUnqualifiedArrayType(DestType, Quals);
+ Qualifiers SrcQuals, DestQuals;
+ SrcType = Self.Context.getUnqualifiedArrayType(SrcType, SrcQuals);
+ DestType = Self.Context.getUnqualifiedArrayType(DestType, DestQuals);
+
+ // const_cast is permitted to strip cvr-qualifiers, only. Make sure that
+ // the other qualifiers (e.g., address spaces) are identical.
+ SrcQuals.removeCVRQualifiers();
+ DestQuals.removeCVRQualifiers();
+ if (SrcQuals != DestQuals)
+ return TC_NotApplicable;
}
// Since we're dealing in canonical types, the remainder must be the same.
@@ -1259,43 +1288,8 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
return TC_Success;
}
-// A helper function to resolve and fix an overloaded expression that
-// can be resolved because it identifies a single function
-// template specialization
-// Last three arguments should only be supplied if Complain = true
-static ExprResult ResolveAndFixSingleFunctionTemplateSpecialization(
- Sema &Self, Expr *SrcExpr,
- bool DoFunctionPointerConverion,
- bool Complain,
- const SourceRange& OpRangeForComplaining,
- QualType DestTypeForComplaining,
- unsigned DiagIDForComplaining) {
- assert(SrcExpr->getType() == Self.Context.OverloadTy);
- DeclAccessPair Found;
- Expr* SingleFunctionExpression = 0;
- if (FunctionDecl* Fn = Self.ResolveSingleFunctionTemplateSpecialization(
- SrcExpr, false, // false -> Complain
- &Found)) {
- if (!Self.DiagnoseUseOfDecl(Fn, SrcExpr->getSourceRange().getBegin())) {
- // mark the expression as resolved to Fn
- SingleFunctionExpression = Self.FixOverloadedFunctionReference(SrcExpr,
- Found, Fn);
-
- if (DoFunctionPointerConverion)
- Self.DefaultFunctionArrayLvalueConversion(SingleFunctionExpression);
- }
- }
- if (!SingleFunctionExpression && Complain) {
- OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
- Self.Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
- << oe->getName() << DestTypeForComplaining << OpRangeForComplaining
- << oe->getQualifierRange();
- Self.NoteAllOverloadCandidates(SrcExpr);
- }
- return SingleFunctionExpression;
-}
-static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
+static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
@@ -1303,19 +1297,19 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
bool IsLValueCast = false;
DestType = Self.Context.getCanonicalType(DestType);
- QualType SrcType = SrcExpr->getType();
+ QualType SrcType = SrcExpr.get()->getType();
// Is the source an overloaded name? (i.e. &foo)
// If so, reinterpret_cast can not help us here (13.4, p1, bullet 5) ...
if (SrcType == Self.Context.OverloadTy) {
// ... unless foo<int> resolves to an lvalue unambiguously
ExprResult SingleFunctionExpr =
- ResolveAndFixSingleFunctionTemplateSpecialization(Self, SrcExpr,
+ Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr.get(),
Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr
);
if (SingleFunctionExpr.isUsable()) {
- SrcExpr = SingleFunctionExpr.release();
- SrcType = SrcExpr->getType();
+ SrcExpr = move(SingleFunctionExpr);
+ SrcType = SrcExpr.get()->getType();
}
else
return TC_NotApplicable;
@@ -1323,7 +1317,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) {
bool LValue = DestTypeTmp->isLValueReferenceType();
- if (LValue && !SrcExpr->isLValue()) {
+ if (LValue && !SrcExpr.get()->isLValue()) {
// Cannot cast non-lvalue to lvalue reference type. See the similar
// comment in const_cast.
msg = diag::err_bad_cxx_cast_rvalue;
@@ -1333,6 +1327,23 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
// C++ 5.2.10p10: [...] a reference cast reinterpret_cast<T&>(x) has the
// same effect as the conversion *reinterpret_cast<T*>(&x) with the
// built-in & and * operators.
+
+ const char *inappropriate = 0;
+ switch (SrcExpr.get()->getObjectKind()) {
+ case OK_Ordinary:
+ break;
+ case OK_BitField: inappropriate = "bit-field"; break;
+ case OK_VectorComponent: inappropriate = "vector element"; break;
+ case OK_ObjCProperty: inappropriate = "property expression"; break;
+ }
+ if (inappropriate) {
+ Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_reference)
+ << inappropriate << DestType
+ << OpRange << SrcExpr.get()->getSourceRange();
+ msg = 0; SrcExpr = ExprError();
+ return TC_NotApplicable;
+ }
+
// This code does this transformation for the checked types.
DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
SrcType = Self.Context.getPointerType(SrcType);
@@ -1359,7 +1370,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
// A reinterpret_cast followed by a const_cast can, though, so in C-style,
// we accept it.
if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) {
- msg = diag::err_bad_cxx_cast_const_away;
+ msg = diag::err_bad_cxx_cast_qualifiers_away;
return TC_Failed;
}
@@ -1472,7 +1483,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
// C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness.
// The C-style cast operator can.
if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) {
- msg = diag::err_bad_cxx_cast_const_away;
+ msg = diag::err_bad_cxx_cast_qualifiers_away;
return TC_Failed;
}
@@ -1525,39 +1536,39 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
return TC_Success;
}
-bool
+ExprResult
Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
- Expr *&CastExpr, CastKind &Kind,
+ Expr *CastExpr, CastKind &Kind,
CXXCastPath &BasePath,
bool FunctionalStyle) {
- if (CastExpr->isBoundMemberFunction(Context))
- return Diag(CastExpr->getLocStart(),
- diag::err_invalid_use_of_bound_member_func)
- << CastExpr->getSourceRange();
-
// This test is outside everything else because it's the only case where
// a non-lvalue-reference target type does not lead to decay.
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
if (CastTy->isVoidType()) {
- IgnoredValueConversions(CastExpr);
- bool ret = false; // false is 'able to convert'
+ Kind = CK_ToVoid;
+
+ ExprResult CastExprRes = IgnoredValueConversions(CastExpr);
+ if (CastExprRes.isInvalid())
+ return ExprError();
+ CastExpr = CastExprRes.take();
+
+ if (CastExpr->getType() == Context.BoundMemberTy)
+ return CheckPlaceholderExpr(CastExpr); // will always fail
+
if (CastExpr->getType() == Context.OverloadTy) {
ExprResult SingleFunctionExpr =
- ResolveAndFixSingleFunctionTemplateSpecialization(*this,
- CastExpr,
- /* Decay Function to ptr */ false,
- /* Complain */ true,
- R, CastTy, diag::err_bad_cstyle_cast_overload);
- if (SingleFunctionExpr.isUsable()) {
- CastExpr = SingleFunctionExpr.release();
- Kind = CK_ToVoid;
- }
- else
- ret = true;
+ ResolveAndFixSingleFunctionTemplateSpecialization(
+ CastExpr, /* Decay Function to ptr */ false,
+ /* Complain */ true, R, CastTy,
+ diag::err_bad_cstyle_cast_overload);
+ if (SingleFunctionExpr.isInvalid())
+ return ExprError();
+ CastExpr = SingleFunctionExpr.take();
}
- else
- Kind = CK_ToVoid;
- return ret;
+
+ assert(!CastExpr->getType()->isPlaceholderType());
+
+ return Owned(CastExpr);
}
// Make sure we determine the value kind before we bail out for
@@ -1567,11 +1578,24 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
// If the type is dependent, we won't do any other semantic analysis now.
if (CastTy->isDependentType() || CastExpr->isTypeDependent()) {
Kind = CK_Dependent;
- return false;
+ return Owned(CastExpr);
+ }
+
+ if (VK == VK_RValue && !CastTy->isRecordType()) {
+ ExprResult CastExprRes = DefaultFunctionArrayLvalueConversion(CastExpr);
+ if (CastExprRes.isInvalid())
+ return ExprError();
+ CastExpr = CastExprRes.take();
}
- if (VK == VK_RValue && !CastTy->isRecordType())
- DefaultFunctionArrayLvalueConversion(CastExpr);
+ // AltiVec vector initialization with a single literal.
+ if (const VectorType *vecTy = CastTy->getAs<VectorType>())
+ if (vecTy->getVectorKind() == VectorType::AltiVecVector
+ && (CastExpr->getType()->isIntegerType()
+ || CastExpr->getType()->isFloatingType())) {
+ Kind = CK_VectorSplat;
+ return Owned(CastExpr);
+ }
// C++ [expr.cast]p5: The conversions performed by
// - a const_cast,
@@ -1592,25 +1616,32 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
if (tcr == TC_NotApplicable) {
// ... or if that is not possible, a static_cast, ignoring const, ...
- tcr = TryStaticCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg, Kind,
- BasePath);
+ ExprResult CastExprRes = Owned(CastExpr);
+ tcr = TryStaticCast(*this, CastExprRes, CastTy, /*CStyle*/true, R, msg,
+ Kind, BasePath);
+ if (CastExprRes.isInvalid())
+ return ExprError();
+ CastExpr = CastExprRes.take();
if (tcr == TC_NotApplicable) {
// ... and finally a reinterpret_cast, ignoring const.
- tcr = TryReinterpretCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg,
- Kind);
+ CastExprRes = Owned(CastExpr);
+ tcr = TryReinterpretCast(*this, CastExprRes, CastTy, /*CStyle*/true, R,
+ msg, Kind);
+ if (CastExprRes.isInvalid())
+ return ExprError();
+ CastExpr = CastExprRes.take();
}
}
if (tcr != TC_Success && msg != 0) {
if (CastExpr->getType() == Context.OverloadTy) {
DeclAccessPair Found;
- FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(CastExpr,
+ FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(CastExpr,
CastTy,
/* Complain */ true,
Found);
- assert(!Fn
- && "cast failed but able to resolve overload expression!!");
+ assert(!Fn && "cast failed but able to resolve overload expression!!");
(void)Fn;
} else {
@@ -1621,5 +1652,8 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
else if (Kind == CK_BitCast)
CheckCastAlign(CastExpr, CastTy, R);
- return tcr != TC_Success;
+ if (tcr != TC_Success)
+ return ExprError();
+
+ return Owned(CastExpr);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 7ad4b45..7049f6b 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -255,7 +255,7 @@ bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) {
QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
if (T->isDependentType())
return true;
- else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
+ else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
if (TD->getUnderlyingType()->isRecordType() ||
(Context.getLangOptions().CPlusPlus0x &&
TD->getUnderlyingType()->isEnumeralType()))
@@ -549,7 +549,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
} else if (isa<RecordDecl>(SD)) {
RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T);
RecordTL.setNameLoc(IdentifierLoc);
- } else if (isa<TypedefDecl>(SD)) {
+ } else if (isa<TypedefNameDecl>(SD)) {
TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T);
TypedefTL.setNameLoc(IdentifierLoc);
} else if (isa<EnumDecl>(SD)) {
@@ -641,20 +641,87 @@ bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
}
bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
- ParsedType Type,
+ SourceLocation TemplateLoc,
+ CXXScopeSpec &SS,
+ TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation RAngleLoc,
SourceLocation CCLoc,
- CXXScopeSpec &SS) {
+ bool EnteringContext) {
if (SS.isInvalid())
return true;
- TypeSourceInfo *TSInfo;
- QualType T = GetTypeFromParser(Type, &TSInfo);
+ // Translate the parser's template argument list in our AST format.
+ TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+ translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+ if (DependentTemplateName *DTN = Template.get().getAsDependentTemplateName()){
+ // Handle a dependent template specialization for which we cannot resolve
+ // the template name.
+ assert(DTN->getQualifier()
+ == static_cast<NestedNameSpecifier*>(SS.getScopeRep()));
+ QualType T = Context.getDependentTemplateSpecializationType(ETK_None,
+ DTN->getQualifier(),
+ DTN->getIdentifier(),
+ TemplateArgs);
+
+ // Create source-location information for this type.
+ TypeLocBuilder Builder;
+ DependentTemplateSpecializationTypeLoc SpecTL
+ = Builder.push<DependentTemplateSpecializationTypeLoc>(T);
+ SpecTL.setLAngleLoc(LAngleLoc);
+ SpecTL.setRAngleLoc(RAngleLoc);
+ SpecTL.setKeywordLoc(SourceLocation());
+ SpecTL.setNameLoc(TemplateNameLoc);
+ SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+ SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+
+ SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T),
+ CCLoc);
+ return false;
+ }
+
+
+ if (Template.get().getAsOverloadedTemplate() ||
+ isa<FunctionTemplateDecl>(Template.get().getAsTemplateDecl())) {
+ SourceRange R(TemplateNameLoc, RAngleLoc);
+ if (SS.getRange().isValid())
+ R.setBegin(SS.getRange().getBegin());
+
+ Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier)
+ << Template.get() << R;
+ NoteAllFoundTemplates(Template.get());
+ return true;
+ }
+
+ // We were able to resolve the template name to an actual template.
+ // Build an appropriate nested-name-specifier.
+ QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc,
+ TemplateArgs);
if (T.isNull())
return true;
- assert(TSInfo && "Not TypeSourceInfo in nested-name-specifier?");
- // FIXME: location of the 'template' keyword?
- SS.Extend(Context, SourceLocation(), TSInfo->getTypeLoc(), CCLoc);
+ // FIXME: Template aliases will need to check the resulting type to make
+ // sure that it's either dependent or a tag type.
+
+ // Provide source-location information for the template specialization
+ // type.
+ TypeLocBuilder Builder;
+ TemplateSpecializationTypeLoc SpecTL
+ = Builder.push<TemplateSpecializationTypeLoc>(T);
+
+ SpecTL.setLAngleLoc(LAngleLoc);
+ SpecTL.setRAngleLoc(RAngleLoc);
+ SpecTL.setTemplateNameLoc(TemplateNameLoc);
+ for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+ SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+
+
+ SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T),
+ CCLoc);
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
index 3ffa748..5b645df 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -180,6 +180,7 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Builtin::BI__sync_bool_compare_and_swap:
case Builtin::BI__sync_lock_test_and_set:
case Builtin::BI__sync_lock_release:
+ case Builtin::BI__sync_swap:
return SemaBuiltinAtomicOverloaded(move(TheCallResult));
}
@@ -313,9 +314,14 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
for (specific_attr_iterator<NonNullAttr>
i = FDecl->specific_attr_begin<NonNullAttr>(),
e = FDecl->specific_attr_end<NonNullAttr>(); i != e; ++i) {
- CheckNonNullArguments(*i, TheCall);
+ CheckNonNullArguments(*i, TheCall->getArgs(),
+ TheCall->getCallee()->getLocStart());
}
+ // Memset handling
+ if (FnInfo->isStr("memset"))
+ CheckMemsetArguments(TheCall);
+
return false;
}
@@ -414,7 +420,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
BUILTIN_ROW(__sync_val_compare_and_swap),
BUILTIN_ROW(__sync_bool_compare_and_swap),
BUILTIN_ROW(__sync_lock_test_and_set),
- BUILTIN_ROW(__sync_lock_release)
+ BUILTIN_ROW(__sync_lock_release),
+ BUILTIN_ROW(__sync_swap)
};
#undef BUILTIN_ROW
@@ -467,6 +474,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
NumFixed = 0;
ResultType = Context.VoidTy;
break;
+ case Builtin::BI__sync_swap: BuiltinIndex = 14; break;
}
// Now that we know how many fixed arguments we expect, first check that we
@@ -491,14 +499,14 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
// deduce the types of the rest of the arguments accordingly. Walk
// the remaining arguments, converting them to the deduced value type.
for (unsigned i = 0; i != NumFixed; ++i) {
- Expr *Arg = TheCall->getArg(i+1);
+ ExprResult Arg = TheCall->getArg(i+1);
// If the argument is an implicit cast, then there was a promotion due to
// "...", just remove it now.
- if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg.get())) {
Arg = ICE->getSubExpr();
ICE->setSubExpr(0);
- TheCall->setArg(i+1, Arg);
+ TheCall->setArg(i+1, Arg.get());
}
// GCC does an implicit conversion to the pointer or integer ValType. This
@@ -506,7 +514,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
CastKind Kind = CK_Invalid;
ExprValueKind VK = VK_RValue;
CXXCastPath BasePath;
- if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, VK, BasePath))
+ Arg = CheckCastTypes(Arg.get()->getSourceRange(), ValType, Arg.take(), Kind, VK, BasePath);
+ if (Arg.isInvalid())
return ExprError();
// Okay, we have something that *can* be converted to the right type. Check
@@ -515,8 +524,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
// pass in 42. The 42 gets converted to char. This is even more strange
// for things like 45.123 -> char, etc.
// FIXME: Do this check.
- ImpCastExprToType(Arg, ValType, Kind, VK, &BasePath);
- TheCall->setArg(i+1, Arg);
+ Arg = ImpCastExprToType(Arg.take(), ValType, Kind, VK, &BasePath);
+ TheCall->setArg(i+1, Arg.get());
}
// Switch the DeclRefExpr to refer to the new decl.
@@ -525,9 +534,10 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
// Set the callee in the CallExpr.
// FIXME: This leaks the original parens and implicit casts.
- Expr *PromotedCall = DRE;
- UsualUnaryConversions(PromotedCall);
- TheCall->setCallee(PromotedCall);
+ ExprResult PromotedCall = UsualUnaryConversions(DRE);
+ if (PromotedCall.isInvalid())
+ return ExprError();
+ TheCall->setCallee(PromotedCall.take());
// Change the result type of the call to match the original value type. This
// is arbitrary, but the codegen for these builtins ins design to handle it
@@ -552,12 +562,6 @@ bool Sema::CheckObjCString(Expr *Arg) {
return true;
}
- size_t NulPos = Literal->getString().find('\0');
- if (NulPos != llvm::StringRef::npos) {
- Diag(getLocationOfStringLiteralByte(Literal, NulPos),
- diag::warn_cfstring_literal_contains_nul_character)
- << Arg->getSourceRange();
- }
if (Literal->containsNonAsciiOrNull()) {
llvm::StringRef String = Literal->getString();
unsigned NumBytes = String.size();
@@ -650,29 +654,31 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
<< SourceRange(TheCall->getArg(2)->getLocStart(),
(*(TheCall->arg_end()-1))->getLocEnd());
- Expr *OrigArg0 = TheCall->getArg(0);
- Expr *OrigArg1 = TheCall->getArg(1);
+ ExprResult OrigArg0 = TheCall->getArg(0);
+ ExprResult OrigArg1 = TheCall->getArg(1);
// Do standard promotions between the two arguments, returning their common
// type.
QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false);
+ if (OrigArg0.isInvalid() || OrigArg1.isInvalid())
+ return true;
// Make sure any conversions are pushed back into the call; this is
// type safe since unordered compare builtins are declared as "_Bool
// foo(...)".
- TheCall->setArg(0, OrigArg0);
- TheCall->setArg(1, OrigArg1);
+ TheCall->setArg(0, OrigArg0.get());
+ TheCall->setArg(1, OrigArg1.get());
- if (OrigArg0->isTypeDependent() || OrigArg1->isTypeDependent())
+ if (OrigArg0.get()->isTypeDependent() || OrigArg1.get()->isTypeDependent())
return false;
// If the common type isn't a real floating type, then the arguments were
// invalid for this operation.
if (!Res->isRealFloatingType())
- return Diag(OrigArg0->getLocStart(),
+ return Diag(OrigArg0.get()->getLocStart(),
diag::err_typecheck_call_invalid_ordered_compare)
- << OrigArg0->getType() << OrigArg1->getType()
- << SourceRange(OrigArg0->getLocStart(), OrigArg1->getLocEnd());
+ << OrigArg0.get()->getType() << OrigArg1.get()->getType()
+ << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd());
return false;
}
@@ -860,7 +866,7 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
/// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr,
/// int type). This simply type checks that type is one of the defined
/// constants (0-3).
-// For compatability check 0-3, llvm only handles 0 and 2.
+// For compatibility check 0-3, llvm only handles 0 and 2.
bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) {
llvm::APSInt Result;
@@ -903,6 +909,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
if (E->isTypeDependent() || E->isValueDependent())
return false;
+ E = E->IgnoreParens();
+
switch (E->getStmtClass()) {
case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass: {
@@ -925,11 +933,6 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
goto tryAgain;
}
- case Stmt::ParenExprClass: {
- E = cast<ParenExpr>(E)->getSubExpr();
- goto tryAgain;
- }
-
case Stmt::OpaqueValueExprClass:
if (const Expr *src = cast<OpaqueValueExpr>(E)->getSourceExpr()) {
E = src;
@@ -1036,15 +1039,15 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
void
Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
- const CallExpr *TheCall) {
+ const Expr * const *ExprArgs,
+ SourceLocation CallSiteLoc) {
for (NonNullAttr::args_iterator i = NonNull->args_begin(),
e = NonNull->args_end();
i != e; ++i) {
- const Expr *ArgExpr = TheCall->getArg(*i);
+ const Expr *ArgExpr = ExprArgs[*i];
if (ArgExpr->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNotNull))
- Diag(TheCall->getCallee()->getLocStart(), diag::warn_null_arg)
- << ArgExpr->getSourceRange();
+ Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
}
}
@@ -1218,10 +1221,12 @@ void CheckFormatHandler::HandleZeroPosition(const char *startPos,
}
void CheckFormatHandler::HandleNullChar(const char *nullCharacter) {
- // The presence of a null character is likely an error.
- S.Diag(getLocationOfByte(nullCharacter),
- diag::warn_printf_format_string_contains_null_char)
- << getFormatStringRange();
+ if (!IsObjCLiteral) {
+ // The presence of a null character is likely an error.
+ S.Diag(getLocationOfByte(nullCharacter),
+ diag::warn_printf_format_string_contains_null_char)
+ << getFormatStringRange();
+ }
}
const Expr *CheckFormatHandler::getDataArg(unsigned i) const {
@@ -1825,6 +1830,54 @@ void Sema::CheckFormatString(const StringLiteral *FExpr,
}
}
+//===--- CHECK: Standard memory functions ---------------------------------===//
+
+/// \brief Check for dangerous or invalid arguments to memset().
+///
+/// This issues warnings on known problematic or dangerous or unspecified
+/// arguments to the standard 'memset' function call.
+///
+/// \param Call The call expression to diagnose.
+void Sema::CheckMemsetArguments(const CallExpr *Call) {
+ // It is possible to have a non-standard definition of memset. Validate
+ // we have the proper number of arguments, and if not, abort further
+ // checking.
+ if (Call->getNumArgs() != 3)
+ return;
+
+ const Expr *Dest = Call->getArg(0)->IgnoreParenImpCasts();
+
+ // The type checking for this warning is moderately expensive, only do it
+ // when enabled.
+ if (getDiagnostics().getDiagnosticLevel(diag::warn_non_pod_memset,
+ Dest->getExprLoc()) ==
+ Diagnostic::Ignored)
+ return;
+
+ QualType DestTy = Dest->getType();
+ if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) {
+ QualType PointeeTy = DestPtrTy->getPointeeType();
+ if (PointeeTy->isVoidType())
+ return;
+
+ // Check the C++11 POD definition regardless of language mode; it is more
+ // relaxed than earlier definitions and we don't want spurrious warnings.
+ if (PointeeTy->isCXX11PODType())
+ return;
+
+ DiagRuntimeBehavior(
+ Dest->getExprLoc(), Dest,
+ PDiag(diag::warn_non_pod_memset)
+ << PointeeTy << Call->getCallee()->getSourceRange());
+
+ SourceRange ArgRange = Call->getArg(0)->getSourceRange();
+ DiagRuntimeBehavior(
+ Dest->getExprLoc(), Dest,
+ PDiag(diag::note_non_pod_memset_silence)
+ << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)"));
+ }
+}
+
//===--- CHECK: Return Address of Stack Variable --------------------------===//
static Expr *EvalVal(Expr *E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars);
@@ -1928,14 +1981,12 @@ static Expr *EvalAddr(Expr *E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars) {
E->getType()->isObjCQualifiedIdType()) &&
"EvalAddr only works on pointers");
+ E = E->IgnoreParens();
+
// Our "symbolic interpreter" is just a dispatch off the currently
// viewed AST node. We then recursively traverse the AST by calling
// EvalAddr and EvalVal appropriately.
switch (E->getStmtClass()) {
- case Stmt::ParenExprClass:
- // Ignore parentheses.
- return EvalAddr(cast<ParenExpr>(E)->getSubExpr(), refVars);
-
case Stmt::DeclRefExprClass: {
DeclRefExpr *DR = cast<DeclRefExpr>(E);
@@ -2065,6 +2116,8 @@ do {
// Our "symbolic interpreter" is just a dispatch off the currently
// viewed AST node. We then recursively traverse the AST by calling
// EvalAddr and EvalVal appropriately.
+
+ E = E->IgnoreParens();
switch (E->getStmtClass()) {
case Stmt::ImplicitCastExprClass: {
ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E);
@@ -2098,12 +2151,6 @@ do {
return NULL;
}
- case Stmt::ParenExprClass: {
- // Ignore parentheses.
- E = cast<ParenExpr>(E)->getSubExpr();
- continue;
- }
-
case Stmt::UnaryOperatorClass: {
// The only unary operator that make sense to handle here
// is Deref. All others don't resolve to a "name." This includes
@@ -2782,10 +2829,48 @@ void AnalyzeAssignment(Sema &S, BinaryOperator *E) {
}
/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
+void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T,
+ SourceLocation CContext, unsigned diag) {
+ S.Diag(E->getExprLoc(), diag)
+ << SourceType << T << E->getSourceRange() << SourceRange(CContext);
+}
+
+/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext,
unsigned diag) {
- S.Diag(E->getExprLoc(), diag)
- << E->getType() << T << E->getSourceRange() << SourceRange(CContext);
+ DiagnoseImpCast(S, E, E->getType(), T, CContext, diag);
+}
+
+/// Diagnose an implicit cast from a literal expression. Also attemps to supply
+/// fixit hints when the cast wouldn't lose information to simply write the
+/// expression with the expected type.
+void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T,
+ SourceLocation CContext) {
+ // Emit the primary warning first, then try to emit a fixit hint note if
+ // reasonable.
+ S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer)
+ << FL->getType() << T << FL->getSourceRange() << SourceRange(CContext);
+
+ const llvm::APFloat &Value = FL->getValue();
+
+ // Don't attempt to fix PPC double double literals.
+ if (&Value.getSemantics() == &llvm::APFloat::PPCDoubleDouble)
+ return;
+
+ // Try to convert this exactly to an 64-bit integer. FIXME: It would be
+ // nice to support arbitrarily large integers here.
+ bool isExact = false;
+ uint64_t IntegerPart;
+ if (Value.convertToInteger(&IntegerPart, 64, /*isSigned=*/true,
+ llvm::APFloat::rmTowardZero, &isExact)
+ != llvm::APFloat::opOK || !isExact)
+ return;
+
+ llvm::APInt IntegerValue(64, IntegerPart, /*isSigned=*/true);
+
+ std::string LiteralValue = IntegerValue.toString(10, /*isSigned=*/true);
+ S.Diag(FL->getExprLoc(), diag::note_fix_integral_float_as_integer)
+ << FixItHint::CreateReplacement(FL->getSourceRange(), LiteralValue);
}
std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) {
@@ -2797,6 +2882,11 @@ std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) {
return ValueInRange.toString(10);
}
+static bool isFromSystemMacro(Sema &S, SourceLocation loc) {
+ SourceManager &smgr = S.Context.getSourceManager();
+ return loc.isMacroID() && smgr.isInSystemHeader(smgr.getSpellingLoc(loc));
+}
+
void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
SourceLocation CC, bool *ICContext = 0) {
if (E->isTypeDependent() || E->isValueDependent()) return;
@@ -2806,11 +2896,12 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
if (Source == Target) return;
if (Target->isDependentType()) return;
- // If the conversion context location is invalid or instantiated
- // from a system macro, don't complain.
- if (CC.isInvalid() ||
- (CC.isMacroID() && S.Context.getSourceManager().isInSystemHeader(
- S.Context.getSourceManager().getSpellingLoc(CC))))
+ // If the conversion context location is invalid don't complain.
+ // We also don't want to emit a warning if the issue occurs from the
+ // instantiation of a system macro. The problem is that 'getSpellingLoc()'
+ // is slow, so we delay this check as long as possible. Once we detect
+ // we are in that scenario, we just return.
+ if (CC.isInvalid())
return;
// Never diagnose implicit casts to bool.
@@ -2819,8 +2910,11 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
// Strip vector types.
if (isa<VectorType>(Source)) {
- if (!isa<VectorType>(Target))
+ if (!isa<VectorType>(Target)) {
+ if (isFromSystemMacro(S, CC))
+ return;
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar);
+ }
Source = cast<VectorType>(Source)->getElementType().getTypePtr();
Target = cast<VectorType>(Target)->getElementType().getTypePtr();
@@ -2828,8 +2922,12 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
// Strip complex types.
if (isa<ComplexType>(Source)) {
- if (!isa<ComplexType>(Target))
+ if (!isa<ComplexType>(Target)) {
+ if (isFromSystemMacro(S, CC))
+ return;
+
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_complex_scalar);
+ }
Source = cast<ComplexType>(Source)->getElementType().getTypePtr();
Target = cast<ComplexType>(Target)->getElementType().getTypePtr();
@@ -2857,17 +2955,22 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
return;
}
+ if (isFromSystemMacro(S, CC))
+ return;
+
DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision);
}
return;
}
- // If the target is integral, always warn.
+ // If the target is integral, always warn.
if ((TargetBT && TargetBT->isInteger())) {
+ if (isFromSystemMacro(S, CC))
+ return;
+
Expr *InnerE = E->IgnoreParenImpCasts();
- if (FloatingLiteral *LiteralExpr = dyn_cast<FloatingLiteral>(InnerE)) {
- DiagnoseImpCast(S, LiteralExpr, T, CC,
- diag::warn_impcast_literal_float_to_integer);
+ if (FloatingLiteral *FL = dyn_cast<FloatingLiteral>(InnerE)) {
+ DiagnoseFloatingLiteralImpCast(S, FL, T, CC);
} else {
DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_integer);
}
@@ -2887,6 +2990,9 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
// TODO: this should happen for bitfield stores, too.
llvm::APSInt Value(32);
if (E->isIntegerConstantExpr(Value, S.Context)) {
+ if (isFromSystemMacro(S, CC))
+ return;
+
std::string PrettySourceValue = Value.toString(10);
std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);
@@ -2898,6 +3004,10 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
// People want to build with -Wshorten-64-to-32 and not -Wconversion
// and by god we'll let them.
+
+ if (isFromSystemMacro(S, CC))
+ return;
+
if (SourceRange.Width == 64 && TargetRange.Width == 32)
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32);
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision);
@@ -2906,6 +3016,10 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
if ((TargetRange.NonNegative && !SourceRange.NonNegative) ||
(!TargetRange.NonNegative && SourceRange.NonNegative &&
SourceRange.Width == TargetRange.Width)) {
+
+ if (isFromSystemMacro(S, CC))
+ return;
+
unsigned DiagID = diag::warn_impcast_integer_sign;
// Traditionally, gcc has warned about this under -Wsign-compare.
@@ -2922,15 +3036,31 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
}
// Diagnose conversions between different enumeration types.
+ // In C, we pretend that the type of an EnumConstantDecl is its enumeration
+ // type, to give us better diagnostics.
+ QualType SourceType = E->getType();
+ if (!S.getLangOptions().CPlusPlus) {
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ if (EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
+ EnumDecl *Enum = cast<EnumDecl>(ECD->getDeclContext());
+ SourceType = S.Context.getTypeDeclType(Enum);
+ Source = S.Context.getCanonicalType(SourceType).getTypePtr();
+ }
+ }
+
if (const EnumType *SourceEnum = Source->getAs<EnumType>())
if (const EnumType *TargetEnum = Target->getAs<EnumType>())
if ((SourceEnum->getDecl()->getIdentifier() ||
- SourceEnum->getDecl()->getTypedefForAnonDecl()) &&
+ SourceEnum->getDecl()->getTypedefNameForAnonDecl()) &&
(TargetEnum->getDecl()->getIdentifier() ||
- TargetEnum->getDecl()->getTypedefForAnonDecl()) &&
- SourceEnum != TargetEnum)
- return DiagnoseImpCast(S, E, T, CC,
+ TargetEnum->getDecl()->getTypedefNameForAnonDecl()) &&
+ SourceEnum != TargetEnum) {
+ if (isFromSystemMacro(S, CC))
+ return;
+
+ return DiagnoseImpCast(S, E, SourceType, T, CC,
diag::warn_impcast_different_enum_types);
+ }
return;
}
@@ -3039,7 +3169,7 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
if (isa<StmtExpr>(E)) return;
// Don't descend into unevaluated contexts.
- if (isa<SizeOfAlignOfExpr>(E)) return;
+ if (isa<UnaryExprOrTypeTraitExpr>(E)) return;
// Now just recurse over the expression's children.
CC = E->getExprLoc();
@@ -3169,10 +3299,11 @@ void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
<< TRange << Op->getSourceRange();
}
-void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) {
+static void CheckArrayAccess_Check(Sema &S,
+ const clang::ArraySubscriptExpr *E) {
const Expr *BaseExpr = E->getBase()->IgnoreParenImpCasts();
const ConstantArrayType *ArrayTy =
- Context.getAsConstantArrayType(BaseExpr->getType());
+ S.Context.getAsConstantArrayType(BaseExpr->getType());
if (!ArrayTy)
return;
@@ -3180,7 +3311,7 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) {
if (IndexExpr->isValueDependent())
return;
llvm::APSInt index;
- if (!IndexExpr->isIntegerConstantExpr(index, Context))
+ if (!IndexExpr->isIntegerConstantExpr(index, S.Context))
return;
if (index.isUnsigned() || !index.isNegative()) {
@@ -3195,15 +3326,16 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) {
if (index.slt(size))
return;
- DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr,
- PDiag(diag::warn_array_index_exceeds_bounds)
- << index.toString(10, true) << size.toString(10, true)
- << IndexExpr->getSourceRange());
+ S.DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr,
+ S.PDiag(diag::warn_array_index_exceeds_bounds)
+ << index.toString(10, true)
+ << size.toString(10, true)
+ << IndexExpr->getSourceRange());
} else {
- DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr,
- PDiag(diag::warn_array_index_precedes_bounds)
- << index.toString(10, true)
- << IndexExpr->getSourceRange());
+ S.DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr,
+ S.PDiag(diag::warn_array_index_precedes_bounds)
+ << index.toString(10, true)
+ << IndexExpr->getSourceRange());
}
const NamedDecl *ND = NULL;
@@ -3212,8 +3344,28 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) {
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
ND = dyn_cast<NamedDecl>(ME->getMemberDecl());
if (ND)
- DiagRuntimeBehavior(ND->getLocStart(), BaseExpr,
- PDiag(diag::note_array_index_out_of_bounds)
- << ND->getDeclName());
+ S.DiagRuntimeBehavior(ND->getLocStart(), BaseExpr,
+ S.PDiag(diag::note_array_index_out_of_bounds)
+ << ND->getDeclName());
}
+void Sema::CheckArrayAccess(const Expr *expr) {
+ while (true) {
+ expr = expr->IgnoreParens();
+ switch (expr->getStmtClass()) {
+ case Stmt::ArraySubscriptExprClass:
+ CheckArrayAccess_Check(*this, cast<ArraySubscriptExpr>(expr));
+ return;
+ case Stmt::ConditionalOperatorClass: {
+ const ConditionalOperator *cond = cast<ConditionalOperator>(expr);
+ if (const Expr *lhs = cond->getLHS())
+ CheckArrayAccess(lhs);
+ if (const Expr *rhs = cond->getRHS())
+ CheckArrayAccess(rhs);
+ return;
+ }
+ default:
+ return;
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
index bab665a..cc8726d 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
@@ -667,8 +667,39 @@ QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
T = Value->getType();
else
return QualType();
-
- return T.getNonReferenceType();
+
+ // Dig through references, function pointers, and block pointers to
+ // get down to the likely type of an expression when the entity is
+ // used.
+ do {
+ if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
+ T = Ref->getPointeeType();
+ continue;
+ }
+
+ if (const PointerType *Pointer = T->getAs<PointerType>()) {
+ if (Pointer->getPointeeType()->isFunctionType()) {
+ T = Pointer->getPointeeType();
+ continue;
+ }
+
+ break;
+ }
+
+ if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
+ T = Block->getPointeeType();
+ continue;
+ }
+
+ if (const FunctionType *Function = T->getAs<FunctionType>()) {
+ T = Function->getResultType();
+ continue;
+ }
+
+ break;
+ } while (true);
+
+ return T;
}
void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
@@ -1482,7 +1513,8 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
case Sema::PCC_Statement: {
AddTypedefResult(Results);
- if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
+ if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns() &&
+ SemaRef.getLangOptions().CXXExceptions) {
Builder.AddTypedTextChunk("try");
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddPlaceholderChunk("statements");
@@ -1655,15 +1687,17 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Results.AddResult(Result("true"));
Results.AddResult(Result("false"));
- // dynamic_cast < type-id > ( expression )
- Builder.AddTypedTextChunk("dynamic_cast");
- Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
- Builder.AddPlaceholderChunk("type");
- Builder.AddChunk(CodeCompletionString::CK_RightAngle);
- Builder.AddChunk(CodeCompletionString::CK_LeftParen);
- Builder.AddPlaceholderChunk("expression");
- Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
+ if (SemaRef.getLangOptions().RTTI) {
+ // dynamic_cast < type-id > ( expression )
+ Builder.AddTypedTextChunk("dynamic_cast");
+ Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
+ Builder.AddPlaceholderChunk("type");
+ Builder.AddChunk(CodeCompletionString::CK_RightAngle);
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
// static_cast < type-id > ( expression )
Builder.AddTypedTextChunk("static_cast");
@@ -1695,13 +1729,15 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
- // typeid ( expression-or-type )
- Builder.AddTypedTextChunk("typeid");
- Builder.AddChunk(CodeCompletionString::CK_LeftParen);
- Builder.AddPlaceholderChunk("expression-or-type");
- Builder.AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Builder.TakeString()));
-
+ if (SemaRef.getLangOptions().RTTI) {
+ // typeid ( expression-or-type )
+ Builder.AddTypedTextChunk("typeid");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression-or-type");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+
// new T ( ... )
Builder.AddTypedTextChunk("new");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -1738,11 +1774,13 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
- // throw expression
- Builder.AddTypedTextChunk("throw");
- Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Builder.AddPlaceholderChunk("expression");
- Results.AddResult(Result(Builder.TakeString()));
+ if (SemaRef.getLangOptions().CXXExceptions) {
+ // throw expression
+ Builder.AddTypedTextChunk("throw");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("expression");
+ Results.AddResult(Result(Builder.TakeString()));
+ }
// FIXME: Rethrow?
}
@@ -1785,9 +1823,9 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
///
/// This routine provides a fast path where we provide constant strings for
/// common type names.
-const char *GetCompletionTypeString(QualType T,
- ASTContext &Context,
- CodeCompletionAllocator &Allocator) {
+static const char *GetCompletionTypeString(QualType T,
+ ASTContext &Context,
+ CodeCompletionAllocator &Allocator) {
PrintingPolicy Policy(Context.PrintingPolicy);
Policy.AnonymousTagLocations = false;
@@ -1799,7 +1837,7 @@ const char *GetCompletionTypeString(QualType T,
// Anonymous tag types are constant strings.
if (const TagType *TagT = dyn_cast<TagType>(T))
if (TagDecl *Tag = TagT->getDecl())
- if (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl()) {
+ if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
switch (Tag->getTagKind()) {
case TTK_Struct: return "struct <anonymous>";
case TTK_Class: return "class <anonymous>";
@@ -1902,7 +1940,7 @@ static std::string FormatFunctionParameter(ASTContext &Context,
// Look through typedefs.
if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
if (TypeSourceInfo *InnerTSInfo
- = TypedefTL->getTypedefDecl()->getTypeSourceInfo()) {
+ = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
continue;
}
@@ -2602,6 +2640,7 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) {
case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
case Decl::ParmVar: return CXCursor_ParmDecl;
case Decl::Typedef: return CXCursor_TypedefDecl;
+ case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
case Decl::Var: return CXCursor_VarDecl;
case Decl::Namespace: return CXCursor_Namespace;
case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
@@ -4816,8 +4855,12 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
// If necessary, apply function/array conversion to the receiver.
// C99 6.7.5.3p[7,8].
- if (RecExpr)
- DefaultFunctionArrayLvalueConversion(RecExpr);
+ if (RecExpr) {
+ ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
+ if (Conv.isInvalid()) // conversion failed. bail.
+ return;
+ RecExpr = Conv.take();
+ }
QualType ReceiverType = RecExpr? RecExpr->getType()
: Super? Context.getObjCObjectPointerType(
Context.getObjCInterfaceType(Super))
@@ -5327,16 +5370,65 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
->getClassInterface();
+ // Determine the type of the property we're synthesizing.
+ QualType PropertyType = Context.getObjCIdType();
+ if (Class) {
+ if (ObjCPropertyDecl *Property
+ = Class->FindPropertyDeclaration(PropertyName)) {
+ PropertyType
+ = Property->getType().getNonReferenceType().getUnqualifiedType();
+
+ // Give preference to ivars
+ Results.setPreferredType(PropertyType);
+ }
+ }
+
// Add all of the instance variables in this class and its superclasses.
Results.EnterNewScope();
+ bool SawSimilarlyNamedIvar = false;
+ std::string NameWithPrefix;
+ NameWithPrefix += '_';
+ NameWithPrefix += PropertyName->getName().str();
+ std::string NameWithSuffix = PropertyName->getName().str();
+ NameWithSuffix += '_';
for(; Class; Class = Class->getSuperClass()) {
- // FIXME: We could screen the type of each ivar for compatibility with
- // the property, but is that being too paternal?
- for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(),
- IVarEnd = Class->ivar_end();
- IVar != IVarEnd; ++IVar)
- Results.AddResult(Result(*IVar, 0), CurContext, 0, false);
+ for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
+ Ivar = Ivar->getNextIvar()) {
+ Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
+
+ // Determine whether we've seen an ivar with a name similar to the
+ // property.
+ if ((PropertyName == Ivar->getIdentifier() ||
+ NameWithPrefix == Ivar->getName() ||
+ NameWithSuffix == Ivar->getName())) {
+ SawSimilarlyNamedIvar = true;
+
+ // Reduce the priority of this result by one, to give it a slight
+ // advantage over other results whose names don't match so closely.
+ if (Results.size() &&
+ Results.data()[Results.size() - 1].Kind
+ == CodeCompletionResult::RK_Declaration &&
+ Results.data()[Results.size() - 1].Declaration == Ivar)
+ Results.data()[Results.size() - 1].Priority--;
+ }
+ }
+ }
+
+ if (!SawSimilarlyNamedIvar) {
+ // Create ivar result _propName, that the user can use to synthesize
+ // an ivar of the appropriate type.
+ unsigned Priority = CCP_MemberDeclaration + 1;
+ typedef CodeCompletionResult Result;
+ CodeCompletionAllocator &Allocator = Results.getAllocator();
+ CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available);
+
+ Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
+ Allocator));
+ Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
+ Results.AddResult(Result(Builder.TakeString(), Priority,
+ CXCursor_ObjCIvarDecl));
}
+
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
index d6efd7a..7214988 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
@@ -17,6 +17,7 @@
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -24,6 +25,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/CharUnits.h"
@@ -61,7 +63,8 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr) {
ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, CXXScopeSpec *SS,
bool isClassName, bool HasTrailingDot,
- ParsedType ObjectTypePtr) {
+ ParsedType ObjectTypePtr,
+ bool WantNontrivialTypeSourceInfo) {
// Determine where we will perform name lookup.
DeclContext *LookupCtx = 0;
if (ObjectTypePtr) {
@@ -87,10 +90,15 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
// We know from the grammar that this name refers to a type,
// so build a dependent node to describe the type.
+ if (WantNontrivialTypeSourceInfo)
+ return ActOnTypenameType(S, SourceLocation(), *SS, II, NameLoc).get();
+
+ NestedNameSpecifierLoc QualifierLoc = SS->getWithLocInContext(Context);
QualType T =
- CheckTypenameType(ETK_None, SS->getScopeRep(), II,
- SourceLocation(), SS->getRange(), NameLoc);
- return ParsedType::make(T);
+ CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc,
+ II, NameLoc);
+
+ return ParsedType::make(T);
}
return ParsedType();
@@ -189,10 +197,23 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
if (T.isNull())
T = Context.getTypeDeclType(TD);
- if (SS)
- T = getElaboratedType(ETK_None, *SS, T);
-
+ if (SS && SS->isNotEmpty()) {
+ if (WantNontrivialTypeSourceInfo) {
+ // Construct a type with type-source information.
+ TypeLocBuilder Builder;
+ Builder.pushTypeSpec(T).setNameLoc(NameLoc);
+
+ T = getElaboratedType(ETK_None, *SS, T);
+ ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T);
+ ElabTL.setKeywordLoc(SourceLocation());
+ ElabTL.setQualifierLoc(SS->getWithLocInContext(Context));
+ return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
+ } else {
+ T = getElaboratedType(ETK_None, *SS, T);
+ }
+ }
} else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
+ (void)DiagnoseUseOfDecl(IDecl, NameLoc);
if (!HasTrailingDot)
T = Context.getObjCInterfaceType(IDecl);
}
@@ -229,6 +250,33 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
return DeclSpec::TST_unspecified;
}
+/// isMicrosoftMissingTypename - In Microsoft mode, within class scope,
+/// if a CXXScopeSpec's type is equal to the type of one of the base classes
+/// then downgrade the missing typename error to a warning.
+/// This is needed for MSVC compatibility; Example:
+/// @code
+/// template<class T> class A {
+/// public:
+/// typedef int TYPE;
+/// };
+/// template<class T> class B : public A<T> {
+/// public:
+/// A<T>::TYPE a; // no typename required because A<T> is a base class.
+/// };
+/// @endcode
+bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS) {
+ if (CurContext->isRecord()) {
+ const Type *Ty = SS->getScopeRep()->getAsType();
+
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext);
+ for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(),
+ BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base)
+ if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base->getType()))
+ return true;
+ }
+ return false;
+}
+
bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
SourceLocation IILoc,
Scope *S,
@@ -263,7 +311,9 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
Diag(Result->getLocation(), diag::note_previous_decl)
<< Result->getDeclName();
- SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS);
+ SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS,
+ false, false, ParsedType(),
+ /*NonTrivialTypeSourceInfo=*/true);
return true;
}
} else if (Lookup.empty()) {
@@ -304,7 +354,11 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
Diag(IILoc, diag::err_typename_nested_not_found)
<< &II << DC << SS->getRange();
else if (isDependentScopeSpecifier(*SS)) {
- Diag(SS->getRange().getBegin(), diag::err_typename_missing)
+ unsigned DiagID = diag::err_typename_missing;
+ if (getLangOptions().Microsoft && isMicrosoftMissingTypename(SS))
+ DiagID = diag::warn_typename_missing;
+
+ Diag(SS->getRange().getBegin(), DiagID)
<< (NestedNameSpecifier *)SS->getScopeRep() << II.getName()
<< SourceRange(SS->getRange().getBegin(), IILoc)
<< FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename ");
@@ -317,6 +371,328 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
return true;
}
+/// \brief Determine whether the given result set contains either a type name
+/// or
+static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) {
+ bool CheckTemplate = R.getSema().getLangOptions().CPlusPlus &&
+ NextToken.is(tok::less);
+
+ for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) {
+ if (isa<TypeDecl>(*I) || isa<ObjCInterfaceDecl>(*I))
+ return true;
+
+ if (CheckTemplate && isa<TemplateDecl>(*I))
+ return true;
+ }
+
+ return false;
+}
+
+Sema::NameClassification Sema::ClassifyName(Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *&Name,
+ SourceLocation NameLoc,
+ const Token &NextToken) {
+ DeclarationNameInfo NameInfo(Name, NameLoc);
+ ObjCMethodDecl *CurMethod = getCurMethodDecl();
+
+ if (NextToken.is(tok::coloncolon)) {
+ BuildCXXNestedNameSpecifier(S, *Name, NameLoc, NextToken.getLocation(),
+ QualType(), false, SS, 0, false);
+
+ }
+
+ LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
+ LookupParsedName(Result, S, &SS, !CurMethod);
+
+ // Perform lookup for Objective-C instance variables (including automatically
+ // synthesized instance variables), if we're in an Objective-C method.
+ // FIXME: This lookup really, really needs to be folded in to the normal
+ // unqualified lookup mechanism.
+ if (!SS.isSet() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) {
+ ExprResult E = LookupInObjCMethod(Result, S, Name, true);
+ if (E.get() || E.isInvalid())
+ return E;
+
+ // Synthesize ivars lazily.
+ if (getLangOptions().ObjCDefaultSynthProperties &&
+ getLangOptions().ObjCNonFragileABI2) {
+ if (SynthesizeProvisionalIvar(Result, Name, NameLoc)) {
+ if (const ObjCPropertyDecl *Property =
+ canSynthesizeProvisionalIvar(Name)) {
+ Diag(NameLoc, diag::warn_synthesized_ivar_access) << Name;
+ Diag(Property->getLocation(), diag::note_property_declare);
+ }
+
+ // FIXME: This is strange. Shouldn't we just take the ivar returned
+ // from SynthesizeProvisionalIvar and continue with that?
+ E = LookupInObjCMethod(Result, S, Name, true);
+ if (E.get() || E.isInvalid())
+ return E;
+ }
+ }
+ }
+
+ bool SecondTry = false;
+ bool IsFilteredTemplateName = false;
+
+Corrected:
+ switch (Result.getResultKind()) {
+ case LookupResult::NotFound:
+ // If an unqualified-id is followed by a '(', then we have a function
+ // call.
+ if (!SS.isSet() && NextToken.is(tok::l_paren)) {
+ // In C++, this is an ADL-only call.
+ // FIXME: Reference?
+ if (getLangOptions().CPlusPlus)
+ return BuildDeclarationNameExpr(SS, Result, /*ADL=*/true);
+
+ // C90 6.3.2.2:
+ // If the expression that precedes the parenthesized argument list in a
+ // function call consists solely of an identifier, and if no
+ // declaration is visible for this identifier, the identifier is
+ // implicitly declared exactly as if, in the innermost block containing
+ // the function call, the declaration
+ //
+ // extern int identifier ();
+ //
+ // appeared.
+ //
+ // We also allow this in C99 as an extension.
+ if (NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *Name, S)) {
+ Result.addDecl(D);
+ Result.resolveKind();
+ return BuildDeclarationNameExpr(SS, Result, /*ADL=*/false);
+ }
+ }
+
+ // In C, we first see whether there is a tag type by the same name, in
+ // which case it's likely that the user just forget to write "enum",
+ // "struct", or "union".
+ if (!getLangOptions().CPlusPlus && !SecondTry) {
+ Result.clear(LookupTagName);
+ LookupParsedName(Result, S, &SS);
+ if (TagDecl *Tag = Result.getAsSingle<TagDecl>()) {
+ const char *TagName = 0;
+ const char *FixItTagName = 0;
+ switch (Tag->getTagKind()) {
+ case TTK_Class:
+ TagName = "class";
+ FixItTagName = "class ";
+ break;
+
+ case TTK_Enum:
+ TagName = "enum";
+ FixItTagName = "enum ";
+ break;
+
+ case TTK_Struct:
+ TagName = "struct";
+ FixItTagName = "struct ";
+ break;
+
+ case TTK_Union:
+ TagName = "union";
+ FixItTagName = "union ";
+ break;
+ }
+
+ Diag(NameLoc, diag::err_use_of_tag_name_without_tag)
+ << Name << TagName << getLangOptions().CPlusPlus
+ << FixItHint::CreateInsertion(NameLoc, FixItTagName);
+ break;
+ }
+
+ Result.clear(LookupOrdinaryName);
+ }
+
+ // Perform typo correction to determine if there is another name that is
+ // close to this name.
+ if (!SecondTry) {
+ if (DeclarationName Corrected = CorrectTypo(Result, S, &SS)) {
+ unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
+ unsigned QualifiedDiag = diag::err_no_member_suggest;
+
+ NamedDecl *FirstDecl = Result.empty()? 0 : *Result.begin();
+ NamedDecl *UnderlyingFirstDecl
+ = FirstDecl? FirstDecl->getUnderlyingDecl() : 0;
+ if (getLangOptions().CPlusPlus && NextToken.is(tok::less) &&
+ UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) {
+ UnqualifiedDiag = diag::err_no_template_suggest;
+ QualifiedDiag = diag::err_no_member_template_suggest;
+ } else if (UnderlyingFirstDecl &&
+ (isa<TypeDecl>(UnderlyingFirstDecl) ||
+ isa<ObjCInterfaceDecl>(UnderlyingFirstDecl) ||
+ isa<ObjCCompatibleAliasDecl>(UnderlyingFirstDecl))) {
+ UnqualifiedDiag = diag::err_unknown_typename_suggest;
+ QualifiedDiag = diag::err_unknown_nested_typename_suggest;
+ }
+
+ if (SS.isEmpty())
+ Diag(NameLoc, UnqualifiedDiag)
+ << Name << Corrected
+ << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString());
+ else
+ Diag(NameLoc, QualifiedDiag)
+ << Name << computeDeclContext(SS, false) << Corrected
+ << SS.getRange()
+ << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString());
+
+ // Update the name, so that the caller has the new name.
+ Name = Corrected.getAsIdentifierInfo();
+
+ // Typo correction corrected to a keyword.
+ if (Result.empty())
+ return Corrected.getAsIdentifierInfo();
+
+ Diag(FirstDecl->getLocation(), diag::note_previous_decl)
+ << FirstDecl->getDeclName();
+
+ // If we found an Objective-C instance variable, let
+ // LookupInObjCMethod build the appropriate expression to
+ // reference the ivar.
+ // FIXME: This is a gross hack.
+ if (ObjCIvarDecl *Ivar = Result.getAsSingle<ObjCIvarDecl>()) {
+ Result.clear();
+ ExprResult E(LookupInObjCMethod(Result, S, Ivar->getIdentifier()));
+ return move(E);
+ }
+
+ goto Corrected;
+ }
+ }
+
+ // We failed to correct; just fall through and let the parser deal with it.
+ Result.suppressDiagnostics();
+ return NameClassification::Unknown();
+
+ case LookupResult::NotFoundInCurrentInstantiation:
+ // We performed name lookup into the current instantiation, and there were
+ // dependent bases, so we treat this result the same way as any other
+ // dependent nested-name-specifier.
+
+ // C++ [temp.res]p2:
+ // A name used in a template declaration or definition and that is
+ // dependent on a template-parameter is assumed not to name a type
+ // unless the applicable name lookup finds a type name or the name is
+ // qualified by the keyword typename.
+ //
+ // FIXME: If the next token is '<', we might want to ask the parser to
+ // perform some heroics to see if we actually have a
+ // template-argument-list, which would indicate a missing 'template'
+ // keyword here.
+ return BuildDependentDeclRefExpr(SS, NameInfo, /*TemplateArgs=*/0);
+
+ case LookupResult::Found:
+ case LookupResult::FoundOverloaded:
+ case LookupResult::FoundUnresolvedValue:
+ break;
+
+ case LookupResult::Ambiguous:
+ if (getLangOptions().CPlusPlus && NextToken.is(tok::less) &&
+ hasAnyAcceptableTemplateNames(Result)) {
+ // C++ [temp.local]p3:
+ // A lookup that finds an injected-class-name (10.2) can result in an
+ // ambiguity in certain cases (for example, if it is found in more than
+ // one base class). If all of the injected-class-names that are found
+ // refer to specializations of the same class template, and if the name
+ // is followed by a template-argument-list, the reference refers to the
+ // class template itself and not a specialization thereof, and is not
+ // ambiguous.
+ //
+ // This filtering can make an ambiguous result into an unambiguous one,
+ // so try again after filtering out template names.
+ FilterAcceptableTemplateNames(Result);
+ if (!Result.isAmbiguous()) {
+ IsFilteredTemplateName = true;
+ break;
+ }
+ }
+
+ // Diagnose the ambiguity and return an error.
+ return NameClassification::Error();
+ }
+
+ if (getLangOptions().CPlusPlus && NextToken.is(tok::less) &&
+ (IsFilteredTemplateName || hasAnyAcceptableTemplateNames(Result))) {
+ // C++ [temp.names]p3:
+ // After name lookup (3.4) finds that a name is a template-name or that
+ // an operator-function-id or a literal- operator-id refers to a set of
+ // overloaded functions any member of which is a function template if
+ // this is followed by a <, the < is always taken as the delimiter of a
+ // template-argument-list and never as the less-than operator.
+ if (!IsFilteredTemplateName)
+ FilterAcceptableTemplateNames(Result);
+
+ if (!Result.empty()) {
+ bool IsFunctionTemplate;
+ TemplateName Template;
+ if (Result.end() - Result.begin() > 1) {
+ IsFunctionTemplate = true;
+ Template = Context.getOverloadedTemplateName(Result.begin(),
+ Result.end());
+ } else {
+ TemplateDecl *TD
+ = cast<TemplateDecl>((*Result.begin())->getUnderlyingDecl());
+ IsFunctionTemplate = isa<FunctionTemplateDecl>(TD);
+
+ if (SS.isSet() && !SS.isInvalid())
+ Template = Context.getQualifiedTemplateName(SS.getScopeRep(),
+ /*TemplateKeyword=*/false,
+ TD);
+ else
+ Template = TemplateName(TD);
+ }
+
+ if (IsFunctionTemplate) {
+ // Function templates always go through overload resolution, at which
+ // point we'll perform the various checks (e.g., accessibility) we need
+ // to based on which function we selected.
+ Result.suppressDiagnostics();
+
+ return NameClassification::FunctionTemplate(Template);
+ }
+
+ return NameClassification::TypeTemplate(Template);
+ }
+ }
+
+ NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl();
+ if (TypeDecl *Type = dyn_cast<TypeDecl>(FirstDecl)) {
+ DiagnoseUseOfDecl(Type, NameLoc);
+ QualType T = Context.getTypeDeclType(Type);
+ return ParsedType::make(T);
+ }
+
+ ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(FirstDecl);
+ if (!Class) {
+ // FIXME: It's unfortunate that we don't have a Type node for handling this.
+ if (ObjCCompatibleAliasDecl *Alias
+ = dyn_cast<ObjCCompatibleAliasDecl>(FirstDecl))
+ Class = Alias->getClassInterface();
+ }
+
+ if (Class) {
+ DiagnoseUseOfDecl(Class, NameLoc);
+
+ if (NextToken.is(tok::period)) {
+ // Interface. <something> is parsed as a property reference expression.
+ // Just return "unknown" as a fall-through for now.
+ Result.suppressDiagnostics();
+ return NameClassification::Unknown();
+ }
+
+ QualType T = Context.getObjCInterfaceType(Class);
+ return ParsedType::make(T);
+ }
+
+ if (!Result.empty() && (*Result.begin())->isCXXClassMember())
+ return BuildPossibleImplicitMemberExpr(SS, Result, 0);
+
+ bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren));
+ return BuildDeclarationNameExpr(SS, Result, ADL);
+}
+
// Determines the context to return to after temporarily entering a
// context. This depends in an unnecessarily complicated way on the
// exact ordering of callbacks from the parser.
@@ -472,11 +848,30 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
}
S->AddDecl(D);
- IdResolver.AddDecl(D);
+
+ if (isa<LabelDecl>(D) && !cast<LabelDecl>(D)->isGnuLocal()) {
+ // Implicitly-generated labels may end up getting generated in an order that
+ // isn't strictly lexical, which breaks name lookup. Be careful to insert
+ // the label at the appropriate place in the identifier chain.
+ for (I = IdResolver.begin(D->getDeclName()); I != IEnd; ++I) {
+ DeclContext *IDC = (*I)->getLexicalDeclContext()->getRedeclContext();
+ if (IDC == CurContext) {
+ if (!S->isDeclScope(*I))
+ continue;
+ } else if (IDC->Encloses(CurContext))
+ break;
+ }
+
+ IdResolver.InsertDeclAfter(I, D);
+ } else {
+ IdResolver.AddDecl(D);
+ }
}
-bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) {
- return IdResolver.isDeclInScope(D, Ctx, Context, S);
+bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S,
+ bool ExplicitInstantiationOrSpecialization) {
+ return IdResolver.isDeclInScope(D, Ctx, Context, S,
+ ExplicitInstantiationOrSpecialization);
}
Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) {
@@ -498,12 +893,13 @@ static bool isOutOfScopePreviousDeclaration(NamedDecl *,
/// as determined by isDeclInScope.
static void FilterLookupForScope(Sema &SemaRef, LookupResult &R,
DeclContext *Ctx, Scope *S,
- bool ConsiderLinkage) {
+ bool ConsiderLinkage,
+ bool ExplicitInstantiationOrSpecialization) {
LookupResult::Filter F = R.makeFilter();
while (F.hasNext()) {
NamedDecl *D = F.next();
- if (SemaRef.isDeclInScope(D, Ctx, S))
+ if (SemaRef.isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization))
continue;
if (ConsiderLinkage &&
@@ -841,7 +1237,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
FunctionDecl *New = FunctionDecl::Create(Context,
Context.getTranslationUnitDecl(),
- Loc, II, R, /*TInfo=*/0,
+ Loc, Loc, II, R, /*TInfo=*/0,
SC_Extern,
SC_None, false,
/*hasPrototype=*/true);
@@ -851,10 +1247,15 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
// FunctionDecl.
if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) {
llvm::SmallVector<ParmVarDecl*, 16> Params;
- for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i)
- Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0,
- FT->getArgType(i), /*TInfo=*/0,
- SC_None, SC_None, 0));
+ for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
+ ParmVarDecl *parm =
+ ParmVarDecl::Create(Context, New, SourceLocation(),
+ SourceLocation(), 0,
+ FT->getArgType(i), /*TInfo=*/0,
+ SC_None, SC_None, 0);
+ parm->setScopeInfo(0, i);
+ Params.push_back(parm);
+ }
New->setParams(Params.data(), Params.size());
}
@@ -871,12 +1272,12 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
return New;
}
-/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the
+/// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the
/// same name and scope as a previous declaration 'Old'. Figure out
/// how to resolve this situation, merging decls or emitting
/// diagnostics as appropriate. If there was an error, set New to be invalid.
///
-void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
+void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
// If the new decl is known invalid already, don't bother doing any
// merging checks.
if (New->isInvalidDecl()) return;
@@ -936,7 +1337,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
// Determine the "old" type we'll use for checking and diagnostics.
QualType OldType;
- if (TypedefDecl *OldTypedef = dyn_cast<TypedefDecl>(Old))
+ if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
OldType = OldTypedef->getUnderlyingType();
else
OldType = Context.getTypeDeclType(Old);
@@ -947,8 +1348,11 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
if (OldType != New->getUnderlyingType() &&
Context.getCanonicalType(OldType) !=
Context.getCanonicalType(New->getUnderlyingType())) {
+ int Kind = 0;
+ if (isa<TypeAliasDecl>(Old))
+ Kind = 1;
Diag(New->getLocation(), diag::err_redefinition_different_typedef)
- << New->getUnderlyingType() << OldType;
+ << Kind << New->getUnderlyingType() << OldType;
if (Old->getLocation().isValid())
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
@@ -958,8 +1362,8 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
// declaration was a typedef.
// FIXME: this is a potential source of wierdness if the type
// spellings don't match exactly.
- if (isa<TypedefDecl>(Old))
- New->setPreviousDeclaration(cast<TypedefDecl>(Old));
+ if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old))
+ New->setPreviousDeclaration(Typedef);
if (getLangOptions().Microsoft)
return;
@@ -993,7 +1397,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
// };
//
// since that was the intent of DR56.
- if (!isa<TypedefDecl >(Old))
+ if (!isa<TypedefNameDecl>(Old))
return;
Diag(New->getLocation(), diag::err_redefinition)
@@ -1033,23 +1437,58 @@ DeclHasAttr(const Decl *D, const Attr *A) {
return false;
}
-/// MergeDeclAttributes - append attributes from the Old decl to the New one.
-static void MergeDeclAttributes(Decl *New, Decl *Old, ASTContext &C) {
- if (!Old->hasAttrs())
+/// mergeDeclAttributes - Copy attributes from the Old decl to the New one.
+static void mergeDeclAttributes(Decl *newDecl, const Decl *oldDecl,
+ ASTContext &C) {
+ if (!oldDecl->hasAttrs())
return;
+
+ bool foundAny = newDecl->hasAttrs();
+
// Ensure that any moving of objects within the allocated map is done before
// we process them.
- if (!New->hasAttrs())
- New->setAttrs(AttrVec());
+ if (!foundAny) newDecl->setAttrs(AttrVec());
+
for (specific_attr_iterator<InheritableAttr>
- i = Old->specific_attr_begin<InheritableAttr>(),
- e = Old->specific_attr_end<InheritableAttr>(); i != e; ++i) {
- if (!DeclHasAttr(New, *i)) {
- InheritableAttr *NewAttr = cast<InheritableAttr>((*i)->clone(C));
- NewAttr->setInherited(true);
- New->addAttr(NewAttr);
+ i = oldDecl->specific_attr_begin<InheritableAttr>(),
+ e = oldDecl->specific_attr_end<InheritableAttr>(); i != e; ++i) {
+ if (!DeclHasAttr(newDecl, *i)) {
+ InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(C));
+ newAttr->setInherited(true);
+ newDecl->addAttr(newAttr);
+ foundAny = true;
}
}
+
+ if (!foundAny) newDecl->dropAttrs();
+}
+
+/// mergeParamDeclAttributes - Copy attributes from the old parameter
+/// to the new one.
+static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
+ const ParmVarDecl *oldDecl,
+ ASTContext &C) {
+ if (!oldDecl->hasAttrs())
+ return;
+
+ bool foundAny = newDecl->hasAttrs();
+
+ // Ensure that any moving of objects within the allocated map is
+ // done before we process them.
+ if (!foundAny) newDecl->setAttrs(AttrVec());
+
+ for (specific_attr_iterator<InheritableParamAttr>
+ i = oldDecl->specific_attr_begin<InheritableParamAttr>(),
+ e = oldDecl->specific_attr_end<InheritableParamAttr>(); i != e; ++i) {
+ if (!DeclHasAttr(newDecl, *i)) {
+ InheritableAttr *newAttr = cast<InheritableParamAttr>((*i)->clone(C));
+ newAttr->setInherited(true);
+ newDecl->addAttr(newAttr);
+ foundAny = true;
+ }
+ }
+
+ if (!foundAny) newDecl->dropAttrs();
}
namespace {
@@ -1145,10 +1584,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
New->getStorageClass() == SC_Static &&
Old->getStorageClass() != SC_Static &&
!canRedefineFunction(Old, getLangOptions())) {
- Diag(New->getLocation(), diag::err_static_non_static)
- << New;
- Diag(Old->getLocation(), PrevDiag);
- return true;
+ if (getLangOptions().Microsoft) {
+ Diag(New->getLocation(), diag::warn_static_non_static) << New;
+ Diag(Old->getLocation(), PrevDiag);
+ } else {
+ Diag(New->getLocation(), diag::err_static_non_static) << New;
+ Diag(Old->getLocation(), PrevDiag);
+ return true;
+ }
}
// If a function is first declared with a calling convention, but is
@@ -1191,8 +1634,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
}
// Merge regparm attribute.
- if (OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) {
- if (NewTypeInfo.getRegParm()) {
+ if (OldTypeInfo.getHasRegParm() != NewTypeInfo.getHasRegParm() ||
+ OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) {
+ if (NewTypeInfo.getHasRegParm()) {
Diag(New->getLocation(), diag::err_regparm_mismatch)
<< NewType->getRegParmType()
<< OldType->getRegParmType();
@@ -1335,10 +1779,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
ParamEnd = OldProto->arg_type_end();
ParamType != ParamEnd; ++ParamType) {
ParmVarDecl *Param = ParmVarDecl::Create(Context, New,
+ SourceLocation(),
SourceLocation(), 0,
*ParamType, /*TInfo=*/0,
SC_None, SC_None,
0);
+ Param->setScopeInfo(0, Params.size());
Param->setImplicit();
Params.push_back(Param);
}
@@ -1450,7 +1896,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
/// \returns false
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
// Merge the attributes
- MergeDeclAttributes(New, Old, Context);
+ mergeDeclAttributes(New, Old, Context);
// Merge the storage class.
if (Old->getStorageClass() != SC_Extern &&
@@ -1465,14 +1911,33 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
if (Old->isDeleted())
New->setDeleted();
+ // Merge attributes from the parameters. These can mismatch with K&R
+ // declarations.
+ if (New->getNumParams() == Old->getNumParams())
+ for (unsigned i = 0, e = New->getNumParams(); i != e; ++i)
+ mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i),
+ Context);
+
if (getLangOptions().CPlusPlus)
return MergeCXXFunctionDecl(New, Old);
return false;
}
-/// MergeVarDecl - We parsed a variable 'New' which has the same name and scope
-/// as a previous declaration 'Old'. Figure out how to merge their types,
+void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
+ const ObjCMethodDecl *oldMethod) {
+ // Merge the attributes.
+ mergeDeclAttributes(newMethod, oldMethod, Context);
+
+ // Merge attributes from the parameters.
+ for (ObjCMethodDecl::param_iterator oi = oldMethod->param_begin(),
+ ni = newMethod->param_begin(), ne = newMethod->param_end();
+ ni != ne; ++ni, ++oi)
+ mergeParamDeclAttributes(*ni, *oi, Context);
+}
+
+/// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and
+/// scope as a previous declaration 'Old'. Figure out how to merge their types,
/// emitting diagnostics as appropriate.
///
/// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back
@@ -1489,8 +1954,10 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
if (AT && !AT->isDeduced()) {
// We don't know what the new type is until the initializer is attached.
return;
- } else if (Context.hasSameType(New->getType(), Old->getType()))
- return;
+ } else if (Context.hasSameType(New->getType(), Old->getType())) {
+ // These could still be something that needs exception specs checked.
+ return MergeVarDeclExceptionSpecs(New, Old);
+ }
// C++ [basic.link]p10:
// [...] the types specified by all declarations referring to a given
// object or function shall be identical, except that declarations for an
@@ -1564,7 +2031,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->setInvalidDecl();
}
- MergeDeclAttributes(New, Old, Context);
+ mergeDeclAttributes(New, Old, Context);
// Merge the types.
MergeVarDeclTypes(New, Old);
@@ -1664,12 +2131,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
/// no declarator (e.g. "struct foo;") is parsed.
Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
- DeclSpec &DS) {
- // FIXME: Error on inline/virtual/explicit
- // FIXME: Warn on useless __thread
- // FIXME: Warn on useless const/volatile
- // FIXME: Warn on useless static/extern/typedef/private_extern/mutable
- // FIXME: Warn on useless attributes
+ DeclSpec &DS) {
Decl *TagD = 0;
TagDecl *Tag = 0;
if (DS.getTypeSpecType() == DeclSpec::TST_class ||
@@ -1703,6 +2165,10 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return 0;
return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0));
}
+
+ // Track whether we warned about the fact that there aren't any
+ // declarators.
+ bool emittedWarning = false;
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
ProcessDeclAttributeList(S, Record, DS.getAttributes().getList());
@@ -1715,6 +2181,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators)
<< DS.getSourceRange();
+ emittedWarning = true;
}
}
@@ -1740,12 +2207,16 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
DS.getStorageClassSpec() != DeclSpec::SCS_typedef)
if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Tag))
if (Enum->enumerator_begin() == Enum->enumerator_end() &&
- !Enum->getIdentifier() && !Enum->isInvalidDecl())
+ !Enum->getIdentifier() && !Enum->isInvalidDecl()) {
Diag(Enum->getLocation(), diag::ext_no_declarators)
<< DS.getSourceRange();
+ emittedWarning = true;
+ }
+
+ // Skip all the checks below if we have a type error.
+ if (DS.getTypeSpecType() == DeclSpec::TST_error) return TagD;
- if (!DS.isMissingDeclaratorOk() &&
- DS.getTypeSpecType() != DeclSpec::TST_error) {
+ if (!DS.isMissingDeclaratorOk()) {
// Warn about typedefs of enums without names, since this is an
// extension in both Microsoft and GNU.
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef &&
@@ -1757,7 +2228,40 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators)
<< DS.getSourceRange();
- }
+ emittedWarning = true;
+ }
+
+ // We're going to complain about a bunch of spurious specifiers;
+ // only do this if we're declaring a tag, because otherwise we
+ // should be getting diag::ext_no_declarators.
+ if (emittedWarning || (TagD && TagD->isInvalidDecl()))
+ return TagD;
+
+ // Note that a linkage-specification sets a storage class, but
+ // 'extern "C" struct foo;' is actually valid and not theoretically
+ // useless.
+ if (DeclSpec::SCS scs = DS.getStorageClassSpec())
+ if (!DS.isExternInLinkageSpec())
+ Diag(DS.getStorageClassSpecLoc(), diag::warn_standalone_specifier)
+ << DeclSpec::getSpecifierName(scs);
+
+ if (DS.isThreadSpecified())
+ Diag(DS.getThreadSpecLoc(), diag::warn_standalone_specifier) << "__thread";
+ if (DS.getTypeQualifiers()) {
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
+ Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "const";
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
+ Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "volatile";
+ // Restrict is covered above.
+ }
+ if (DS.isInlineSpecified())
+ Diag(DS.getInlineSpecLoc(), diag::warn_standalone_specifier) << "inline";
+ if (DS.isVirtualSpecified())
+ Diag(DS.getVirtualSpecLoc(), diag::warn_standalone_specifier) << "virtual";
+ if (DS.isExplicitSpecified())
+ Diag(DS.getExplicitSpecLoc(), diag::warn_standalone_specifier) <<"explicit";
+
+ // FIXME: Warn on useless attributes
return TagD;
}
@@ -2062,7 +2566,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// Create a declaration for this anonymous struct/union.
NamedDecl *Anon = 0;
if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) {
- Anon = FieldDecl::Create(Context, OwningClass, Record->getLocation(),
+ Anon = FieldDecl::Create(Context, OwningClass,
+ DS.getSourceRange().getBegin(),
+ Record->getLocation(),
/*IdentifierInfo=*/0,
Context.getTypeDeclType(Record),
TInfo,
@@ -2086,8 +2592,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
VarDecl::StorageClass SCAsWritten
= StorageClassSpecToVarDeclStorageClass(SCSpec);
- Anon = VarDecl::Create(Context, Owner, Record->getLocation(),
- /*IdentifierInfo=*/0,
+ Anon = VarDecl::Create(Context, Owner,
+ DS.getSourceRange().getBegin(),
+ Record->getLocation(), /*IdentifierInfo=*/0,
Context.getTypeDeclType(Record),
TInfo, SC, SCAsWritten);
}
@@ -2151,6 +2658,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
NamedDecl* Anon = FieldDecl::Create(Context,
cast<RecordDecl>(CurContext),
DS.getSourceRange().getBegin(),
+ DS.getSourceRange().getBegin(),
/*IdentifierInfo=*/0,
Context.getTypeDeclType(Record),
TInfo,
@@ -2379,6 +2887,26 @@ Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false);
}
+/// DiagnoseClassNameShadow - Implement C++ [class.mem]p13:
+/// If T is the name of a class, then each of the following shall have a
+/// name different from T:
+/// - every static data member of class T;
+/// - every member function of class T
+/// - every member of class T that is itself a type;
+/// \returns true if the declaration name violates these rules.
+bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
+ DeclarationNameInfo NameInfo) {
+ DeclarationName Name = NameInfo.getName();
+
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
+ if (Record->getIdentifier() && Record->getDeclName() == Name) {
+ Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name;
+ return true;
+ }
+
+ return false;
+}
+
Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
MultiTemplateParamsArg TemplateParamLists,
bool IsFunctionDefinition) {
@@ -2466,23 +2994,12 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
D.setInvalidType();
}
}
-
- // C++ [class.mem]p13:
- // If T is the name of a class, then each of the following shall have a
- // name different from T:
- // - every static data member of class T;
- // - every member function of class T
- // - every member of class T that is itself a type;
- if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
- if (Record->getIdentifier() && Record->getDeclName() == Name) {
- Diag(D.getIdentifierLoc(), diag::err_member_name_of_class)
- << Name;
-
- // If this is a typedef, we'll end up spewing multiple diagnostics.
- // Just return early; it's safer.
- if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
- return 0;
- }
+
+ if (DiagnoseClassNameShadow(DC, NameInfo))
+ // If this is a typedef, we'll end up spewing multiple diagnostics.
+ // Just return early; it's safer.
+ if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+ return 0;
NamedDecl *New;
@@ -2777,6 +3294,15 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewTD, D);
+ return ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration);
+}
+
+/// ActOnTypedefNameDecl - Perform semantic checking for a declaration which
+/// declares a typedef-name, either using the 'typedef' type specifier or via
+/// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'.
+NamedDecl*
+Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
+ LookupResult &Previous, bool &Redeclaration) {
// C99 6.7.7p2: If a typedef name specifies a variably modified type
// then it shall have block scope.
// Note that variably modified types must be fixed before merging the decl so
@@ -2792,18 +3318,17 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative,
Oversized);
if (!FixedTy.isNull()) {
- Diag(D.getIdentifierLoc(), diag::warn_illegal_constant_array_size);
+ Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size);
NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy));
} else {
if (SizeIsNegative)
- Diag(D.getIdentifierLoc(), diag::err_typecheck_negative_array_size);
+ Diag(NewTD->getLocation(), diag::err_typecheck_negative_array_size);
else if (T->isVariableArrayType())
- Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope);
+ Diag(NewTD->getLocation(), diag::err_vla_decl_in_file_scope);
else if (Oversized.getBoolValue())
- Diag(D.getIdentifierLoc(), diag::err_array_too_large)
- << Oversized.toString(10);
+ Diag(NewTD->getLocation(), diag::err_array_too_large) << Oversized.toString(10);
else
- Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope);
+ Diag(NewTD->getLocation(), diag::err_vm_decl_in_file_scope);
NewTD->setInvalidDecl();
}
}
@@ -2811,10 +3336,11 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Merge the decl with the existing one if appropriate. If the decl is
// in an outer scope, it isn't the same thing.
- FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false);
+ FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false,
+ /*ExplicitInstantiationOrSpecialization=*/false);
if (!Previous.empty()) {
Redeclaration = true;
- MergeTypeDefDecl(NewTD, Previous);
+ MergeTypedefNameDecl(NewTD, Previous);
}
// If this is the C FILE type, notify the AST context.
@@ -2952,8 +3478,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
bool isExplicitSpecialization = false;
VarDecl *NewVD;
if (!getLangOptions().CPlusPlus) {
- NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
- II, R, TInfo, SC, SCAsWritten);
+ NewVD = VarDecl::Create(Context, DC, D.getSourceRange().getBegin(),
+ D.getIdentifierLoc(), II,
+ R, TInfo, SC, SCAsWritten);
if (D.isInvalidType())
NewVD->setInvalidDecl();
@@ -2988,7 +3515,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Match up the template parameter lists with the scope specifier, then
// determine whether we have a template or a template specialization.
isExplicitSpecialization = false;
- unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
bool Invalid = false;
if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(
@@ -2999,9 +3525,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
/*never a friend*/ false,
isExplicitSpecialization,
Invalid)) {
- // All but one template parameter lists have been matching.
- --NumMatchedTemplateParamLists;
-
if (TemplateParams->size() > 0) {
// There is no such thing as a variable template.
Diag(D.getIdentifierLoc(), diag::err_template_variable)
@@ -3017,13 +3540,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
<< II
<< SourceRange(TemplateParams->getTemplateLoc(),
TemplateParams->getRAngleLoc());
-
isExplicitSpecialization = true;
}
}
- NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
- II, R, TInfo, SC, SCAsWritten);
+ NewVD = VarDecl::Create(Context, DC, D.getSourceRange().getBegin(),
+ D.getIdentifierLoc(), II,
+ R, TInfo, SC, SCAsWritten);
// If this decl has an auto type in need of deduction, make a note of the
// Decl so we can diagnose uses of it in its own initializer.
@@ -3036,9 +3559,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
SetNestedNameSpecifier(NewVD, D);
- if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
+ if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) {
NewVD->setTemplateParameterListsInfo(Context,
- NumMatchedTemplateParamLists,
+ TemplateParamLists.size(),
TemplateParamLists.release());
}
}
@@ -3092,7 +3615,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Don't consider existing declarations that are in a different
// scope and are out-of-semantic-context declarations (if the new
// declaration has linkage).
- FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage());
+ FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage(),
+ isExplicitSpecialization);
if (!getLangOptions().CPlusPlus)
CheckVariableDeclaration(NewVD, Previous, Redeclaration);
@@ -3169,10 +3693,11 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
return;
// Don't diagnose declarations at file scope.
- DeclContext *NewDC = D->getDeclContext();
- if (NewDC->isFileContext())
+ if (D->hasGlobalStorage())
return;
-
+
+ DeclContext *NewDC = D->getDeclContext();
+
// Only diagnose if we're shadowing an unambiguous field or variable.
if (R.getResultKind() != LookupResult::Found)
return;
@@ -3189,17 +3714,6 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
if (VarDecl *shadowedVar = dyn_cast<VarDecl>(ShadowedDecl))
if (shadowedVar->isExternC()) {
- // Don't warn for this case:
- //
- // @code
- // extern int bob;
- // void f() {
- // extern int bob;
- // }
- // @endcode
- if (D->isExternC())
- return;
-
// For shadowing external vars, make sure that we point to the global
// declaration, not a locally scoped extern declaration.
for (VarDecl::redecl_iterator
@@ -3528,8 +4042,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
FunctionTemplateDecl *FunctionTemplate = 0;
bool isExplicitSpecialization = false;
bool isFunctionTemplateSpecialization = false;
- unsigned NumMatchedTemplateParamLists = 0;
-
+
if (!getLangOptions().CPlusPlus) {
// Determine whether the function was written with a
// prototype. This true when:
@@ -3540,7 +4053,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
(D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) ||
(!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType());
- NewFD = FunctionDecl::Create(Context, DC,
+ NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(),
NameInfo, R, TInfo, SC, SCAsWritten, isInline,
HasPrototype);
if (D.isInvalidType())
@@ -3549,7 +4062,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Set the lexical context.
NewFD->setLexicalDeclContext(CurContext);
// Filter out previous declarations that don't match the scope.
- FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage());
+ FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage(),
+ /*ExplicitInstantiationOrSpecialization=*/false);
} else {
isFriend = D.getDeclSpec().isFriendSpecified();
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
@@ -3566,14 +4080,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
AbstractReturnType))
D.setInvalidType();
-
- if (isFriend) {
- // C++ [class.friend]p5
- // A function can be defined in a friend declaration of a
- // class . . . . Such a function is implicitly inline.
- isInline |= IsFunctionDefinition;
- }
-
if (Name.getNameKind() == DeclarationName::CXXConstructorName) {
// This is a C++ constructor declaration.
assert(DC->isRecord() &&
@@ -3584,6 +4090,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Create the new declaration
NewFD = CXXConstructorDecl::Create(Context,
cast<CXXRecordDecl>(DC),
+ D.getSourceRange().getBegin(),
NameInfo, R, TInfo,
isExplicit, isInline,
/*isImplicitlyDeclared=*/false);
@@ -3594,6 +4101,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NewFD = CXXDestructorDecl::Create(Context,
cast<CXXRecordDecl>(DC),
+ D.getSourceRange().getBegin(),
NameInfo, R, TInfo,
isInline,
/*isImplicitlyDeclared=*/false);
@@ -3603,8 +4111,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Create a FunctionDecl to satisfy the function definition parsing
// code path.
- NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(),
- Name, R, TInfo, SC, SCAsWritten, isInline,
+ NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(),
+ D.getIdentifierLoc(), Name, R, TInfo,
+ SC, SCAsWritten, isInline,
/*hasPrototype=*/true);
D.setInvalidType();
}
@@ -3617,8 +4126,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
CheckConversionDeclarator(D, R, SC);
NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
+ D.getSourceRange().getBegin(),
NameInfo, R, TInfo,
- isInline, isExplicit);
+ isInline, isExplicit,
+ SourceLocation());
isVirtualOkay = true;
} else if (DC->isRecord()) {
@@ -3636,7 +4147,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
bool isStatic = SC == SC_Static;
-
+
// [class.free]p1:
// Any allocation function for a class T is a static member
// (even if not explicitly declared static).
@@ -3649,25 +4160,34 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (Name.getCXXOverloadedOperator() == OO_Delete ||
Name.getCXXOverloadedOperator() == OO_Array_Delete)
isStatic = true;
-
+
// This is a C++ method declaration.
NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
+ D.getSourceRange().getBegin(),
NameInfo, R, TInfo,
- isStatic, SCAsWritten, isInline);
+ isStatic, SCAsWritten, isInline,
+ SourceLocation());
isVirtualOkay = !isStatic;
} else {
// Determine whether the function was written with a
// prototype. This true when:
// - we're in C++ (where every function has a prototype),
- NewFD = FunctionDecl::Create(Context, DC,
+ NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(),
NameInfo, R, TInfo, SC, SCAsWritten, isInline,
true/*HasPrototype*/);
}
+
+ if (isFriend && !isInline && IsFunctionDefinition) {
+ // C++ [class.friend]p5
+ // A function can be defined in a friend declaration of a
+ // class . . . . Such a function is implicitly inline.
+ NewFD->setImplicitlyInline();
+ }
+
SetNestedNameSpecifier(NewFD, D);
isExplicitSpecialization = false;
isFunctionTemplateSpecialization = false;
- NumMatchedTemplateParamLists = TemplateParamLists.size();
if (D.isInvalidType())
NewFD->setInvalidDecl();
@@ -3680,7 +4200,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// determine whether we have a template or a template specialization.
bool Invalid = false;
if (TemplateParameterList *TemplateParams
- = MatchTemplateParametersToScopeSpecifier(
+ = MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getSourceRange().getBegin(),
D.getCXXScopeSpec(),
TemplateParamLists.get(),
@@ -3688,54 +4208,71 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
isFriend,
isExplicitSpecialization,
Invalid)) {
- // All but one template parameter lists have been matching.
- --NumMatchedTemplateParamLists;
-
- if (TemplateParams->size() > 0) {
- // This is a function template
-
- // Check that we can declare a template here.
- if (CheckTemplateDeclScope(S, TemplateParams))
- return 0;
-
- FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
- NewFD->getLocation(),
- Name, TemplateParams,
- NewFD);
- FunctionTemplate->setLexicalDeclContext(CurContext);
- NewFD->setDescribedFunctionTemplate(FunctionTemplate);
- } else {
- // This is a function template specialization.
- isFunctionTemplateSpecialization = true;
-
- // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
- if (isFriend && isFunctionTemplateSpecialization) {
- // We want to remove the "template<>", found here.
- SourceRange RemoveRange = TemplateParams->getSourceRange();
-
- // If we remove the template<> and the name is not a
- // template-id, we're actually silently creating a problem:
- // the friend declaration will refer to an untemplated decl,
- // and clearly the user wants a template specialization. So
- // we need to insert '<>' after the name.
- SourceLocation InsertLoc;
- if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
- InsertLoc = D.getName().getSourceRange().getEnd();
- InsertLoc = PP.getLocForEndOfToken(InsertLoc);
- }
+ if (TemplateParams->size() > 0) {
+ // This is a function template
- Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
- << Name << RemoveRange
- << FixItHint::CreateRemoval(RemoveRange)
- << FixItHint::CreateInsertion(InsertLoc, "<>");
- }
- }
+ // Check that we can declare a template here.
+ if (CheckTemplateDeclScope(S, TemplateParams))
+ return 0;
+
+ // A destructor cannot be a template.
+ if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
+ Diag(NewFD->getLocation(), diag::err_destructor_template);
+ return 0;
}
- if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
- NewFD->setTemplateParameterListsInfo(Context,
- NumMatchedTemplateParamLists,
- TemplateParamLists.release());
+ FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
+ NewFD->getLocation(),
+ Name, TemplateParams,
+ NewFD);
+ FunctionTemplate->setLexicalDeclContext(CurContext);
+ NewFD->setDescribedFunctionTemplate(FunctionTemplate);
+
+ // For source fidelity, store the other template param lists.
+ if (TemplateParamLists.size() > 1) {
+ NewFD->setTemplateParameterListsInfo(Context,
+ TemplateParamLists.size() - 1,
+ TemplateParamLists.release());
+ }
+ } else {
+ // This is a function template specialization.
+ isFunctionTemplateSpecialization = true;
+ // For source fidelity, store all the template param lists.
+ NewFD->setTemplateParameterListsInfo(Context,
+ TemplateParamLists.size(),
+ TemplateParamLists.release());
+
+ // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
+ if (isFriend) {
+ // We want to remove the "template<>", found here.
+ SourceRange RemoveRange = TemplateParams->getSourceRange();
+
+ // If we remove the template<> and the name is not a
+ // template-id, we're actually silently creating a problem:
+ // the friend declaration will refer to an untemplated decl,
+ // and clearly the user wants a template specialization. So
+ // we need to insert '<>' after the name.
+ SourceLocation InsertLoc;
+ if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ InsertLoc = D.getName().getSourceRange().getEnd();
+ InsertLoc = PP.getLocForEndOfToken(InsertLoc);
+ }
+
+ Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
+ << Name << RemoveRange
+ << FixItHint::CreateRemoval(RemoveRange)
+ << FixItHint::CreateInsertion(InsertLoc, "<>");
+ }
+ }
+ }
+ else {
+ // All template param lists were matched against the scope specifier:
+ // this is NOT (an explicit specialization of) a template.
+ if (TemplateParamLists.size() > 0)
+ // For source fidelity, store all the template param lists.
+ NewFD->setTemplateParameterListsInfo(Context,
+ TemplateParamLists.size(),
+ TemplateParamLists.release());
}
if (Invalid) {
@@ -3802,7 +4339,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
// Filter out previous declarations that don't match the scope.
- FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage());
+ FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage(),
+ isExplicitSpecialization ||
+ isFunctionTemplateSpecialization);
if (isFriend) {
// For now, claim that the objects have no previous declaration.
@@ -3863,8 +4402,13 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// In C++, the empty parameter-type-list must be spelled "void"; a
// typedef of void is not permitted.
if (getLangOptions().CPlusPlus &&
- Param->getType().getUnqualifiedType() != Context.VoidTy)
- Diag(Param->getLocation(), diag::err_param_typedef_of_void);
+ Param->getType().getUnqualifiedType() != Context.VoidTy) {
+ bool IsTypeAlias = false;
+ if (const TypedefType *TT = Param->getType()->getAs<TypedefType>())
+ IsTypeAlias = isa<TypeAliasDecl>(TT->getDecl());
+ Diag(Param->getLocation(), diag::err_param_typedef_of_void)
+ << IsTypeAlias;
+ }
} else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
@@ -3892,6 +4436,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
AE = FT->arg_type_end(); AI != AE; ++AI) {
ParmVarDecl *Param =
BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI);
+ Param->setScopeInfo(0, Params.size());
Params.push_back(Param);
}
} else {
@@ -3977,9 +4522,15 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Previous))
NewFD->setInvalidDecl();
} else if (isFunctionTemplateSpecialization) {
- if (CheckFunctionTemplateSpecialization(NewFD,
- (HasExplicitTemplateArgs ? &TemplateArgs : 0),
- Previous))
+ if (CurContext->isDependentContext() && CurContext->isRecord()
+ && !isFriend) {
+ Diag(NewFD->getLocation(), diag::err_function_specialization_in_class)
+ << NewFD->getDeclName();
+ NewFD->setInvalidDecl();
+ return 0;
+ } else if (CheckFunctionTemplateSpecialization(NewFD,
+ (HasExplicitTemplateArgs ? &TemplateArgs : 0),
+ Previous))
NewFD->setInvalidDecl();
} else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD)) {
if (CheckMemberSpecialization(NewFD, Previous))
@@ -4049,7 +4600,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// are situations where these conditions don't apply and we
// can actually do this check immediately.
if (isFriend &&
- (NumMatchedTemplateParamLists ||
+ (TemplateParamLists.size() ||
D.getCXXScopeSpec().getScopeRep()->isDependent() ||
CurContext->isDependentContext())) {
// ignore these
@@ -4146,7 +4697,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
RegisterLocallyScopedExternCDecl(NewFD, Previous, S);
// Set this FunctionDecl's range up to the right paren.
- NewFD->setLocEnd(D.getSourceRange().getEnd());
+ NewFD->setRangeEnd(D.getSourceRange().getEnd());
if (getLangOptions().CPlusPlus) {
if (FunctionTemplate) {
@@ -4420,8 +4971,7 @@ void Sema::CheckMain(FunctionDecl* FD) {
// Darwin passes an undocumented fourth argument of type char**. If
// other platforms start sprouting these, the logic below will start
// getting shifty.
- if (nparams == 4 &&
- Context.Target.getTriple().getOS() == llvm::Triple::Darwin)
+ if (nparams == 4 && Context.Target.getTriple().isOSDarwin())
HasExtraParameters = false;
if (HasExtraParameters) {
@@ -4493,6 +5043,46 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
return true;
}
+namespace {
+ // Visits an initialization expression to see if OrigDecl is evaluated in
+ // its own initialization and throws a warning if it does.
+ class SelfReferenceChecker
+ : public EvaluatedExprVisitor<SelfReferenceChecker> {
+ Sema &S;
+ Decl *OrigDecl;
+
+ public:
+ typedef EvaluatedExprVisitor<SelfReferenceChecker> Inherited;
+
+ SelfReferenceChecker(Sema &S, Decl *OrigDecl) : Inherited(S.Context),
+ S(S), OrigDecl(OrigDecl) { }
+
+ void VisitExpr(Expr *E) {
+ if (isa<ObjCMessageExpr>(*E)) return;
+ Inherited::VisitExpr(E);
+ }
+
+ void VisitImplicitCastExpr(ImplicitCastExpr *E) {
+ CheckForSelfReference(E);
+ Inherited::VisitImplicitCastExpr(E);
+ }
+
+ void CheckForSelfReference(ImplicitCastExpr *E) {
+ if (E->getCastKind() != CK_LValueToRValue) return;
+ Expr* SubExpr = E->getSubExpr()->IgnoreParenImpCasts();
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SubExpr);
+ if (!DRE) return;
+ Decl* ReferenceDecl = DRE->getDecl();
+ if (OrigDecl != ReferenceDecl) return;
+ LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName,
+ Sema::NotForRedeclaration);
+ S.Diag(SubExpr->getLocStart(), diag::warn_uninit_self_reference_in_init)
+ << Result.getLookupName() << OrigDecl->getLocation()
+ << SubExpr->getSourceRange();
+ }
+ };
+}
+
/// AddInitializerToDecl - Adds the initializer Init to the
/// declaration dcl. If DirectInit is true, this is C++ direct
/// initialization rather than copy initialization.
@@ -4503,6 +5093,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
if (RealDecl == 0 || RealDecl->isInvalidDecl())
return;
+ // Check for self-references within variable initializers.
+ if (VarDecl *vd = dyn_cast<VarDecl>(RealDecl)) {
+ // Variables declared within a function/method body are handled
+ // by a dataflow analysis.
+ if (!vd->hasLocalStorage() && !vd->isStaticLocal())
+ SelfReferenceChecker(*this, RealDecl).VisitExpr(Init);
+ }
+ else {
+ SelfReferenceChecker(*this, RealDecl).VisitExpr(Init);
+ }
+
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
// With declarators parsed the way they are, the parser cannot
// distinguish between a normal initializer and a pure-specifier.
@@ -4533,15 +5134,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
- QualType DeducedType;
- if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) {
+ TypeSourceInfo *DeducedType = 0;
+ if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType))
Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
<< VDecl->getDeclName() << VDecl->getType() << Init->getType()
<< Init->getSourceRange();
+ if (!DeducedType) {
RealDecl->setInvalidDecl();
return;
}
- VDecl->setType(DeducedType);
+ VDecl->setTypeSourceInfo(DeducedType);
+ VDecl->setType(DeducedType->getType());
// If this is a redeclaration, check that the type we just deduced matches
// the previously declared type.
@@ -4952,7 +5555,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
const RecordType *Record
= Context.getBaseElementType(Type)->getAs<RecordType>();
- if (Record && getLangOptions().CPlusPlus && !getLangOptions().CPlusPlus0x &&
+ if (Record && getLangOptions().CPlusPlus &&
cast<CXXRecordDecl>(Record->getDecl())->isPOD()) {
// C++03 [dcl.init]p9:
// If no initializer is specified for an object, and the
@@ -4965,7 +5568,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
// any, have an indeterminate initial value); if the object
// or any of its subobjects are of const-qualified type, the
// program is ill-formed.
- // FIXME: DPG thinks it is very fishy that C++0x disables this.
} else {
// Check for jumps past the implicit initializer. C++0x
// clarifies that this applies to a "variable with automatic
@@ -4990,6 +5592,47 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
}
}
+void Sema::ActOnCXXForRangeDecl(Decl *D) {
+ VarDecl *VD = dyn_cast<VarDecl>(D);
+ if (!VD) {
+ Diag(D->getLocation(), diag::err_for_range_decl_must_be_var);
+ D->setInvalidDecl();
+ return;
+ }
+
+ VD->setCXXForRangeDecl(true);
+
+ // for-range-declaration cannot be given a storage class specifier.
+ int Error = -1;
+ switch (VD->getStorageClassAsWritten()) {
+ case SC_None:
+ break;
+ case SC_Extern:
+ Error = 0;
+ break;
+ case SC_Static:
+ Error = 1;
+ break;
+ case SC_PrivateExtern:
+ Error = 2;
+ break;
+ case SC_Auto:
+ Error = 3;
+ break;
+ case SC_Register:
+ Error = 4;
+ break;
+ }
+ // FIXME: constexpr isn't allowed here.
+ //if (DS.isConstexprSpecified())
+ // Error = 5;
+ if (Error != -1) {
+ Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class)
+ << VD->getDeclName() << Error;
+ D->setInvalidDecl();
+ }
+}
+
void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
if (var->isInvalidDecl()) return;
@@ -5058,7 +5701,7 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
if (Decl *D = Group[i])
Decls.push_back(D);
- return BuildDeclaratorGroup(Decls.data(), Decls.size(),
+ return BuildDeclaratorGroup(Decls.data(), Decls.size(),
DS.getTypeSpecType() == DeclSpec::TST_auto);
}
@@ -5195,12 +5838,18 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// the enclosing context. This prevents them from accidentally
// looking like class members in C++.
ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(),
- TInfo, parmDeclType, II,
- D.getIdentifierLoc(),
+ D.getSourceRange().getBegin(),
+ D.getIdentifierLoc(), II,
+ parmDeclType, TInfo,
StorageClass, StorageClassAsWritten);
if (D.isInvalidType())
- New->setInvalidDecl();
+ New->setInvalidDecl();
+
+ assert(S->isFunctionPrototypeScope());
+ assert(S->getFunctionPrototypeDepth() >= 1);
+ New->setScopeInfo(S->getFunctionPrototypeDepth() - 1,
+ S->getNextFunctionPrototypeIndex());
// Add the parameter declaration into this scope.
S->AddDecl(New);
@@ -5220,7 +5869,10 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC,
SourceLocation Loc,
QualType T) {
- ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, 0,
+ /* FIXME: setting StartLoc == Loc.
+ Would it be worth to modify callers so as to provide proper source
+ location for the unnamed parameters, embedding the parameter's type? */
+ ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, 0,
T, Context.getTrivialTypeSourceInfo(T, Loc),
SC_None, SC_None, 0);
Param->setImplicit();
@@ -5272,14 +5924,13 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param,
}
}
-ParmVarDecl *Sema::CheckParameter(DeclContext *DC,
- TypeSourceInfo *TSInfo, QualType T,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
+ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation NameLoc, IdentifierInfo *Name,
+ QualType T, TypeSourceInfo *TSInfo,
VarDecl::StorageClass StorageClass,
VarDecl::StorageClass StorageClassAsWritten) {
- ParmVarDecl *New = ParmVarDecl::Create(Context, DC, NameLoc, Name,
- adjustParameterType(T), TSInfo,
+ ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name,
+ adjustParameterType(T), TSInfo,
StorageClass, StorageClassAsWritten,
0);
@@ -5331,7 +5982,8 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
// Implicitly declare the argument as type 'int' for lack of a better
// type.
- DeclSpec DS;
+ AttributeFactory attrs;
+ DeclSpec DS(attrs);
const char* PrevSpec; // unused
unsigned DiagID; // unused
DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc,
@@ -5374,7 +6026,7 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) {
return false;
// Don't warn about inline functions.
- if (FD->isInlineSpecified())
+ if (FD->isInlined())
return false;
// Don't warn about function templates.
@@ -5400,6 +6052,22 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) {
return MissingPrototype;
}
+void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) {
+ // Don't complain if we're in GNU89 mode and the previous definition
+ // was an extern inline function.
+ const FunctionDecl *Definition;
+ if (FD->hasBody(Definition) &&
+ !canRedefineFunction(Definition, getLangOptions())) {
+ if (getLangOptions().GNUMode && Definition->isInlineSpecified() &&
+ Definition->getStorageClass() == SC_Extern)
+ Diag(FD->getLocation(), diag::err_redefinition_extern_inline)
+ << FD->getDeclName() << getLangOptions().CPlusPlus;
+ else
+ Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
+ Diag(Definition->getLocation(), diag::note_previous_definition);
+ }
+}
+
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// Clear the last template instantiation error context.
LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation();
@@ -5417,19 +6085,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
PushFunctionScope();
// See if this is a redefinition.
- // But don't complain if we're in GNU89 mode and the previous definition
- // was an extern inline function.
- const FunctionDecl *Definition;
- if (FD->hasBody(Definition) &&
- !canRedefineFunction(Definition, getLangOptions())) {
- if (getLangOptions().GNUMode && Definition->isInlineSpecified() &&
- Definition->getStorageClass() == SC_Extern)
- Diag(FD->getLocation(), diag::err_redefinition_extern_inline)
- << FD->getDeclName() << getLangOptions().CPlusPlus;
- else
- Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
- Diag(Definition->getLocation(), diag::note_previous_definition);
- }
+ if (!FD->isLateTemplateParsed())
+ CheckForFunctionRedefinition(FD);
// Builtin functions cannot be defined.
if (unsigned BuiltinID = FD->getBuiltinID()) {
@@ -5481,7 +6138,9 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
if (DA && (!FD->getAttr<DLLExportAttr>())) {
// dllimport attribute cannot be directly applied to definition.
- if (!DA->isInherited()) {
+ // Microsoft accepts dllimport for functions defined within class scope.
+ if (!DA->isInherited() &&
+ !(LangOpts.Microsoft && FD->getLexicalDeclContext()->isRecord())) {
Diag(FD->getLocation(),
diag::err_attribute_can_be_applied_only_to_symbol_declaration)
<< "dllimport";
@@ -5615,7 +6274,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// If any errors have occurred, clear out any temporaries that may have
// been leftover. This ensures that these temporaries won't be picked up for
// deletion in some later function.
- if (PP.getDiagnostics().hasErrorOccurred())
+ if (PP.getDiagnostics().hasErrorOccurred() ||
+ PP.getDiagnostics().getSuppressAllDiagnostics())
ExprTemporaries.clear();
else if (!isa<FunctionTemplateDecl>(dcl)) {
// Since the body is valid, issue any analysis-based warnings that are
@@ -5666,17 +6326,18 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
// Set a Declarator for the implicit definition: int foo();
const char *Dummy;
- DeclSpec DS;
+ AttributeFactory attrFactory;
+ DeclSpec DS(attrFactory);
unsigned DiagID;
bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID);
(void)Error; // Silence warning.
assert(!Error && "Error setting up implicit decl!");
Declarator D(DS, Declarator::BlockContext);
- D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(),
- false, false, SourceLocation(), 0,
+ D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0,
0, 0, true, SourceLocation(),
- false, SourceLocation(),
- false, 0,0,0, Loc, Loc, D),
+ EST_None, SourceLocation(),
+ 0, 0, 0, 0, Loc, Loc, D),
+ DS.getAttributes(),
SourceLocation());
D.SetIdentifier(&II, Loc);
@@ -5784,6 +6445,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
// Scope manipulation handled by caller.
TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext,
+ D.getSourceRange().getBegin(),
D.getIdentifierLoc(),
D.getIdentifier(),
TInfo);
@@ -5810,7 +6472,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
// Do nothing if the tag is not anonymous or already has an
// associated typedef (from an earlier typedef in this decl group).
if (tagFromDeclSpec->getIdentifier()) break;
- if (tagFromDeclSpec->getTypedefForAnonDecl()) break;
+ if (tagFromDeclSpec->getTypedefNameForAnonDecl()) break;
// A well-formed anonymous tag must always be a TUK_Definition.
assert(tagFromDeclSpec->isThisDeclarationADefinition());
@@ -5820,7 +6482,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
break;
// Otherwise, set this is the anon-decl typedef for the tag.
- tagFromDeclSpec->setTypedefForAnonDecl(NewTD);
+ tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD);
break;
}
@@ -5897,36 +6559,33 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// FIXME: Check explicit specializations more carefully.
bool isExplicitSpecialization = false;
- unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
bool Invalid = false;
// We only need to do this matching if we have template parameters
// or a scope specifier, which also conveniently avoids this work
// for non-C++ cases.
- if (NumMatchedTemplateParamLists ||
+ if (TemplateParameterLists.size() > 0 ||
(SS.isNotEmpty() && TUK != TUK_Reference)) {
if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
TemplateParameterLists.get(),
- TemplateParameterLists.size(),
+ TemplateParameterLists.size(),
TUK == TUK_Friend,
isExplicitSpecialization,
Invalid)) {
- // All but one template parameter lists have been matching.
- --NumMatchedTemplateParamLists;
-
if (TemplateParams->size() > 0) {
// This is a declaration or definition of a class template (which may
// be a member of another template).
+
if (Invalid)
return 0;
-
+
OwnedDecl = false;
DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
SS, Name, NameLoc, Attr,
- TemplateParams,
- AS);
- TemplateParameterLists.release();
+ TemplateParams, AS,
+ TemplateParameterLists.size() - 1,
+ (TemplateParameterList**) TemplateParameterLists.release());
return Result.get();
} else {
// The "template<>" header is extraneous.
@@ -6164,7 +6823,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// okay according to the likely resolution of an open issue;
// see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407
if (getLangOptions().CPlusPlus) {
- if (TypedefDecl *TD = dyn_cast<TypedefDecl>(PrevDecl)) {
+ if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(PrevDecl)) {
if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
TagDecl *Tag = TT->getDecl();
if (Tag->getDeclName() == Name &&
@@ -6184,7 +6843,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// in the same scope (so that the definition/declaration completes or
// rementions the tag), reuse the decl.
if (TUK == TUK_Reference || TUK == TUK_Friend ||
- isDeclInScope(PrevDecl, SearchDC, S)) {
+ isDeclInScope(PrevDecl, SearchDC, S, isExplicitSpecialization)) {
// Make sure that this wasn't declared as an enum and now used as a
// struct or something similar.
if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, KWLoc, *Name)) {
@@ -6322,30 +6981,34 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
!Previous.isForRedeclaration()) {
unsigned Kind = 0;
if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
- else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2;
+ else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2;
+ else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 3;
Diag(NameLoc, diag::err_tag_reference_non_tag) << Kind;
Diag(PrevDecl->getLocation(), diag::note_declared_at);
Invalid = true;
// Otherwise, only diagnose if the declaration is in scope.
- } else if (!isDeclInScope(PrevDecl, SearchDC, S)) {
+ } else if (!isDeclInScope(PrevDecl, SearchDC, S,
+ isExplicitSpecialization)) {
// do nothing
// Diagnose implicit declarations introduced by elaborated types.
} else if (TUK == TUK_Reference || TUK == TUK_Friend) {
unsigned Kind = 0;
if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
- else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2;
+ else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2;
+ else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 3;
Diag(NameLoc, diag::err_tag_reference_conflict) << Kind;
Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
Invalid = true;
// Otherwise it's a declaration. Call out a particularly common
// case here.
- } else if (isa<TypedefDecl>(PrevDecl)) {
+ } else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(PrevDecl)) {
+ unsigned Kind = 0;
+ if (isa<TypeAliasDecl>(PrevDecl)) Kind = 1;
Diag(NameLoc, diag::err_tag_definition_of_typedef)
- << Name
- << cast<TypedefDecl>(PrevDecl)->getUnderlyingType();
+ << Name << Kind << TND->getUnderlyingType();
Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
Invalid = true;
@@ -6385,7 +7048,7 @@ CreateNewDecl:
if (Kind == TTK_Enum) {
// FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
// enum X { A, B, C } D; D should chain to X.
- New = EnumDecl::Create(Context, SearchDC, Loc, Name, KWLoc,
+ New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name,
cast_or_null<EnumDecl>(PrevDecl), ScopedEnum,
ScopedEnumUsesClassTag, !EnumUnderlying.isNull());
// If this is an undefined enum, warn.
@@ -6431,13 +7094,13 @@ CreateNewDecl:
// struct X { int A; } D; D should chain to X.
if (getLangOptions().CPlusPlus) {
// FIXME: Look for a way to use RecordDecl for simple structs.
- New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc,
+ New = CXXRecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name,
cast_or_null<CXXRecordDecl>(PrevDecl));
-
+
if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit()))
StdBadAlloc = cast<CXXRecordDecl>(New);
} else
- New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc,
+ New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name,
cast_or_null<RecordDecl>(PrevDecl));
}
@@ -6445,9 +7108,9 @@ CreateNewDecl:
if (SS.isNotEmpty()) {
if (SS.isSet()) {
New->setQualifierInfo(SS.getWithLocInContext(Context));
- if (NumMatchedTemplateParamLists > 0) {
+ if (TemplateParameterLists.size() > 0) {
New->setTemplateParameterListsInfo(Context,
- NumMatchedTemplateParamLists,
+ TemplateParameterLists.size(),
(TemplateParameterList**) TemplateParameterLists.release());
}
}
@@ -6466,6 +7129,8 @@ CreateNewDecl:
// the #pragma tokens are effectively skipped over during the
// parsing of the struct).
AddAlignmentAttributesForRecord(RD);
+
+ AddMsStructLayoutForRecord(RD);
}
// If this is a specialization of a member class (of a class template),
@@ -6541,7 +7206,7 @@ void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
}
void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
- ClassVirtSpecifiers &CVS,
+ SourceLocation FinalLoc,
SourceLocation LBraceLoc) {
AdjustDeclIfTemplate(TagD);
CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD);
@@ -6551,10 +7216,8 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
if (!Record->getIdentifier())
return;
- if (CVS.isFinalSpecified())
- Record->addAttr(new (Context) FinalAttr(CVS.getFinalLoc(), Context));
- if (CVS.isExplicitSpecified())
- Record->addAttr(new (Context) ExplicitAttr(CVS.getExplicitLoc(), Context));
+ if (FinalLoc.isValid())
+ Record->addAttr(new (Context) FinalAttr(FinalLoc, Context));
// C++ [class]p2:
// [...] The class-name is also inserted into the scope of the
@@ -6562,10 +7225,9 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
// purposes of access checking, the injected-class-name is treated
// as if it were a public member name.
CXXRecordDecl *InjectedClassName
- = CXXRecordDecl::Create(Context, Record->getTagKind(),
- CurContext, Record->getLocation(),
+ = CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext,
+ Record->getLocStart(), Record->getLocation(),
Record->getIdentifier(),
- Record->getTagKeywordLoc(),
/*PrevDecl=*/0,
/*DelayTypeCreation=*/true);
Context.getTypeDeclType(InjectedClassName, Record);
@@ -6852,7 +7514,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
}
}
- FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, TInfo,
+ FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo,
BitWidth, Mutable);
if (InvalidDecl)
NewFD->setInvalidDecl();
@@ -7152,8 +7814,8 @@ Decl *Sema::ActOnIvar(Scope *S,
}
// Construct the decl.
- ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context,
- EnclosingContext, Loc, II, T,
+ ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, EnclosingContext,
+ DeclStart, Loc, II, T,
TInfo, ac, (Expr *)BitfieldWidth);
if (II) {
@@ -7216,7 +7878,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl,
Expr * BW = IntegerLiteral::Create(Context, Zero, Context.CharTy, DeclLoc);
Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(EnclosingDecl),
- DeclLoc, 0,
+ DeclLoc, DeclLoc, 0,
Context.CharTy,
Context.CreateTypeSourceInfo(Context.CharTy),
ObjCIvarDecl::Private, BW,
@@ -7281,20 +7943,27 @@ void Sema::ActOnFields(Scope* S,
continue;
} else if (FDTy->isIncompleteArrayType() && Record &&
((i == NumFields - 1 && !Record->isUnion()) ||
- (getLangOptions().Microsoft &&
+ ((getLangOptions().Microsoft || getLangOptions().CPlusPlus) &&
(i == NumFields - 1 || Record->isUnion())))) {
// Flexible array member.
- // Microsoft is more permissive regarding flexible array.
+ // Microsoft and g++ is more permissive regarding flexible array.
// It will accept flexible array in union and also
// as the sole element of a struct/class.
if (getLangOptions().Microsoft) {
if (Record->isUnion())
- Diag(FD->getLocation(), diag::ext_flexible_array_union)
+ Diag(FD->getLocation(), diag::ext_flexible_array_union_ms)
+ << FD->getDeclName();
+ else if (NumFields == 1)
+ Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_ms)
+ << FD->getDeclName() << Record->getTagKind();
+ } else if (getLangOptions().CPlusPlus) {
+ if (Record->isUnion())
+ Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu)
<< FD->getDeclName();
else if (NumFields == 1)
- Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate)
+ Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_gnu)
<< FD->getDeclName() << Record->getTagKind();
- } else if (NumNamedMembers < 1) {
+ } else if (NumNamedMembers < 1) {
Diag(FD->getLocation(), diag::err_flexible_array_empty_struct)
<< FD->getDeclName();
FD->setInvalidDecl();
@@ -7547,7 +8216,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
<< (EnumVal.isUnsigned() || EnumVal.isNonNegative());
else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
// Force the type of the expression to 'int'.
- ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast);
+ Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).take();
}
}
@@ -7560,12 +8229,12 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
if (getLangOptions().Microsoft) {
Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy;
- ImpCastExprToType(Val, EltTy, CK_IntegralCast);
+ Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
} else
Diag(IdLoc, diag::err_enumerator_too_large)
<< EltTy;
} else
- ImpCastExprToType(Val, EltTy, CK_IntegralCast);
+ Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
}
else {
// C++0x [dcl.enum]p5:
@@ -7949,11 +8618,14 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
NumPositiveBits, NumNegativeBits);
}
-Decl *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr) {
+Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
StringLiteral *AsmString = cast<StringLiteral>(expr);
FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext,
- Loc, AsmString);
+ AsmString, StartLoc,
+ EndLoc);
CurContext->addDecl(New);
return New;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
index 893cf6a..7f93ab7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
@@ -24,6 +24,26 @@
using namespace clang;
using namespace sema;
+/// These constants match the enumerated choices of
+/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
+enum {
+ ExpectedFunction,
+ ExpectedUnion,
+ ExpectedVariableOrFunction,
+ ExpectedFunctionOrMethod,
+ ExpectedParameter,
+ ExpectedParameterOrMethod,
+ ExpectedFunctionMethodOrBlock,
+ ExpectedClassOrVirtualMethod,
+ ExpectedFunctionMethodOrParameter,
+ ExpectedClass,
+ ExpectedVirtualMethod,
+ ExpectedClassMember,
+ ExpectedVariable,
+ ExpectedMethod,
+ ExpectedVariableFunctionOrLabel
+};
+
//===----------------------------------------------------------------------===//
// Helper functions
//===----------------------------------------------------------------------===//
@@ -35,7 +55,7 @@ static const FunctionType *getFunctionType(const Decl *d,
Ty = decl->getType();
else if (const FieldDecl *decl = dyn_cast<FieldDecl>(d))
Ty = decl->getType();
- else if (const TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
+ else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(d))
Ty = decl->getUnderlyingType();
else
return 0;
@@ -81,8 +101,8 @@ static bool isFunctionOrMethodOrBlock(const Decl *d) {
/// Return true if the given decl has a declarator that should have
/// been processed by Sema::GetTypeForDeclarator.
static bool hasDeclarator(const Decl *d) {
- // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
- return isa<DeclaratorDecl>(d) || isa<BlockDecl>(d) || isa<TypedefDecl>(d);
+ // In some sense, TypedefNameDecl really *ought* to be a DeclaratorDecl.
+ return isa<DeclaratorDecl>(d) || isa<BlockDecl>(d) || isa<TypedefNameDecl>(d);
}
/// hasFunctionProto - Return true if the given decl has a argument
@@ -182,7 +202,7 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
static void HandleExtVectorTypeAttr(Scope *scope, Decl *d,
const AttributeList &Attr, Sema &S) {
- TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
+ TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(d);
if (tDecl == 0) {
S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
return;
@@ -241,6 +261,13 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
+static void HandleMsStructAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (TagDecl *TD = dyn_cast<TagDecl>(d))
+ TD->addAttr(::new (S.Context) MsStructAttr(Attr.getLoc(), S.Context));
+ else
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+}
+
static void HandleIBAction(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() > 0) {
@@ -332,7 +359,7 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// ignore it as well
if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunction;
return;
}
@@ -474,8 +501,8 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
}
if (!isFunction(d) || !hasFunctionProto(d)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL.getName()
- << 0 /*function*/;
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL.getName() << ExpectedFunction;
return;
}
@@ -615,7 +642,7 @@ static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isa<VarDecl>(d) && !isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << 2 /*variables and functions*/;
+ << Attr.getName() << ExpectedVariableOrFunction;
return;
}
@@ -701,7 +728,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- if (S.Context.Target.getTriple().getOS() == llvm::Triple::Darwin) {
+ if (S.Context.Target.getTriple().isOSDarwin()) {
S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin);
return;
}
@@ -722,7 +749,7 @@ static void HandleNakedAttr(Decl *d, const AttributeList &Attr,
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunction;
return;
}
@@ -732,14 +759,14 @@ static void HandleNakedAttr(Decl *d, const AttributeList &Attr,
static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
Sema &S) {
// Check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
+ if (Attr.hasParameterOrArguments()) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
return;
}
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunction;
return;
}
@@ -748,7 +775,7 @@ static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// Check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
+ if (Attr.hasParameterOrArguments()) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
return;
}
@@ -780,7 +807,7 @@ static void HandleNoCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) {
d->addAttr(::new (S.Context) NoCommonAttr(Attr.getLoc(), S.Context));
else
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 12 /* variable */;
+ << Attr.getName() << ExpectedVariable;
}
static void HandleCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -789,7 +816,7 @@ static void HandleCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) {
d->addAttr(::new (S.Context) CommonAttr(Attr.getLoc(), S.Context));
else
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 12 /* variable */;
+ << Attr.getName() << ExpectedVariable;
}
static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) {
@@ -799,7 +826,7 @@ static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) {
if (!isa<ObjCMethodDecl>(d)) {
S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << attr.getName() << 0 /*function*/;
+ << attr.getName() << ExpectedFunctionOrMethod;
return;
}
@@ -807,7 +834,7 @@ static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) {
}
bool Sema::CheckNoReturnAttr(const AttributeList &attr) {
- if (attr.getNumArgs() != 0) {
+ if (attr.hasParameterOrArguments()) {
Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
attr.setInvalid();
return true;
@@ -834,7 +861,7 @@ static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
S.Diag(Attr.getLoc(),
Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
: diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunctionMethodOrBlock;
return;
}
}
@@ -870,7 +897,7 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr,
*/
if (!isa<RecordDecl>(d)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << 9 /*class*/;
+ << Attr.getName() << ExpectedClass;
return;
}
@@ -907,7 +934,7 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr,
static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << 8 /*function, method, or parameter*/;
+ << Attr.getName() << ExpectedFunctionMethodOrParameter;
return;
}
// FIXME: Actually store the attribute on the declaration
@@ -915,7 +942,7 @@ static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
+ if (Attr.hasParameterOrArguments()) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
return;
}
@@ -923,7 +950,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isa<VarDecl>(d) && !isa<ObjCIvarDecl>(d) && !isFunctionOrMethod(d) &&
!isa<TypeDecl>(d) && !isa<LabelDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 14 /*variable, function, labels*/;
+ << Attr.getName() << ExpectedVariableFunctionOrLabel;
return;
}
@@ -932,7 +959,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
+ if (Attr.hasParameterOrArguments()) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
return;
}
@@ -944,7 +971,7 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
} else if (!isFunctionOrMethod(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 2 /*variable and function*/;
+ << Attr.getName() << ExpectedVariableOrFunction;
return;
}
@@ -953,9 +980,8 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
- if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << "0 or 1";
+ if (Attr.getNumArgs() > 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
return;
}
@@ -974,7 +1000,7 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunction;
return;
}
@@ -984,9 +1010,8 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
- if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << "0 or 1";
+ if (Attr.getNumArgs() > 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
return;
}
@@ -1005,7 +1030,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunction;
return;
}
@@ -1016,8 +1041,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
unsigned NumArgs = Attr.getNumArgs();
if (NumArgs > 1) {
- S.Diag(Attr.getLoc(),
- diag::err_attribute_wrong_number_arguments) << "0 or 1";
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
return;
}
@@ -1039,8 +1063,7 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
unsigned NumArgs = Attr.getNumArgs();
if (NumArgs > 1) {
- S.Diag(Attr.getLoc(),
- diag::err_attribute_wrong_number_arguments) << "0 or 1";
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
return;
}
@@ -1058,6 +1081,59 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context, Str));
}
+static void HandleAvailabilityAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+ IdentifierInfo *Platform = Attr.getParameterName();
+ SourceLocation PlatformLoc = Attr.getParameterLoc();
+
+ llvm::StringRef PlatformName
+ = AvailabilityAttr::getPrettyPlatformName(Platform->getName());
+ if (PlatformName.empty()) {
+ S.Diag(PlatformLoc, diag::warn_availability_unknown_platform)
+ << Platform;
+
+ PlatformName = Platform->getName();
+ }
+
+ AvailabilityChange Introduced = Attr.getAvailabilityIntroduced();
+ AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated();
+ AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted();
+ bool IsUnavailable = Attr.getUnavailableLoc().isValid();
+
+ // Ensure that Introduced < Deprecated < Obsoleted (although not all
+ // of these steps are needed).
+ if (Introduced.isValid() && Deprecated.isValid() &&
+ !(Introduced.Version < Deprecated.Version)) {
+ S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering)
+ << 1 << PlatformName << Deprecated.Version.getAsString()
+ << 0 << Introduced.Version.getAsString();
+ return;
+ }
+
+ if (Introduced.isValid() && Obsoleted.isValid() &&
+ !(Introduced.Version < Obsoleted.Version)) {
+ S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering)
+ << 2 << PlatformName << Obsoleted.Version.getAsString()
+ << 0 << Introduced.Version.getAsString();
+ return;
+ }
+
+ if (Deprecated.isValid() && Obsoleted.isValid() &&
+ !(Deprecated.Version < Obsoleted.Version)) {
+ S.Diag(Deprecated.KeywordLoc, diag::warn_availability_version_ordering)
+ << 2 << PlatformName << Obsoleted.Version.getAsString()
+ << 1 << Deprecated.Version.getAsString();
+ return;
+ }
+
+ d->addAttr(::new (S.Context) AvailabilityAttr(Attr.getLoc(), S.Context,
+ Platform,
+ Introduced.Version,
+ Deprecated.Version,
+ Obsoleted.Version,
+ IsUnavailable));
+}
+
static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 1) {
@@ -1094,6 +1170,51 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
d->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type));
}
+static void HandleObjCMethodFamilyAttr(Decl *decl, const AttributeList &attr,
+ Sema &S) {
+ ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(decl);
+ if (!method) {
+ S.Diag(attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << ExpectedMethod;
+ return;
+ }
+
+ if (attr.getNumArgs() != 0 || !attr.getParameterName()) {
+ if (!attr.getParameterName() && attr.getNumArgs() == 1) {
+ S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
+ << "objc_method_family" << 1;
+ } else {
+ S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ }
+ attr.setInvalid();
+ return;
+ }
+
+ llvm::StringRef param = attr.getParameterName()->getName();
+ ObjCMethodFamilyAttr::FamilyKind family;
+ if (param == "none")
+ family = ObjCMethodFamilyAttr::OMF_None;
+ else if (param == "alloc")
+ family = ObjCMethodFamilyAttr::OMF_alloc;
+ else if (param == "copy")
+ family = ObjCMethodFamilyAttr::OMF_copy;
+ else if (param == "init")
+ family = ObjCMethodFamilyAttr::OMF_init;
+ else if (param == "mutableCopy")
+ family = ObjCMethodFamilyAttr::OMF_mutableCopy;
+ else if (param == "new")
+ family = ObjCMethodFamilyAttr::OMF_new;
+ else {
+ // Just warn and ignore it. This is future-proof against new
+ // families being used in system headers.
+ S.Diag(attr.getParameterLoc(), diag::warn_unknown_method_family);
+ return;
+ }
+
+ decl->addAttr(new (S.Context) ObjCMethodFamilyAttr(attr.getLoc(),
+ S.Context, family));
+}
+
static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
Sema &S) {
if (Attr.getNumArgs() != 0) {
@@ -1115,7 +1236,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
return;
}
- if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+ if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
QualType T = TD->getUnderlyingType();
if (!T->isPointerType() ||
!T->getAs<PointerType>()->getPointeeType()->isRecordType()) {
@@ -1168,8 +1289,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() > 2) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << "0, 1 or 2";
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2;
return;
}
@@ -1247,12 +1367,12 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
} else {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 6 /*function, method or block */;
+ << Attr.getName() << ExpectedFunctionMethodOrBlock;
return;
}
} else {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 6 /*function, method or block */;
+ << Attr.getName() << ExpectedFunctionMethodOrBlock;
return;
}
d->addAttr(::new (S.Context) SentinelAttr(Attr.getLoc(), S.Context, sentinel,
@@ -1268,7 +1388,7 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S)
if (!isFunction(D) && !isa<ObjCMethodDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunctionOrMethod;
return;
}
@@ -1289,14 +1409,14 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S)
static void HandleWeakAttr(Decl *d, const AttributeList &attr, Sema &S) {
// check the attribute arguments.
- if (attr.getNumArgs() != 0) {
+ if (attr.hasParameterOrArguments()) {
S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
return;
}
if (!isa<VarDecl>(d) && !isa<FunctionDecl>(d)) {
S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << attr.getName() << 2 /*variables and functions*/;
+ << attr.getName() << ExpectedVariableOrFunction;
return;
}
@@ -1320,27 +1440,19 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// weak_import only applies to variable & function declarations.
bool isDef = false;
- if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
- isDef = (!VD->hasExternalStorage() || VD->getInit());
- } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- isDef = FD->hasBody();
- } else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) {
- // We ignore weak import on properties and methods
- return;
- } else if (!(S.LangOpts.ObjCNonFragileABI && isa<ObjCInterfaceDecl>(D))) {
- // Don't issue the warning for darwin as target; yet, ignore the attribute.
- if (S.Context.Target.getTriple().getOS() != llvm::Triple::Darwin ||
- !isa<ObjCInterfaceDecl>(D))
+ if (!D->canBeWeakImported(isDef)) {
+ if (isDef)
+ S.Diag(Attr.getLoc(),
+ diag::warn_attribute_weak_import_invalid_on_definition)
+ << "weak_import" << 2 /*variable and function*/;
+ else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) ||
+ (S.Context.Target.getTriple().isOSDarwin() &&
+ isa<ObjCInterfaceDecl>(D))) {
+ // Nothing to warn about here.
+ } else
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 2 /*variable and function*/;
- return;
- }
+ << Attr.getName() << ExpectedVariableOrFunction;
- // Merge should handle any subsequent violations.
- if (isDef) {
- S.Diag(Attr.getLoc(),
- diag::warn_attribute_weak_import_invalid_on_definition)
- << "weak_import" << 2 /*variable and function*/;
return;
}
@@ -1409,7 +1521,7 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
+ if (Attr.hasParameterOrArguments()) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
return;
}
@@ -1419,7 +1531,7 @@ static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
+ if (Attr.hasParameterOrArguments()) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
return;
}
@@ -1506,7 +1618,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunction;
return;
}
@@ -1674,7 +1786,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isFunctionOrMethodOrBlock(d) || !hasFunctionProto(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunction;
return;
}
@@ -1807,7 +1919,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
// Try to find the underlying union declaration.
RecordDecl *RD = 0;
- TypedefDecl *TD = dyn_cast<TypedefDecl>(d);
+ TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(d);
if (TD && TD->getUnderlyingType()->isUnionType())
RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
else
@@ -1815,7 +1927,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
if (!RD || !RD->isUnion()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 1 /*union*/;
+ << Attr.getName() << ExpectedUnion;
return;
}
@@ -1998,7 +2110,7 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
}
QualType OldTy;
- if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
+ if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
OldTy = TD->getUnderlyingType();
else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
OldTy = VD->getType();
@@ -2097,7 +2209,7 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
}
// Install the new type.
- if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+ if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
// FIXME: preserve existing source info.
TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy));
} else
@@ -2113,7 +2225,7 @@ static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isFunctionOrMethod(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunction;
return;
}
@@ -2129,7 +2241,7 @@ static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunction;
return;
}
@@ -2146,7 +2258,7 @@ static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr,
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunction;
return;
}
@@ -2157,14 +2269,14 @@ static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr,
static void HandleConstantAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (S.LangOpts.CUDA) {
// check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
+ if (Attr.hasParameterOrArguments()) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
return;
}
if (!isa<VarDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 12 /*variable*/;
+ << Attr.getName() << ExpectedVariable;
return;
}
@@ -2184,7 +2296,7 @@ static void HandleDeviceAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isa<FunctionDecl>(d) && !isa<VarDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 2 /*variable and function*/;
+ << Attr.getName() << ExpectedVariableOrFunction;
return;
}
@@ -2204,7 +2316,7 @@ static void HandleGlobalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunction;
return;
}
@@ -2239,7 +2351,7 @@ static void HandleHostAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunction;
return;
}
@@ -2259,7 +2371,7 @@ static void HandleSharedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isa<VarDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 12 /*variable*/;
+ << Attr.getName() << ExpectedVariable;
return;
}
@@ -2279,7 +2391,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
if (Fn == 0) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunction;
return;
}
@@ -2302,7 +2414,7 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) {
if (!isa<ObjCMethodDecl>(d)) {
S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << attr.getName() << 0 /*function*/;
+ << attr.getName() << ExpectedFunctionOrMethod;
return;
}
@@ -2322,6 +2434,30 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) {
case AttributeList::AT_pascal:
d->addAttr(::new (S.Context) PascalAttr(attr.getLoc(), S.Context));
return;
+ case AttributeList::AT_pcs: {
+ Expr *Arg = attr.getArg(0);
+ StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+ if (Str == 0 || Str->isWide()) {
+ S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
+ << "pcs" << 1;
+ attr.setInvalid();
+ return;
+ }
+
+ llvm::StringRef StrRef = Str->getString();
+ PcsAttr::PCSType PCS;
+ if (StrRef == "aapcs")
+ PCS = PcsAttr::AAPCS;
+ else if (StrRef == "aapcs-vfp")
+ PCS = PcsAttr::AAPCS_VFP;
+ else {
+ S.Diag(attr.getLoc(), diag::err_invalid_pcs);
+ attr.setInvalid();
+ return;
+ }
+
+ d->addAttr(::new (S.Context) PcsAttr(attr.getLoc(), S.Context, PCS));
+ }
default:
llvm_unreachable("unexpected attribute kind");
return;
@@ -2337,19 +2473,42 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) {
if (attr.isInvalid())
return true;
- if (attr.getNumArgs() != 0) {
+ if ((attr.getNumArgs() != 0 &&
+ !(attr.getKind() == AttributeList::AT_pcs && attr.getNumArgs() == 1)) ||
+ attr.getParameterName()) {
Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
attr.setInvalid();
return true;
}
- // TODO: diagnose uses of these conventions on the wrong target.
+ // TODO: diagnose uses of these conventions on the wrong target. Or, better
+ // move to TargetAttributesSema one day.
switch (attr.getKind()) {
case AttributeList::AT_cdecl: CC = CC_C; break;
case AttributeList::AT_fastcall: CC = CC_X86FastCall; break;
case AttributeList::AT_stdcall: CC = CC_X86StdCall; break;
case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break;
case AttributeList::AT_pascal: CC = CC_X86Pascal; break;
+ case AttributeList::AT_pcs: {
+ Expr *Arg = attr.getArg(0);
+ StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+ if (Str == 0 || Str->isWide()) {
+ Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
+ << "pcs" << 1;
+ attr.setInvalid();
+ return true;
+ }
+
+ llvm::StringRef StrRef = Str->getString();
+ if (StrRef == "aapcs") {
+ CC = CC_AAPCS;
+ break;
+ } else if (StrRef == "aapcs-vfp") {
+ CC = CC_AAPCS_VFP;
+ break;
+ }
+ // FALLS THROUGH
+ }
default: llvm_unreachable("unexpected attribute kind"); return true;
}
@@ -2365,7 +2524,7 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &attr, Sema &S) {
if (!isa<ObjCMethodDecl>(d)) {
S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << attr.getName() << 0 /*function*/;
+ << attr.getName() << ExpectedFunctionOrMethod;
return;
}
@@ -2416,14 +2575,14 @@ static void HandleLaunchBoundsAttr(Decl *d, const AttributeList &Attr, Sema &S){
if (S.LangOpts.CUDA) {
// check the attribute arguments.
if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << "1 or 2";
+ // FIXME: 0 is not okay.
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2;
return;
}
if (!isFunctionOrMethod(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
+ << Attr.getName() << ExpectedFunctionOrMethod;
return;
}
@@ -2472,7 +2631,7 @@ static void HandleNSConsumedAttr(Decl *d, const AttributeList &attr, Sema &S) {
ParmVarDecl *param = dyn_cast<ParmVarDecl>(d);
if (!param) {
S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
- << SourceRange(attr.getLoc()) << attr.getName() << 4 /*parameter*/;
+ << SourceRange(attr.getLoc()) << attr.getName() << ExpectedParameter;
return;
}
@@ -2501,7 +2660,7 @@ static void HandleNSConsumesSelfAttr(Decl *d, const AttributeList &attr,
Sema &S) {
if (!isa<ObjCMethodDecl>(d)) {
S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
- << SourceRange(attr.getLoc()) << attr.getName() << 13 /*method*/;
+ << SourceRange(attr.getLoc()) << attr.getName() << ExpectedMethod;
return;
}
@@ -2520,7 +2679,7 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &attr,
else {
S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
<< SourceRange(attr.getLoc()) << attr.getName()
- << 3 /* function or method */;
+ << ExpectedFunctionOrMethod;
return;
}
@@ -2664,6 +2823,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D,
case AttributeList::AT_IBOutletCollection:
HandleIBOutletCollection(D, Attr, S); break;
case AttributeList::AT_address_space:
+ case AttributeList::AT_opencl_image_access:
case AttributeList::AT_objc_gc:
case AttributeList::AT_vector_size:
case AttributeList::AT_neon_vector_type:
@@ -2684,6 +2844,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D,
case AttributeList::AT_analyzer_noreturn:
HandleAnalyzerNoReturnAttr (D, Attr, S); break;
case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
+ case AttributeList::AT_availability:HandleAvailabilityAttr(D, Attr, S); break;
case AttributeList::AT_carries_dependency:
HandleDependencyAttr (D, Attr, S); break;
case AttributeList::AT_common: HandleCommonAttr (D, Attr, S); break;
@@ -2736,6 +2897,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D,
HandleInitPriorityAttr(D, Attr, S); break;
case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break;
+ case AttributeList::AT_MsStruct: HandleMsStructAttr (D, Attr, S); break;
case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break;
case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break;
case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break;
@@ -2752,6 +2914,9 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D,
case AttributeList::AT_objc_exception:
HandleObjCExceptionAttr(D, Attr, S);
break;
+ case AttributeList::AT_objc_method_family:
+ HandleObjCMethodFamilyAttr(D, Attr, S);
+ break;
case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break;
case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break;
case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break;
@@ -2772,6 +2937,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D,
case AttributeList::AT_fastcall:
case AttributeList::AT_thiscall:
case AttributeList::AT_pascal:
+ case AttributeList::AT_pcs:
HandleCallConvAttr(D, Attr, S);
break;
case AttributeList::AT_opencl_kernel_function:
@@ -2837,6 +3003,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {
NamedDecl *NewD = 0;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
+ FD->getInnerLocStart(),
FD->getLocation(), DeclarationName(II),
FD->getType(), FD->getTypeSourceInfo());
if (FD->getQualifier()) {
@@ -2845,7 +3012,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {
}
} else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
- VD->getLocation(), II,
+ VD->getInnerLocStart(), VD->getLocation(), II,
VD->getType(), VD->getTypeSourceInfo(),
VD->getStorageClass(),
VD->getStorageClassAsWritten());
@@ -2986,14 +3153,14 @@ void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state,
// Destroy all the delayed diagnostics we're about to pop off.
for (unsigned i = state.SavedStackSize, e = DD.StackSize; i != e; ++i)
- DD.Stack[i].destroy();
+ DD.Stack[i].Destroy();
DD.StackSize = state.SavedStackSize;
}
static bool isDeclDeprecated(Decl *D) {
do {
- if (D->hasAttr<DeprecatedAttr>())
+ if (D->isDeprecated())
return true;
} while ((D = cast_or_null<Decl>(D->getDeclContext())));
return false;
@@ -3016,7 +3183,7 @@ void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD,
void Sema::EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message,
SourceLocation Loc,
- bool UnknownObjCClass) {
+ const ObjCInterfaceDecl *UnknownObjCClass) {
// Delay if we're currently parsing a declaration.
if (DelayedDiagnostics.shouldDelayDiagnostics()) {
DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, Message));
@@ -3032,7 +3199,9 @@ void Sema::EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message,
else {
if (!UnknownObjCClass)
Diag(Loc, diag::warn_deprecated) << D->getDeclName();
- else
+ else {
Diag(Loc, diag::warn_deprecated_fwdclass_message) << D->getDeclName();
+ Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
+ }
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
index f483262..27632a1 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18,9 +18,11 @@
#include "clang/Sema/Lookup.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
@@ -287,17 +289,37 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
ParmVarDecl *NewParam = New->getParamDecl(p);
if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) {
+
+ unsigned DiagDefaultParamID =
+ diag::err_param_default_argument_redefinition;
+
+ // MSVC accepts that default parameters be redefined for member functions
+ // of template class. The new default parameter's value is ignored.
+ Invalid = true;
+ if (getLangOptions().Microsoft) {
+ CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(New);
+ if (MD && MD->getParent()->getDescribedClassTemplate()) {
+ // Merge the old default argument into the new parameter.
+ NewParam->setHasInheritedDefaultArg();
+ if (OldParam->hasUninstantiatedDefaultArg())
+ NewParam->setUninstantiatedDefaultArg(
+ OldParam->getUninstantiatedDefaultArg());
+ else
+ NewParam->setDefaultArg(OldParam->getInit());
+ DiagDefaultParamID = diag::warn_param_default_argument_redefinition;
+ Invalid = false;
+ }
+ }
+
// FIXME: If we knew where the '=' was, we could easily provide a fix-it
// hint here. Alternatively, we could walk the type-source information
// for NewParam to find the last source location in the type... but it
// isn't worth the effort right now. This is the kind of test case that
// is hard to get right:
-
// int f(int);
// void g(int (*fp)(int) = f);
// void g(int (*fp)(int) = &f);
- Diag(NewParam->getLocation(),
- diag::err_param_default_argument_redefinition)
+ Diag(NewParam->getLocation(), DiagDefaultParamID)
<< NewParam->getDefaultArgRange();
// Look for the function declaration where the default argument was
@@ -312,7 +334,6 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
Diag(OldParam->getLocation(), diag::note_previous_definition)
<< OldParam->getDefaultArgRange();
- Invalid = true;
} else if (OldParam->hasDefaultArg()) {
// Merge the old default argument into the new parameter.
// It's important to use getInit() here; getDefaultArg()
@@ -382,6 +403,48 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
return Invalid;
}
+/// \brief Merge the exception specifications of two variable declarations.
+///
+/// This is called when there's a redeclaration of a VarDecl. The function
+/// checks if the redeclaration might have an exception specification and
+/// validates compatibility and merges the specs if necessary.
+void Sema::MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old) {
+ // Shortcut if exceptions are disabled.
+ if (!getLangOptions().CXXExceptions)
+ return;
+
+ assert(Context.hasSameType(New->getType(), Old->getType()) &&
+ "Should only be called if types are otherwise the same.");
+
+ QualType NewType = New->getType();
+ QualType OldType = Old->getType();
+
+ // We're only interested in pointers and references to functions, as well
+ // as pointers to member functions.
+ if (const ReferenceType *R = NewType->getAs<ReferenceType>()) {
+ NewType = R->getPointeeType();
+ OldType = OldType->getAs<ReferenceType>()->getPointeeType();
+ } else if (const PointerType *P = NewType->getAs<PointerType>()) {
+ NewType = P->getPointeeType();
+ OldType = OldType->getAs<PointerType>()->getPointeeType();
+ } else if (const MemberPointerType *M = NewType->getAs<MemberPointerType>()) {
+ NewType = M->getPointeeType();
+ OldType = OldType->getAs<MemberPointerType>()->getPointeeType();
+ }
+
+ if (!NewType->isFunctionProtoType())
+ return;
+
+ // There's lots of special cases for functions. For function pointers, system
+ // libraries are hopefully not as broken so that we don't need these
+ // workarounds.
+ if (CheckEquivalentExceptionSpec(
+ OldType->getAs<FunctionProtoType>(), Old->getLocation(),
+ NewType->getAs<FunctionProtoType>(), New->getLocation())) {
+ New->setInvalidDecl();
+ }
+}
+
/// CheckCXXDefaultArguments - Verify that the default arguments for a
/// function declaration are well-formed according to C++
/// [dcl.fct.default].
@@ -520,10 +583,9 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
assert(CXXBaseDecl && "Base type is not a C++ type");
- // C++ [class.derived]p2:
- // If a class is marked with the class-virt-specifier final and it appears
- // as a base-type-specifier in a base-clause (10 class.derived), the program
- // is ill-formed.
+ // C++ [class]p3:
+ // If a class is marked final and it appears as a base-type-specifier in
+ // base-clause, the program is ill-formed.
if (CXXBaseDecl->hasAttr<FinalAttr>()) {
Diag(BaseLoc, diag::err_class_marked_final_used_as_base)
<< CXXBaseDecl->getDeclName();
@@ -876,26 +938,6 @@ void Sema::CheckOverrideControl(const Decl *D) {
<< MD->getDeclName();
return;
}
-
- // C++0x [class.derived]p8:
- // In a class definition marked with the class-virt-specifier explicit,
- // if a virtual member function that is neither implicitly-declared nor a
- // destructor overrides a member function of a base class and it is not
- // marked with the virt-specifier override, the program is ill-formed.
- if (MD->getParent()->hasAttr<ExplicitAttr>() && !isa<CXXDestructorDecl>(MD) &&
- HasOverriddenMethods && !MD->hasAttr<OverrideAttr>()) {
- llvm::SmallVector<const CXXMethodDecl*, 4>
- OverriddenMethods(MD->begin_overridden_methods(),
- MD->end_overridden_methods());
-
- Diag(MD->getLocation(), diag::err_function_overriding_without_override)
- << MD->getDeclName()
- << (unsigned)OverriddenMethods.size();
-
- for (unsigned I = 0; I != OverriddenMethods.size(); ++I)
- Diag(OverriddenMethods[I]->getLocation(),
- diag::note_overridden_virtual_function);
- }
}
/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member
@@ -1068,6 +1110,12 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
MD->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context));
}
+ if (VS.getLastLocation().isValid()) {
+ // Update the end location of a method that has a virt-specifiers.
+ if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Member))
+ MD->setRangeEnd(VS.getLastLocation());
+ }
+
CheckOverrideControl(Member);
assert((Name || isInstField) && "No identifier for non-field ?");
@@ -1225,10 +1273,9 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
if (!NotUnknownSpecialization) {
// When the scope specifier can refer to a member of an unknown
// specialization, we take it as a type name.
- BaseType = CheckTypenameType(ETK_None,
- (NestedNameSpecifier *)SS.getScopeRep(),
- *MemberOrBase, SourceLocation(),
- SS.getRange(), IdLoc);
+ BaseType = CheckTypenameType(ETK_None, SourceLocation(),
+ SS.getWithLocInContext(Context),
+ *MemberOrBase, IdLoc);
if (BaseType.isNull())
return true;
@@ -1356,7 +1403,7 @@ static bool InitExprContainsUninitializedFields(const Stmt *S,
*L = ME->getMemberLoc();
return true;
}
- } else if (isa<SizeOfAlignOfExpr>(S)) {
+ } else if (isa<UnaryExprOrTypeTraitExpr>(S)) {
// sizeof/alignof doesn't reference contents, do not warn.
return false;
} else if (const UnaryOperator *UOE = dyn_cast<UnaryOperator>(S)) {
@@ -1476,17 +1523,61 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args,
MemInitResult
Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,
Expr **Args, unsigned NumArgs,
+ SourceLocation NameLoc,
SourceLocation LParenLoc,
SourceLocation RParenLoc,
- CXXRecordDecl *ClassDecl,
- SourceLocation EllipsisLoc) {
+ CXXRecordDecl *ClassDecl) {
SourceLocation Loc = TInfo->getTypeLoc().getLocalSourceRange().getBegin();
if (!LangOpts.CPlusPlus0x)
return Diag(Loc, diag::err_delegation_0x_only)
<< TInfo->getTypeLoc().getLocalSourceRange();
- return Diag(Loc, diag::err_delegation_unimplemented)
- << TInfo->getTypeLoc().getLocalSourceRange();
+ // Initialize the object.
+ InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
+ QualType(ClassDecl->getTypeForDecl(), 0));
+ InitializationKind Kind =
+ InitializationKind::CreateDirect(NameLoc, LParenLoc, RParenLoc);
+
+ InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs);
+
+ ExprResult DelegationInit =
+ InitSeq.Perform(*this, DelegationEntity, Kind,
+ MultiExprArg(*this, Args, NumArgs), 0);
+ if (DelegationInit.isInvalid())
+ return true;
+
+ CXXConstructExpr *ConExpr = cast<CXXConstructExpr>(DelegationInit.get());
+ CXXConstructorDecl *Constructor = ConExpr->getConstructor();
+ assert(Constructor && "Delegating constructor with no target?");
+
+ CheckImplicitConversions(DelegationInit.get(), LParenLoc);
+
+ // C++0x [class.base.init]p7:
+ // The initialization of each base and member constitutes a
+ // full-expression.
+ DelegationInit = MaybeCreateExprWithCleanups(DelegationInit);
+ if (DelegationInit.isInvalid())
+ return true;
+
+ // If we are in a dependent context, template instantiation will
+ // perform this type-checking again. Just save the arguments that we
+ // received in a ParenListExpr.
+ // FIXME: This isn't quite ideal, since our ASTs don't capture all
+ // of the information that we have about the base
+ // initializer. However, deconstructing the ASTs is a dicey process,
+ // and this approach is far more likely to get the corner cases right.
+ if (CurContext->isDependentContext()) {
+ ExprResult Init
+ = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args,
+ NumArgs, RParenLoc));
+ return new (Context) CXXCtorInitializer(Context, Loc, LParenLoc,
+ Constructor, Init.takeAs<Expr>(),
+ RParenLoc);
+ }
+
+ return new (Context) CXXCtorInitializer(Context, Loc, LParenLoc, Constructor,
+ DelegationInit.takeAs<Expr>(),
+ RParenLoc);
}
MemInitResult
@@ -1538,9 +1629,8 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
if (!Dependent) {
if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0),
BaseType))
- return BuildDelegatingInitializer(BaseTInfo, Args, NumArgs,
- LParenLoc, RParenLoc, ClassDecl,
- EllipsisLoc);
+ return BuildDelegatingInitializer(BaseTInfo, Args, NumArgs, BaseLoc,
+ LParenLoc, RParenLoc, ClassDecl);
FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
VirtualBaseSpec);
@@ -1684,7 +1774,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
QualType ParamType = Param->getType().getNonReferenceType();
Expr *CopyCtorArg =
- DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param,
+ DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param,
Constructor->getLocation(), ParamType,
VK_LValue, 0);
@@ -1695,9 +1785,9 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
CXXCastPath BasePath;
BasePath.push_back(BaseSpec);
- SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy,
- CK_UncheckedDerivedToBase,
- VK_LValue, &BasePath);
+ CopyCtorArg = SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy,
+ CK_UncheckedDerivedToBase,
+ VK_LValue, &BasePath).take();
InitializationKind InitKind
= InitializationKind::CreateDirect(Constructor->getLocation(),
@@ -1745,7 +1835,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
QualType ParamType = Param->getType().getNonReferenceType();
Expr *MemberExprBase =
- DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param,
+ DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param,
Loc, ParamType, VK_LValue, 0);
// Build a reference to this field within the parameter.
@@ -1783,7 +1873,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
IterationVarName = &SemaRef.Context.Idents.get(OS.str());
}
VarDecl *IterationVar
- = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc,
+ = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc,
IterationVarName, SizeType,
SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc),
SC_None, SC_None);
@@ -1978,6 +2068,30 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info,
return false;
}
+
+bool
+Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor,
+ CXXCtorInitializer *Initializer) {
+ Constructor->setNumCtorInitializers(1);
+ CXXCtorInitializer **initializer =
+ new (Context) CXXCtorInitializer*[1];
+ memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*));
+ Constructor->setCtorInitializers(initializer);
+
+ // FIXME: This doesn't catch indirect loops yet
+ CXXConstructorDecl *Target = Initializer->getTargetConstructor();
+ while (Target) {
+ if (Target == Constructor) {
+ Diag(Initializer->getSourceLocation(), diag::err_delegating_ctor_loop)
+ << Constructor;
+ return true;
+ }
+ Target = Target->getTargetConstructor();
+ }
+
+ return false;
+}
+
bool
Sema::SetCtorInitializers(CXXConstructorDecl *Constructor,
@@ -2340,10 +2454,23 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
if (CheckRedundantInit(*this, Init, Members[Field]) ||
CheckRedundantUnionInit(*this, Init, MemberUnions))
HadError = true;
- } else {
+ } else if (Init->isBaseInitializer()) {
void *Key = GetKeyForBase(Context, QualType(Init->getBaseClass(), 0));
if (CheckRedundantInit(*this, Init, Members[Key]))
HadError = true;
+ } else {
+ assert(Init->isDelegatingInitializer());
+ // This must be the only initializer
+ if (i != 0 || NumMemInits > 1) {
+ Diag(MemInits[0]->getSourceLocation(),
+ diag::err_delegating_initializer_alone)
+ << MemInits[0]->getSourceRange();
+ HadError = true;
+ // We will treat this as being the only initializer.
+ }
+ SetDelegatingInitializer(Constructor, *MemInits);
+ // Return immediately as the initializer is set.
+ return;
}
}
@@ -2380,10 +2507,13 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
continue;
CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (FieldClassDecl->isInvalidDecl())
+ continue;
if (FieldClassDecl->hasTrivialDestructor())
continue;
CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+ assert(Dtor && "No dtor found for FieldClassDecl!");
CheckDestructorAccess(Field->getLocation(), Dtor,
PDiag(diag::err_access_dtor_field)
<< Field->getDeclName()
@@ -2404,12 +2534,16 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
if (Base->isVirtual())
DirectVirtualBases.insert(RT);
- // Ignore trivial destructors.
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ // If our base class is invalid, we probably can't get its dtor anyway.
+ if (BaseClassDecl->isInvalidDecl())
+ continue;
+ // Ignore trivial destructors.
if (BaseClassDecl->hasTrivialDestructor())
continue;
CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
+ assert(Dtor && "No dtor found for BaseClassDecl!");
// FIXME: caret should be on the start of the class name
CheckDestructorAccess(Base->getSourceRange().getBegin(), Dtor,
@@ -2431,12 +2565,16 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
if (DirectVirtualBases.count(RT))
continue;
- // Ignore trivial destructors.
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ // If our base class is invalid, we probably can't get its dtor anyway.
+ if (BaseClassDecl->isInvalidDecl())
+ continue;
+ // Ignore trivial destructors.
if (BaseClassDecl->hasTrivialDestructor())
continue;
CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
+ assert(Dtor && "No dtor found for BaseClassDecl!");
CheckDestructorAccess(ClassDecl->getLocation(), Dtor,
PDiag(diag::err_access_dtor_vbase)
<< VBase->getType());
@@ -2786,7 +2924,8 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
for (CXXRecordDecl::method_iterator M = Record->method_begin(),
MEnd = Record->method_end();
M != MEnd; ++M) {
- DiagnoseHiddenVirtualMethods(Record, *M);
+ if (!(*M)->isStatic())
+ DiagnoseHiddenVirtualMethods(Record, *M);
}
}
@@ -2801,12 +2940,14 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
/// \brief Data used with FindHiddenVirtualMethod
-struct FindHiddenVirtualMethodData {
- Sema *S;
- CXXMethodDecl *Method;
- llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods;
- llvm::SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
-};
+namespace {
+ struct FindHiddenVirtualMethodData {
+ Sema *S;
+ CXXMethodDecl *Method;
+ llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods;
+ llvm::SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
+ };
+}
/// \brief Member lookup function that determines whether a given C++
/// method overloads virtual methods in a base class without overriding any,
@@ -2917,53 +3058,101 @@ namespace {
/// implicitly-declared special member functions.
class ImplicitExceptionSpecification {
ASTContext &Context;
- bool AllowsAllExceptions;
+ // We order exception specifications thus:
+ // noexcept is the most restrictive, but is only used in C++0x.
+ // throw() comes next.
+ // Then a throw(collected exceptions)
+ // Finally no specification.
+ // throw(...) is used instead if any called function uses it.
+ ExceptionSpecificationType ComputedEST;
llvm::SmallPtrSet<CanQualType, 4> ExceptionsSeen;
llvm::SmallVector<QualType, 4> Exceptions;
-
+
+ void ClearExceptions() {
+ ExceptionsSeen.clear();
+ Exceptions.clear();
+ }
+
public:
explicit ImplicitExceptionSpecification(ASTContext &Context)
- : Context(Context), AllowsAllExceptions(false) { }
-
- /// \brief Whether the special member function should have any
- /// exception specification at all.
- bool hasExceptionSpecification() const {
- return !AllowsAllExceptions;
+ : Context(Context), ComputedEST(EST_BasicNoexcept) {
+ if (!Context.getLangOptions().CPlusPlus0x)
+ ComputedEST = EST_DynamicNone;
}
-
- /// \brief Whether the special member function should have a
- /// throw(...) exception specification (a Microsoft extension).
- bool hasAnyExceptionSpecification() const {
- return false;
+
+ /// \brief Get the computed exception specification type.
+ ExceptionSpecificationType getExceptionSpecType() const {
+ assert(ComputedEST != EST_ComputedNoexcept &&
+ "noexcept(expr) should not be a possible result");
+ return ComputedEST;
}
-
+
/// \brief The number of exceptions in the exception specification.
unsigned size() const { return Exceptions.size(); }
-
+
/// \brief The set of exceptions in the exception specification.
const QualType *data() const { return Exceptions.data(); }
-
- /// \brief Note that
+
+ /// \brief Integrate another called method into the collected data.
void CalledDecl(CXXMethodDecl *Method) {
- // If we already know that we allow all exceptions, do nothing.
- if (AllowsAllExceptions || !Method)
+ // If we have an MSAny spec already, don't bother.
+ if (!Method || ComputedEST == EST_MSAny)
return;
-
+
const FunctionProtoType *Proto
= Method->getType()->getAs<FunctionProtoType>();
-
+
+ ExceptionSpecificationType EST = Proto->getExceptionSpecType();
+
// If this function can throw any exceptions, make a note of that.
- if (!Proto->hasExceptionSpec() || Proto->hasAnyExceptionSpec()) {
- AllowsAllExceptions = true;
- ExceptionsSeen.clear();
- Exceptions.clear();
+ if (EST == EST_MSAny || EST == EST_None) {
+ ClearExceptions();
+ ComputedEST = EST;
return;
}
-
+
+ // If this function has a basic noexcept, it doesn't affect the outcome.
+ if (EST == EST_BasicNoexcept)
+ return;
+
+ // If we have a throw-all spec at this point, ignore the function.
+ if (ComputedEST == EST_None)
+ return;
+
+ // If we're still at noexcept(true) and there's a nothrow() callee,
+ // change to that specification.
+ if (EST == EST_DynamicNone) {
+ if (ComputedEST == EST_BasicNoexcept)
+ ComputedEST = EST_DynamicNone;
+ return;
+ }
+
+ // Check out noexcept specs.
+ if (EST == EST_ComputedNoexcept) {
+ FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(Context);
+ assert(NR != FunctionProtoType::NR_NoNoexcept &&
+ "Must have noexcept result for EST_ComputedNoexcept.");
+ assert(NR != FunctionProtoType::NR_Dependent &&
+ "Should not generate implicit declarations for dependent cases, "
+ "and don't know how to handle them anyway.");
+
+ // noexcept(false) -> no spec on the new function
+ if (NR == FunctionProtoType::NR_Throw) {
+ ClearExceptions();
+ ComputedEST = EST_None;
+ }
+ // noexcept(true) won't change anything either.
+ return;
+ }
+
+ assert(EST == EST_Dynamic && "EST case not considered earlier.");
+ assert(ComputedEST != EST_None &&
+ "Shouldn't collect exceptions when throw-all is guaranteed.");
+ ComputedEST = EST_Dynamic;
// Record the exceptions in this function's exception specification.
for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
EEnd = Proto->exception_end();
- E != EEnd; ++E)
+ E != EEnd; ++E)
if (ExceptionsSeen.insert(Context.getCanonicalType(*E)))
Exceptions.push_back(*E);
}
@@ -3006,6 +3195,25 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
}
}
+void Sema::ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D) {
+ if (!D)
+ return;
+
+ int NumParamList = D->getNumTemplateParameterLists();
+ for (int i = 0; i < NumParamList; i++) {
+ TemplateParameterList* Params = D->getTemplateParameterList(i);
+ for (TemplateParameterList::iterator Param = Params->begin(),
+ ParamEnd = Params->end();
+ Param != ParamEnd; ++Param) {
+ NamedDecl *Named = cast<NamedDecl>(*Param);
+ if (Named->getDeclName()) {
+ S->AddDecl(Named);
+ IdResolver.AddDecl(Named);
+ }
+ }
+ }
+}
+
void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) {
if (!D)
return;
@@ -3256,9 +3464,9 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
// be used as the identifier in the declarator for a destructor
// declaration.
QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName);
- if (isa<TypedefType>(DeclaratorType))
+ if (const TypedefType *TT = DeclaratorType->getAs<TypedefType>())
Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
- << DeclaratorType;
+ << DeclaratorType << isa<TypeAliasDecl>(TT->getDecl());
// C++ [class.dtor]p2:
// A destructor is used to destroy objects of its class type. A
@@ -3488,14 +3696,16 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
/// definition.
Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
SourceLocation InlineLoc,
+ SourceLocation NamespaceLoc,
SourceLocation IdentLoc,
IdentifierInfo *II,
SourceLocation LBrace,
AttributeList *AttrList) {
- // anonymous namespace starts at its left brace
+ SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc;
+ // For anonymous namespace, take the location of the left brace.
+ SourceLocation Loc = II ? IdentLoc : LBrace;
NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext,
- (II ? IdentLoc : LBrace) , II);
- Namespc->setLBracLoc(LBrace);
+ StartLoc, Loc, II);
Namespc->setInline(InlineLoc.isValid());
Scope *DeclRegionScope = NamespcScope->getParent();
@@ -3654,7 +3864,7 @@ static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) {
void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) {
NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl);
assert(Namespc && "Invalid parameter, expected NamespaceDecl");
- Namespc->setRBracLoc(RBrace);
+ Namespc->setRBraceLoc(RBrace);
PopDeclContext();
if (Namespc->hasAttr<VisibilityAttr>())
PopPragmaVisibility();
@@ -3677,7 +3887,7 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() {
// The "std" namespace has not yet been defined, so build one implicitly.
StdNamespace = NamespaceDecl::Create(Context,
Context.getTranslationUnitDecl(),
- SourceLocation(),
+ SourceLocation(), SourceLocation(),
&PP.getIdentifierTable().get("std"));
getStdNamespace()->setImplicit(true);
}
@@ -3685,6 +3895,19 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() {
return getStdNamespace();
}
+/// \brief Determine whether a using statement is in a context where it will be
+/// apply in all contexts.
+static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) {
+ switch (CurContext->getDeclKind()) {
+ case Decl::TranslationUnit:
+ return true;
+ case Decl::LinkageSpec:
+ return IsUsingDirectiveInToplevelContext(CurContext->getParent());
+ default:
+ return false;
+ }
+}
+
Decl *Sema::ActOnUsingDirective(Scope *S,
SourceLocation UsingLoc,
SourceLocation NamespcLoc,
@@ -3769,6 +3992,12 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc,
SS.getWithLocInContext(Context),
IdentLoc, Named, CommonAncestor);
+
+ if (IsUsingDirectiveInToplevelContext(CurContext) &&
+ !SourceMgr.isFromMainFile(SourceMgr.getInstantiationLoc(IdentLoc))) {
+ Diag(IdentLoc, diag::warn_using_directive_in_header);
+ }
+
PushUsingDirective(S, UDir);
} else {
Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
@@ -3870,8 +4099,8 @@ IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2,
return true;
}
- if (TypedefDecl *TD1 = dyn_cast<TypedefDecl>(D1))
- if (TypedefDecl *TD2 = dyn_cast<TypedefDecl>(D2)) {
+ if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1))
+ if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2)) {
SuppressRedeclaration = true;
return Context.hasSameType(TD1->getUnderlyingType(),
TD2->getUnderlyingType());
@@ -4470,6 +4699,61 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
return true;
}
+Decl *Sema::ActOnAliasDeclaration(Scope *S,
+ AccessSpecifier AS,
+ SourceLocation UsingLoc,
+ UnqualifiedId &Name,
+ TypeResult Type) {
+ assert((S->getFlags() & Scope::DeclScope) &&
+ "got alias-declaration outside of declaration scope");
+
+ if (Type.isInvalid())
+ return 0;
+
+ bool Invalid = false;
+ DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name);
+ TypeSourceInfo *TInfo = 0;
+ GetTypeFromParser(Type.get(), &TInfo);
+
+ if (DiagnoseClassNameShadow(CurContext, NameInfo))
+ return 0;
+
+ if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo,
+ UPPC_DeclarationType))
+ Invalid = true;
+
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration);
+ LookupName(Previous, S);
+
+ // Warn about shadowing the name of a template parameter.
+ if (Previous.isSingleResult() &&
+ Previous.getFoundDecl()->isTemplateParameter()) {
+ if (DiagnoseTemplateParameterShadow(Name.StartLocation,
+ Previous.getFoundDecl()))
+ Invalid = true;
+ Previous.clear();
+ }
+
+ assert(Name.Kind == UnqualifiedId::IK_Identifier &&
+ "name in alias declaration must be an identifier");
+ TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc,
+ Name.StartLocation,
+ Name.Identifier, TInfo);
+
+ NewTD->setAccess(AS);
+
+ if (Invalid)
+ NewTD->setInvalidDecl();
+
+ bool Redeclaration = false;
+ ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration);
+
+ if (!Redeclaration)
+ PushOnScopeChains(NewTD, S);
+
+ return NewTD;
+}
+
Decl *Sema::ActOnNamespaceAliasDef(Scope *S,
SourceLocation NamespaceLoc,
SourceLocation AliasLoc,
@@ -4609,7 +4893,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
// exception-specification. [...]
ImplicitExceptionSpecification ExceptSpec(Context);
- // Direct base-class destructors.
+ // Direct base-class constructors.
for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
BEnd = ClassDecl->bases_end();
B != BEnd; ++B) {
@@ -4625,8 +4909,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
ExceptSpec.CalledDecl(Constructor);
}
}
-
- // Virtual base-class destructors.
+
+ // Virtual base-class constructors.
for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
BEnd = ClassDecl->vbases_end();
B != BEnd; ++B) {
@@ -4639,8 +4923,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
ExceptSpec.CalledDecl(Constructor);
}
}
-
- // Field destructors.
+
+ // Field constructors.
for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
FEnd = ClassDecl->field_end();
F != FEnd; ++F) {
@@ -4657,19 +4941,19 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
}
FunctionProtoType::ExtProtoInfo EPI;
- EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification();
- EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification();
+ EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType();
EPI.NumExceptions = ExceptSpec.size();
EPI.Exceptions = ExceptSpec.data();
-
+
// Create the actual constructor declaration.
CanQualType ClassType
= Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+ SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationName Name
= Context.DeclarationNames.getCXXConstructorName(ClassType);
- DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation());
+ DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXConstructorDecl *DefaultCon
- = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo,
+ = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
Context.getFunctionType(Context.VoidTy,
0, 0, EPI),
/*TInfo=*/0,
@@ -4714,6 +4998,10 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
Constructor->setUsed();
MarkVTableUsed(CurrentLocation, ClassDecl);
+
+ if (ASTMutationListener *L = getASTMutationListener()) {
+ L->CompletedImplicitDefinition(Constructor);
+ }
}
void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
@@ -4865,15 +5153,16 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
// user-writtern inline constructor [...]
DeclarationNameInfo DNI(CreatedCtorName, UsingLoc);
CXXConstructorDecl *NewCtor = CXXConstructorDecl::Create(
- Context, ClassDecl, DNI, QualType(NewCtorType, 0), /*TInfo=*/0,
- BaseCtor->isExplicit(), /*Inline=*/true,
+ Context, ClassDecl, UsingLoc, DNI, QualType(NewCtorType, 0),
+ /*TInfo=*/0, BaseCtor->isExplicit(), /*Inline=*/true,
/*ImplicitlyDeclared=*/true);
NewCtor->setAccess(BaseCtor->getAccess());
// Build up the parameter decls and add them.
llvm::SmallVector<ParmVarDecl *, 16> ParamDecls;
for (unsigned i = 0; i < params; ++i) {
- ParamDecls.push_back(ParmVarDecl::Create(Context, NewCtor, UsingLoc,
+ ParamDecls.push_back(ParmVarDecl::Create(Context, NewCtor,
+ UsingLoc, UsingLoc,
/*IdentifierInfo=*/0,
BaseCtorType->getArgType(i),
/*TInfo=*/0, SC_None,
@@ -4931,24 +5220,24 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
ExceptSpec.CalledDecl(
LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
}
-
+
// Create the actual destructor declaration.
FunctionProtoType::ExtProtoInfo EPI;
- EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification();
- EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification();
+ EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType();
EPI.NumExceptions = ExceptSpec.size();
EPI.Exceptions = ExceptSpec.data();
QualType Ty = Context.getFunctionType(Context.VoidTy, 0, 0, EPI);
-
+
CanQualType ClassType
= Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+ SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationName Name
= Context.DeclarationNames.getCXXDestructorName(ClassType);
- DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation());
+ DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXDestructorDecl *Destructor
- = CXXDestructorDecl::Create(Context, ClassDecl, NameInfo, Ty, 0,
- /*isInline=*/true,
- /*isImplicitlyDeclared=*/true);
+ = CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, Ty, 0,
+ /*isInline=*/true,
+ /*isImplicitlyDeclared=*/true);
Destructor->setAccess(AS_public);
Destructor->setImplicit();
Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
@@ -4998,6 +5287,10 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
Destructor->setUsed();
MarkVTableUsed(CurrentLocation, ClassDecl);
+
+ if (ASTMutationListener *L = getASTMutationListener()) {
+ L->CompletedImplicitDefinition(Destructor);
+ }
}
/// \brief Builds a statement that copies the given entity from \p From to
@@ -5133,7 +5426,7 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
OS << "__i" << Depth;
IterationVarName = &S.Context.Idents.get(OS.str());
}
- VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc,
+ VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc,
IterationVarName, SizeType,
S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
SC_None, SC_None);
@@ -5328,30 +5621,30 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
ExceptSpec.CalledDecl(CopyAssign);
}
}
-
+
// An implicitly-declared copy assignment operator is an inline public
// member of its class.
FunctionProtoType::ExtProtoInfo EPI;
- EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification();
- EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification();
+ EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType();
EPI.NumExceptions = ExceptSpec.size();
EPI.Exceptions = ExceptSpec.data();
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
- DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation());
+ SourceLocation ClassLoc = ClassDecl->getLocation();
+ DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXMethodDecl *CopyAssignment
- = CXXMethodDecl::Create(Context, ClassDecl, NameInfo,
+ = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
Context.getFunctionType(RetType, &ArgType, 1, EPI),
/*TInfo=*/0, /*isStatic=*/false,
/*StorageClassAsWritten=*/SC_None,
- /*isInline=*/true);
+ /*isInline=*/true,
+ SourceLocation());
CopyAssignment->setAccess(AS_public);
CopyAssignment->setImplicit();
CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment());
// Add the parameter to the operator.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
- ClassDecl->getLocation(),
- /*Id=*/0,
+ ClassLoc, ClassLoc, /*Id=*/0,
ArgType, /*TInfo=*/0,
SC_None,
SC_None, 0);
@@ -5440,21 +5733,19 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// Construct the "from" expression, which is an implicit cast to the
// appropriately-qualified base type.
Expr *From = OtherRef;
- ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals),
- CK_UncheckedDerivedToBase,
- VK_LValue, &BasePath);
+ From = ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals),
+ CK_UncheckedDerivedToBase,
+ VK_LValue, &BasePath).take();
// Dereference "this".
ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
// Implicitly cast "this" to the appropriately-qualified base type.
- Expr *ToE = To.takeAs<Expr>();
- ImpCastExprToType(ToE,
- Context.getCVRQualifiedType(BaseType,
- CopyAssignOperator->getTypeQualifiers()),
- CK_UncheckedDerivedToBase,
- VK_LValue, &BasePath);
- To = Owned(ToE);
+ To = ImpCastExprToType(To.take(),
+ Context.getCVRQualifiedType(BaseType,
+ CopyAssignOperator->getTypeQualifiers()),
+ CK_UncheckedDerivedToBase,
+ VK_LValue, &BasePath);
// Build the copy.
StmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType,
@@ -5659,6 +5950,10 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
/*isStmtExpr=*/false);
assert(!Body.isInvalid() && "Compound statement creation cannot fail");
CopyAssignOperator->setBody(Body.takeAs<Stmt>());
+
+ if (ASTMutationListener *L = getASTMutationListener()) {
+ L->CompletedImplicitDefinition(CopyAssignOperator);
+ }
}
CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
@@ -5790,20 +6085,20 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
ExceptSpec.CalledDecl(CopyConstructor);
}
}
-
+
// An implicitly-declared copy constructor is an inline public
// member of its class.
FunctionProtoType::ExtProtoInfo EPI;
- EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification();
- EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification();
+ EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType();
EPI.NumExceptions = ExceptSpec.size();
EPI.Exceptions = ExceptSpec.data();
DeclarationName Name
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ClassType));
- DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation());
+ SourceLocation ClassLoc = ClassDecl->getLocation();
+ DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXConstructorDecl *CopyConstructor
- = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo,
+ = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
Context.getFunctionType(Context.VoidTy,
&ArgType, 1, EPI),
/*TInfo=*/0,
@@ -5818,7 +6113,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
// Add the parameter to the constructor.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
- ClassDecl->getLocation(),
+ ClassLoc, ClassLoc,
/*IdentifierInfo=*/0,
ArgType, /*TInfo=*/0,
SC_None,
@@ -5859,6 +6154,10 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
}
CopyConstructor->setUsed();
+
+ if (ASTMutationListener *L = getASTMutationListener()) {
+ L->CompletedImplicitDefinition(CopyConstructor);
+ }
}
ExprResult
@@ -5903,6 +6202,13 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
unsigned NumExprs = ExprArgs.size();
Expr **Exprs = (Expr **)ExprArgs.release();
+ for (specific_attr_iterator<NonNullAttr>
+ i = Constructor->specific_attr_begin<NonNullAttr>(),
+ e = Constructor->specific_attr_end<NonNullAttr>(); i != e; ++i) {
+ const NonNullAttr *NonNull = *i;
+ CheckNonNullArguments(NonNull, ExprArgs.get(), ConstructLoc);
+ }
+
MarkDeclarationReferenced(ConstructLoc, Constructor);
return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
Constructor, Elidable, Exprs, NumExprs,
@@ -5932,20 +6238,29 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD,
}
void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
+ if (VD->isInvalidDecl()) return;
+
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl());
- if (!ClassDecl->isInvalidDecl() && !VD->isInvalidDecl() &&
- !ClassDecl->hasTrivialDestructor() && !ClassDecl->isDependentContext()) {
- CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
- MarkDeclarationReferenced(VD->getLocation(), Destructor);
- CheckDestructorAccess(VD->getLocation(), Destructor,
- PDiag(diag::err_access_dtor_var)
- << VD->getDeclName()
- << VD->getType());
+ if (ClassDecl->isInvalidDecl()) return;
+ if (ClassDecl->hasTrivialDestructor()) return;
+ if (ClassDecl->isDependentContext()) return;
- // TODO: this should be re-enabled for static locals by !CXAAtExit
- if (!VD->isInvalidDecl() && VD->hasGlobalStorage() && !VD->isStaticLocal())
- Diag(VD->getLocation(), diag::warn_global_destructor);
- }
+ CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
+ MarkDeclarationReferenced(VD->getLocation(), Destructor);
+ CheckDestructorAccess(VD->getLocation(), Destructor,
+ PDiag(diag::err_access_dtor_var)
+ << VD->getDeclName()
+ << VD->getType());
+
+ if (!VD->hasGlobalStorage()) return;
+
+ // Emit warning for non-trivial dtor in global scope (a real global,
+ // class-static, function-static).
+ Diag(VD->getLocation(), diag::warn_exit_time_destructor);
+
+ // TODO: this should be re-enabled for static locals by !CXAAtExit
+ if (!VD->isStaticLocal())
+ Diag(VD->getLocation(), diag::warn_global_destructor);
}
/// AddCXXDirectInitializerToDecl - This action is called immediately after
@@ -5983,15 +6298,17 @@ void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl,
}
Expr *Init = Exprs.get()[0];
- QualType DeducedType;
- if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) {
+ TypeSourceInfo *DeducedType = 0;
+ if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType))
Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
<< VDecl->getDeclName() << VDecl->getType() << Init->getType()
<< Init->getSourceRange();
+ if (!DeducedType) {
RealDecl->setInvalidDecl();
return;
}
- VDecl->setType(DeducedType);
+ VDecl->setTypeSourceInfo(DeducedType);
+ VDecl->setType(DeducedType->getType());
// If this is a redeclaration, check that the type we just deduced matches
// the previously declared type.
@@ -6523,8 +6840,7 @@ Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,
// FIXME: Add all the various semantics of linkage specifications
LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext,
- LangLoc, Language,
- LBraceLoc.isValid());
+ ExternLoc, LangLoc, Language);
CurContext->addDecl(D);
PushDeclContext(S, D);
return D;
@@ -6535,20 +6851,26 @@ Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,
/// valid, it's the position of the closing '}' brace in a linkage
/// specification that uses braces.
Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
- Decl *LinkageSpec,
- SourceLocation RBraceLoc) {
- if (LinkageSpec)
+ Decl *LinkageSpec,
+ SourceLocation RBraceLoc) {
+ if (LinkageSpec) {
+ if (RBraceLoc.isValid()) {
+ LinkageSpecDecl* LSDecl = cast<LinkageSpecDecl>(LinkageSpec);
+ LSDecl->setRBraceLoc(RBraceLoc);
+ }
PopDeclContext();
+ }
return LinkageSpec;
}
/// \brief Perform semantic analysis for the variable declaration that
/// occurs within a C++ catch clause, returning the newly-created
/// variable.
-VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
+VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
TypeSourceInfo *TInfo,
- IdentifierInfo *Name,
- SourceLocation Loc) {
+ SourceLocation StartLoc,
+ SourceLocation Loc,
+ IdentifierInfo *Name) {
bool Invalid = false;
QualType ExDeclType = TInfo->getType();
@@ -6608,19 +6930,15 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
Diag(Loc, diag::err_objc_object_catch);
Invalid = true;
} else if (T->isObjCObjectPointerType()) {
- if (!getLangOptions().NeXTRuntime) {
- Diag(Loc, diag::err_objc_pointer_cxx_catch_gnu);
- Invalid = true;
- } else if (!getLangOptions().ObjCNonFragileABI) {
+ if (!getLangOptions().ObjCNonFragileABI) {
Diag(Loc, diag::err_objc_pointer_cxx_catch_fragile);
Invalid = true;
}
}
}
- VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc,
- Name, ExDeclType, TInfo, SC_None,
- SC_None);
+ VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name,
+ ExDeclType, TInfo, SC_None, SC_None);
ExDecl->setExceptionVariable(true);
if (!Invalid) {
@@ -6703,9 +7021,9 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
}
VarDecl *ExDecl = BuildExceptionDeclaration(S, TInfo,
- D.getIdentifier(),
- D.getIdentifierLoc());
-
+ D.getSourceRange().getBegin(),
+ D.getIdentifierLoc(),
+ D.getIdentifier());
if (Invalid)
ExDecl->setInvalidDecl();
@@ -6719,21 +7037,23 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
return ExDecl;
}
-Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
+Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc,
Expr *AssertExpr,
- Expr *AssertMessageExpr_) {
+ Expr *AssertMessageExpr_,
+ SourceLocation RParenLoc) {
StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr_);
if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) {
llvm::APSInt Value(32);
if (!AssertExpr->isIntegerConstantExpr(Value, Context)) {
- Diag(AssertLoc, diag::err_static_assert_expression_is_not_constant) <<
+ Diag(StaticAssertLoc,
+ diag::err_static_assert_expression_is_not_constant) <<
AssertExpr->getSourceRange();
return 0;
}
if (Value == 0) {
- Diag(AssertLoc, diag::err_static_assert_failed)
+ Diag(StaticAssertLoc, diag::err_static_assert_failed)
<< AssertMessage->getString() << AssertExpr->getSourceRange();
}
}
@@ -6741,8 +7061,8 @@ Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression))
return 0;
- Decl *Decl = StaticAssertDecl::Create(Context, CurContext, AssertLoc,
- AssertExpr, AssertMessage);
+ Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc,
+ AssertExpr, AssertMessage, RParenLoc);
CurContext->addDecl(Decl);
return Decl;
@@ -6815,7 +7135,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
bool isExplicitSpecialization = false;
- unsigned NumMatchedTemplateParamLists = TempParamLists.size();
bool Invalid = false;
if (TemplateParameterList *TemplateParams
@@ -6825,16 +7144,16 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
/*friend*/ true,
isExplicitSpecialization,
Invalid)) {
- --NumMatchedTemplateParamLists;
-
if (TemplateParams->size() > 0) {
// This is a declaration of a class template.
if (Invalid)
return 0;
-
+
return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc,
SS, Name, NameLoc, Attr,
- TemplateParams, AS_public).take();
+ TemplateParams, AS_public,
+ TempParamLists.size() - 1,
+ (TemplateParameterList**) TempParamLists.release()).take();
} else {
// The "template<>" header is extraneous.
Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams)
@@ -6848,7 +7167,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?");
bool isAllExplicitSpecializations = true;
- for (unsigned I = 0; I != NumMatchedTemplateParamLists; ++I) {
+ for (unsigned I = TempParamLists.size(); I-- > 0; ) {
if (TempParamLists.get()[I]->size()) {
isAllExplicitSpecializations = false;
break;
@@ -6861,10 +7180,11 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
// about the template header and build an appropriate non-templated
// friend. TODO: for source fidelity, remember the headers.
if (isAllExplicitSpecializations) {
+ NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
ElaboratedTypeKeyword Keyword
= TypeWithKeyword::getKeywordForTagTypeKind(Kind);
- QualType T = CheckTypenameType(Keyword, SS.getScopeRep(), *Name,
- TagLoc, SS.getRange(), NameLoc);
+ QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc,
+ *Name, NameLoc);
if (T.isNull())
return 0;
@@ -6872,12 +7192,12 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
if (isa<DependentNameType>(T)) {
DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
TL.setKeywordLoc(TagLoc);
- TL.setQualifierRange(SS.getRange());
+ TL.setQualifierLoc(QualifierLoc);
TL.setNameLoc(NameLoc);
} else {
ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc());
TL.setKeywordLoc(TagLoc);
- TL.setQualifierRange(SS.getRange());
+ TL.setQualifierLoc(QualifierLoc);
cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(NameLoc);
}
@@ -6896,7 +7216,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
TL.setKeywordLoc(TagLoc);
- TL.setQualifierRange(SS.getRange());
+ TL.setQualifierLoc(SS.getWithLocInContext(Context));
TL.setNameLoc(NameLoc);
FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc,
@@ -7359,10 +7679,14 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
///
/// \param InitRange the source range that covers the "0" initializer.
bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) {
+ SourceLocation EndLoc = InitRange.getEnd();
+ if (EndLoc.isValid())
+ Method->setRangeEnd(EndLoc);
+
if (Method->isVirtual() || Method->getParent()->isDependentContext()) {
Method->setPure();
return false;
- }
+ }
if (!Method->isInvalidDecl())
Diag(Method->getLocation(), diag::err_non_virtual_pure)
@@ -7379,7 +7703,7 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) {
/// class X.
void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
// If there is no declaration, there was an error parsing it.
- if (D == 0) return;
+ if (D == 0 || D->isInvalidDecl()) return;
// We should only get called for declarations with scope specifiers, like:
// int foo::bar;
@@ -7391,7 +7715,7 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
/// initializer for the out-of-line declaration 'D'.
void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
// If there is no declaration, there was an error parsing it.
- if (D == 0) return;
+ if (D == 0 || D->isInvalidDecl()) return;
assert(D->isOutOfLine());
ExitDeclaratorContext(S);
@@ -7472,6 +7796,7 @@ bool Sema::DefineUsedVTables() {
// the members of a class as "used", so we check the size each
// time through the loop and prefer indices (with are stable) to
// iterators (which are not).
+ bool DefinedAnything = false;
for (unsigned I = 0; I != VTableUses.size(); ++I) {
CXXRecordDecl *Class = VTableUses[I].first->getDefinition();
if (!Class)
@@ -7524,6 +7849,7 @@ bool Sema::DefineUsedVTables() {
// Mark all of the virtual members of this class as referenced, so
// that we can build a vtable. Then, tell the AST consumer that a
// vtable for this class is required.
+ DefinedAnything = true;
MarkVirtualMembersReferenced(Loc, Class);
CXXRecordDecl *Canonical = cast<CXXRecordDecl>(Class->getCanonicalDecl());
Consumer.HandleVTable(Class, VTablesUsed[Canonical]);
@@ -7537,7 +7863,7 @@ bool Sema::DefineUsedVTables() {
}
VTableUses.clear();
- return true;
+ return DefinedAnything;
}
void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
index 652318f..7b235ba 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
@@ -28,7 +28,7 @@ static void DiagnoseObjCImplementedDeprecations(Sema &S,
NamedDecl *ND,
SourceLocation ImplLoc,
int select) {
- if (ND && ND->getAttr<DeprecatedAttr>()) {
+ if (ND && ND->isDeprecated()) {
S.Diag(ImplLoc, diag::warn_deprecated_def) << select;
if (select == 0)
S.Diag(ND->getLocation(), diag::note_method_declared_at);
@@ -174,7 +174,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
if (PrevDecl && SuperClassDecl == 0) {
// The previous declaration was not a class decl. Check if we have a
// typedef. If we do, get the underlying class type.
- if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
+ if (const TypedefNameDecl *TDecl =
+ dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
QualType T = TDecl->getUnderlyingType();
if (T->isObjCObjectType()) {
if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface())
@@ -193,7 +194,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
}
}
- if (!dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
+ if (!dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
if (!SuperClassDecl)
Diag(SuperLoc, diag::err_undef_superclass)
<< SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
@@ -242,7 +243,8 @@ Decl *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,
// Check for class declaration
NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation,
LookupOrdinaryName, ForRedeclaration);
- if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(CDeclU)) {
+ if (const TypedefNameDecl *TDecl =
+ dyn_cast_or_null<TypedefNameDecl>(CDeclU)) {
QualType T = TDecl->getUnderlyingType();
if (T->isObjCObjectType()) {
if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
@@ -1242,7 +1244,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
// @class XCElementToggler;
//
// FIXME: Make an extension?
- TypedefDecl *TDD = dyn_cast<TypedefDecl>(PrevDecl);
+ TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(PrevDecl);
if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) {
Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i];
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
@@ -1369,15 +1371,14 @@ void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,
PrevObjCMethod->setDefined(impl);
// If a method is deprecated, push it in the global pool.
// This is used for better diagnostics.
- if (Method->getAttr<DeprecatedAttr>()) {
- if (!PrevObjCMethod->getAttr<DeprecatedAttr>())
+ if (Method->isDeprecated()) {
+ if (!PrevObjCMethod->isDeprecated())
List->Method = Method;
}
// If new method is unavailable, push it into global pool
// unless previous one is deprecated.
- if (Method->getAttr<UnavailableAttr>()) {
- if (!PrevObjCMethod->getAttr<UnavailableAttr>() &&
- !PrevObjCMethod->getAttr<DeprecatedAttr>())
+ if (Method->isUnavailable()) {
+ if (PrevObjCMethod->getAvailability() < AR_Deprecated)
List->Method = Method;
}
return;
@@ -1475,7 +1476,7 @@ void Sema::CompareMethodParamsInBaseAndSuper(Decl *ClassDecl,
assert(PrevI != SuperMethodDecl->param_end() && "Param mismatch");
QualType T1 = Context.getCanonicalType((*ParamI)->getType());
QualType T2 = Context.getCanonicalType((*PrevI)->getType());
- // If type of arguement of method in this class does not match its
+ // If type of argument of method in this class does not match its
// respective argument type in the super class method, issue warning;
if (!Context.typesAreCompatible(T1, T2)) {
Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super)
@@ -1535,7 +1536,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
SourceLocation L = ClassDecl->getLocation();
AtEnd.setBegin(L);
AtEnd.setEnd(L);
- Diag(L, diag::warn_missing_atend);
+ Diag(L, diag::err_missing_atend);
}
// FIXME: Remove these and use the ObjCContainerDecl/DeclContext.
@@ -1697,21 +1698,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
/// objective-c's type qualifier from the parser version of the same info.
static Decl::ObjCDeclQualifier
CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
- Decl::ObjCDeclQualifier ret = Decl::OBJC_TQ_None;
- if (PQTVal & ObjCDeclSpec::DQ_In)
- ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_In);
- if (PQTVal & ObjCDeclSpec::DQ_Inout)
- ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Inout);
- if (PQTVal & ObjCDeclSpec::DQ_Out)
- ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Out);
- if (PQTVal & ObjCDeclSpec::DQ_Bycopy)
- ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Bycopy);
- if (PQTVal & ObjCDeclSpec::DQ_Byref)
- ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Byref);
- if (PQTVal & ObjCDeclSpec::DQ_Oneway)
- ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Oneway);
-
- return ret;
+ return (Decl::ObjCDeclQualifier) (unsigned) PQTVal;
}
static inline
@@ -1736,7 +1723,7 @@ Decl *Sema::ActOnMethodDeclaration(
ObjCArgInfo *ArgInfo,
DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args
AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind,
- bool isVariadic) {
+ bool isVariadic, bool MethodDefinition) {
// Make sure we can establish a context for the method.
if (!ClassDecl) {
Diag(MethodLoc, diag::error_missing_method_context);
@@ -1789,25 +1776,24 @@ Decl *Sema::ActOnMethodDeclaration(
if (R.isSingleResult()) {
NamedDecl *PrevDecl = R.getFoundDecl();
if (S->isDeclScope(PrevDecl)) {
- // FIXME. This should be an error; but will break projects.
- Diag(ArgInfo[i].NameLoc, diag::warn_method_param_redefinition)
+ Diag(ArgInfo[i].NameLoc,
+ (MethodDefinition ? diag::warn_method_param_redefinition
+ : diag::warn_method_param_declaration))
<< ArgInfo[i].Name;
Diag(PrevDecl->getLocation(),
diag::note_previous_declaration);
}
}
- ParmVarDecl* Param
- = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc,
- ArgInfo[i].Name, ArgType, DI,
- SC_None, SC_None, 0);
+ SourceLocation StartLoc = DI
+ ? DI->getTypeLoc().getBeginLoc()
+ : ArgInfo[i].NameLoc;
- if (ArgType->isObjCObjectType()) {
- Diag(ArgInfo[i].NameLoc,
- diag::err_object_cannot_be_passed_returned_by_value)
- << 1 << ArgType;
- Param->setInvalidDecl();
- }
+ ParmVarDecl* Param = CheckParameter(ObjCMethod, StartLoc,
+ ArgInfo[i].NameLoc, ArgInfo[i].Name,
+ ArgType, DI, SC_None, SC_None);
+
+ Param->setObjCMethodScopeInfo(i);
Param->setObjCDeclQualifier(
CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier()));
@@ -1888,16 +1874,9 @@ Decl *Sema::ActOnMethodDeclaration(
Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
}
- // If the interface declared this method, and it was deprecated there,
- // mark it deprecated here.
+ // Merge information down from the interface declaration if we have one.
if (InterfaceMD)
- if (Attr *DA = InterfaceMD->getAttr<DeprecatedAttr>()) {
- StringLiteral *SE = StringLiteral::CreateEmpty(Context, 1);
- ObjCMethod->addAttr(::new (Context)
- DeprecatedAttr(DA->getLocation(),
- Context,
- SE->getString()));
- }
+ mergeObjCMethodDecls(ObjCMethod, InterfaceMD);
return ObjCMethod;
}
@@ -1935,7 +1914,9 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
for (unsigned i = 0; i < Ivars.size(); i++) {
FieldDecl* ID = cast<FieldDecl>(Ivars[i]);
RecordDecl *Record = dyn_cast<RecordDecl>(TagD);
- Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, ID->getLocation(),
+ Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record,
+ /*FIXME: StartL=*/ID->getLocation(),
+ ID->getLocation(),
ID->getIdentifier(), ID->getType(),
ID->getBitWidth());
Decls.push_back(FD);
@@ -1953,17 +1934,17 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
}
/// \brief Build a type-check a new Objective-C exception variable declaration.
-VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo,
- QualType T,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
+VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,
+ SourceLocation StartLoc,
+ SourceLocation IdLoc,
+ IdentifierInfo *Id,
bool Invalid) {
// ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage
// duration shall not be qualified by an address-space qualifier."
// Since all parameters have automatic store duration, they can not have
// an address space.
if (T.getAddressSpace() != 0) {
- Diag(NameLoc, diag::err_arg_with_address_space);
+ Diag(IdLoc, diag::err_arg_with_address_space);
Invalid = true;
}
@@ -1975,14 +1956,14 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo,
// Okay: we don't know what this type will instantiate to.
} else if (!T->isObjCObjectPointerType()) {
Invalid = true;
- Diag(NameLoc ,diag::err_catch_param_not_objc_type);
+ Diag(IdLoc ,diag::err_catch_param_not_objc_type);
} else if (T->isObjCQualifiedIdType()) {
Invalid = true;
- Diag(NameLoc, diag::err_illegal_qualifiers_on_catch_parm);
+ Diag(IdLoc, diag::err_illegal_qualifiers_on_catch_parm);
}
- VarDecl *New = VarDecl::Create(Context, CurContext, NameLoc, Name, T, TInfo,
- SC_None, SC_None);
+ VarDecl *New = VarDecl::Create(Context, CurContext, StartLoc, IdLoc, Id,
+ T, TInfo, SC_None, SC_None);
New->setExceptionVariable(true);
if (Invalid)
@@ -2023,8 +2004,10 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
<< Context.getTypeDeclType(OwnedDecl);
}
- VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType, D.getIdentifier(),
- D.getIdentifierLoc(),
+ VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType,
+ D.getSourceRange().getBegin(),
+ D.getIdentifierLoc(),
+ D.getIdentifier(),
D.isInvalidType());
// Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
index 5d7993b..f1033dc 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -96,16 +96,24 @@ bool Sema::CheckDistantExceptionSpec(QualType T) {
}
bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
+ OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator();
+ bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
bool MissingExceptionSpecification = false;
bool MissingEmptyExceptionSpecification = false;
- if (!CheckEquivalentExceptionSpec(PDiag(diag::err_mismatched_exception_spec),
+ unsigned DiagID = diag::err_mismatched_exception_spec;
+ if (getLangOptions().Microsoft)
+ DiagID = diag::warn_mismatched_exception_spec;
+
+ if (!CheckEquivalentExceptionSpec(PDiag(DiagID),
PDiag(diag::note_previous_declaration),
Old->getType()->getAs<FunctionProtoType>(),
Old->getLocation(),
New->getType()->getAs<FunctionProtoType>(),
New->getLocation(),
&MissingExceptionSpecification,
- &MissingEmptyExceptionSpecification))
+ &MissingEmptyExceptionSpecification,
+ /*AllowNoexceptAllMatchWithNoSpec=*/true,
+ IsOperatorNew))
return false;
// The failure was something other than an empty exception
@@ -129,9 +137,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
Context.getSourceManager().isInSystemHeader(Old->getLocation())) &&
Old->isExternC()) {
FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
- EPI.HasExceptionSpec = true;
- EPI.HasAnyExceptionSpec = false;
- EPI.NumExceptions = 0;
+ EPI.ExceptionSpecType = EST_DynamicNone;
QualType NewType = Context.getFunctionType(NewProto->getResultType(),
NewProto->arg_type_begin(),
NewProto->getNumArgs(),
@@ -145,10 +151,14 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
= Old->getType()->getAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
- EPI.HasExceptionSpec = OldProto->hasExceptionSpec();
- EPI.HasAnyExceptionSpec = OldProto->hasAnyExceptionSpec();
- EPI.NumExceptions = OldProto->getNumExceptions();
- EPI.Exceptions = OldProto->exception_begin();
+ EPI.ExceptionSpecType = OldProto->getExceptionSpecType();
+ if (EPI.ExceptionSpecType == EST_Dynamic) {
+ EPI.NumExceptions = OldProto->getNumExceptions();
+ EPI.Exceptions = OldProto->exception_begin();
+ } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
+ // FIXME: We can't just take the expression from the old prototype. It
+ // likely contains references to the old prototype's parameters.
+ }
// Update the type of the function with the appropriate exception
// specification.
@@ -160,7 +170,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// If exceptions are disabled, suppress the warning about missing
// exception specifications for new and delete operators.
- if (!getLangOptions().Exceptions) {
+ if (!getLangOptions().CXXExceptions) {
switch (New->getDeclName().getCXXOverloadedOperator()) {
case OO_New:
case OO_Array_New:
@@ -178,30 +188,53 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// Warn about the lack of exception specification.
llvm::SmallString<128> ExceptionSpecString;
llvm::raw_svector_ostream OS(ExceptionSpecString);
- OS << "throw(";
- bool OnFirstException = true;
- for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(),
- EEnd = OldProto->exception_end();
- E != EEnd;
- ++E) {
- if (OnFirstException)
- OnFirstException = false;
- else
- OS << ", ";
-
- OS << E->getAsString(Context.PrintingPolicy);
+ switch (OldProto->getExceptionSpecType()) {
+ case EST_DynamicNone:
+ OS << "throw()";
+ break;
+
+ case EST_Dynamic: {
+ OS << "throw(";
+ bool OnFirstException = true;
+ for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(),
+ EEnd = OldProto->exception_end();
+ E != EEnd;
+ ++E) {
+ if (OnFirstException)
+ OnFirstException = false;
+ else
+ OS << ", ";
+
+ OS << E->getAsString(Context.PrintingPolicy);
+ }
+ OS << ")";
+ break;
+ }
+
+ case EST_BasicNoexcept:
+ OS << "noexcept";
+ break;
+
+ case EST_ComputedNoexcept:
+ OS << "noexcept(";
+ OldProto->getNoexceptExpr()->printPretty(OS, Context, 0,
+ Context.PrintingPolicy);
+ OS << ")";
+ break;
+
+ default:
+ assert(false && "This spec type is compatible with none.");
}
- OS << ")";
OS.flush();
- SourceLocation AfterParenLoc;
+ SourceLocation FixItLoc;
if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
if (const FunctionTypeLoc *FTLoc = dyn_cast<FunctionTypeLoc>(&TL))
- AfterParenLoc = PP.getLocForEndOfToken(FTLoc->getRParenLoc());
+ FixItLoc = PP.getLocForEndOfToken(FTLoc->getLocalRangeEnd());
}
- if (AfterParenLoc.isInvalid())
+ if (FixItLoc.isInvalid())
Diag(New->getLocation(), diag::warn_missing_exception_specification)
<< New << OS.str();
else {
@@ -209,7 +242,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// late-specified return types.
Diag(New->getLocation(), diag::warn_missing_exception_specification)
<< New << OS.str()
- << FixItHint::CreateInsertion(AfterParenLoc, " " + OS.str().str());
+ << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str());
}
if (!Old->getLocation().isInvalid())
@@ -218,7 +251,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
return false;
}
- Diag(New->getLocation(), diag::err_mismatched_exception_spec);
+ Diag(New->getLocation(), DiagID);
Diag(Old->getLocation(), diag::note_previous_declaration);
return true;
}
@@ -230,26 +263,29 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
bool Sema::CheckEquivalentExceptionSpec(
const FunctionProtoType *Old, SourceLocation OldLoc,
const FunctionProtoType *New, SourceLocation NewLoc) {
+ unsigned DiagID = diag::err_mismatched_exception_spec;
+ if (getLangOptions().Microsoft)
+ DiagID = diag::warn_mismatched_exception_spec;
return CheckEquivalentExceptionSpec(
- PDiag(diag::err_mismatched_exception_spec),
+ PDiag(DiagID),
PDiag(diag::note_previous_declaration),
Old, OldLoc, New, NewLoc);
}
-/// CheckEquivalentExceptionSpec - Check if the two types have equivalent
-/// exception specifications. Exception specifications are equivalent if
-/// they allow exactly the same set of exception types. It does not matter how
-/// that is achieved. See C++ [except.spec]p2.
-bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
+/// CheckEquivalentExceptionSpec - Check if the two types have compatible
+/// exception specifications. See C++ [except.spec]p3.
+bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
const PartialDiagnostic & NoteID,
- const FunctionProtoType *Old,
+ const FunctionProtoType *Old,
SourceLocation OldLoc,
- const FunctionProtoType *New,
+ const FunctionProtoType *New,
SourceLocation NewLoc,
bool *MissingExceptionSpecification,
- bool *MissingEmptyExceptionSpecification) {
+ bool*MissingEmptyExceptionSpecification,
+ bool AllowNoexceptAllMatchWithNoSpec,
+ bool IsOperatorNew) {
// Just completely ignore this under -fno-exceptions.
- if (!getLangOptions().Exceptions)
+ if (!getLangOptions().CXXExceptions)
return false;
if (MissingExceptionSpecification)
@@ -258,29 +294,133 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
if (MissingEmptyExceptionSpecification)
*MissingEmptyExceptionSpecification = false;
- bool OldAny = !Old->hasExceptionSpec() || Old->hasAnyExceptionSpec();
- bool NewAny = !New->hasExceptionSpec() || New->hasAnyExceptionSpec();
- if (getLangOptions().Microsoft) {
- // Treat throw(whatever) as throw(...) to be compatible with MS headers.
- if (New->hasExceptionSpec() && New->getNumExceptions() > 0)
- NewAny = true;
- if (Old->hasExceptionSpec() && Old->getNumExceptions() > 0)
- OldAny = true;
+ // C++0x [except.spec]p3: Two exception-specifications are compatible if:
+ // - both are non-throwing, regardless of their form,
+ // - both have the form noexcept(constant-expression) and the constant-
+ // expressions are equivalent,
+ // - one exception-specification is a noexcept-specification allowing all
+ // exceptions and the other is of the form throw(type-id-list), or
+ // - both are dynamic-exception-specifications that have the same set of
+ // adjusted types.
+ //
+ // C++0x [except.spec]p12: An exception-specifcation is non-throwing if it is
+ // of the form throw(), noexcept, or noexcept(constant-expression) where the
+ // constant-expression yields true.
+ //
+ // CWG 1073 Proposed resolution: Strike the third bullet above.
+ //
+ // C++0x [except.spec]p4: If any declaration of a function has an exception-
+ // specifier that is not a noexcept-specification allowing all exceptions,
+ // all declarations [...] of that function shall have a compatible
+ // exception-specification.
+ //
+ // That last point basically means that noexcept(false) matches no spec.
+ // It's considered when AllowNoexceptAllMatchWithNoSpec is true.
+
+ ExceptionSpecificationType OldEST = Old->getExceptionSpecType();
+ ExceptionSpecificationType NewEST = New->getExceptionSpecType();
+
+ // Shortcut the case where both have no spec.
+ if (OldEST == EST_None && NewEST == EST_None)
+ return false;
+
+ FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context);
+ FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context);
+ if (OldNR == FunctionProtoType::NR_BadNoexcept ||
+ NewNR == FunctionProtoType::NR_BadNoexcept)
+ return false;
+
+ // Dependent noexcept specifiers are compatible with each other, but nothing
+ // else.
+ // One noexcept is compatible with another if the argument is the same
+ if (OldNR == NewNR &&
+ OldNR != FunctionProtoType::NR_NoNoexcept &&
+ NewNR != FunctionProtoType::NR_NoNoexcept)
+ return false;
+ if (OldNR != NewNR &&
+ OldNR != FunctionProtoType::NR_NoNoexcept &&
+ NewNR != FunctionProtoType::NR_NoNoexcept) {
+ Diag(NewLoc, DiagID);
+ if (NoteID.getDiagID() != 0)
+ Diag(OldLoc, NoteID);
+ return true;
+ }
+
+ // The MS extension throw(...) is compatible with itself.
+ if (OldEST == EST_MSAny && NewEST == EST_MSAny)
+ return false;
+
+ // It's also compatible with no spec.
+ if ((OldEST == EST_None && NewEST == EST_MSAny) ||
+ (OldEST == EST_MSAny && NewEST == EST_None))
+ return false;
+
+ // It's also compatible with noexcept(false).
+ if (OldEST == EST_MSAny && NewNR == FunctionProtoType::NR_Throw)
+ return false;
+ if (NewEST == EST_MSAny && OldNR == FunctionProtoType::NR_Throw)
+ return false;
+
+ // As described above, noexcept(false) matches no spec only for functions.
+ if (AllowNoexceptAllMatchWithNoSpec) {
+ if (OldEST == EST_None && NewNR == FunctionProtoType::NR_Throw)
+ return false;
+ if (NewEST == EST_None && OldNR == FunctionProtoType::NR_Throw)
+ return false;
}
- if (OldAny && NewAny)
+ // Any non-throwing specifications are compatible.
+ bool OldNonThrowing = OldNR == FunctionProtoType::NR_Nothrow ||
+ OldEST == EST_DynamicNone;
+ bool NewNonThrowing = NewNR == FunctionProtoType::NR_Nothrow ||
+ NewEST == EST_DynamicNone;
+ if (OldNonThrowing && NewNonThrowing)
return false;
- if (OldAny || NewAny) {
+
+ // As a special compatibility feature, under C++0x we accept no spec and
+ // throw(std::bad_alloc) as equivalent for operator new and operator new[].
+ // This is because the implicit declaration changed, but old code would break.
+ if (getLangOptions().CPlusPlus0x && IsOperatorNew) {
+ const FunctionProtoType *WithExceptions = 0;
+ if (OldEST == EST_None && NewEST == EST_Dynamic)
+ WithExceptions = New;
+ else if (OldEST == EST_Dynamic && NewEST == EST_None)
+ WithExceptions = Old;
+ if (WithExceptions && WithExceptions->getNumExceptions() == 1) {
+ // One has no spec, the other throw(something). If that something is
+ // std::bad_alloc, all conditions are met.
+ QualType Exception = *WithExceptions->exception_begin();
+ if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) {
+ IdentifierInfo* Name = ExRecord->getIdentifier();
+ if (Name && Name->getName() == "bad_alloc") {
+ // It's called bad_alloc, but is it in std?
+ DeclContext* DC = ExRecord->getDeclContext();
+ DC = DC->getEnclosingNamespaceContext();
+ if (NamespaceDecl* NS = dyn_cast<NamespaceDecl>(DC)) {
+ IdentifierInfo* NSName = NS->getIdentifier();
+ DC = DC->getParent();
+ if (NSName && NSName->getName() == "std" &&
+ DC->getEnclosingNamespaceContext()->isTranslationUnit()) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // At this point, the only remaining valid case is two matching dynamic
+ // specifications. We return here unless both specifications are dynamic.
+ if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) {
if (MissingExceptionSpecification && Old->hasExceptionSpec() &&
!New->hasExceptionSpec()) {
// The old type has an exception specification of some sort, but
// the new type does not.
*MissingExceptionSpecification = true;
- if (MissingEmptyExceptionSpecification &&
- !Old->hasAnyExceptionSpec() && Old->getNumExceptions() == 0) {
- // The old type has a throw() exception specification and the
- // new type has no exception specification, and the caller asked
+ if (MissingEmptyExceptionSpecification && OldNonThrowing) {
+ // The old type has a throw() or noexcept(true) exception specification
+ // and the new type has no exception specification, and the caller asked
// to handle this itself.
*MissingEmptyExceptionSpecification = true;
}
@@ -294,8 +434,11 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
return true;
}
+ assert(OldEST == EST_Dynamic && NewEST == EST_Dynamic &&
+ "Exception compatibility logic error: non-dynamic spec slipped through.");
+
bool Success = true;
- // Both have a definite exception spec. Collect the first set, then compare
+ // Both have a dynamic exception spec. Collect the first set, then compare
// to the second.
llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
for (FunctionProtoType::exception_iterator I = Old->exception_begin(),
@@ -331,7 +474,7 @@ bool Sema::CheckExceptionSpecSubset(
const FunctionProtoType *Subset, SourceLocation SubLoc) {
// Just auto-succeed under -fno-exceptions.
- if (!getLangOptions().Exceptions)
+ if (!getLangOptions().CXXExceptions)
return false;
// FIXME: As usual, we could be more specific in our error messages, but
@@ -340,19 +483,66 @@ bool Sema::CheckExceptionSpecSubset(
if (!SubLoc.isValid())
SubLoc = SuperLoc;
+ ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType();
+
// If superset contains everything, we're done.
- if (!Superset->hasExceptionSpec() || Superset->hasAnyExceptionSpec())
+ if (SuperEST == EST_None || SuperEST == EST_MSAny)
+ return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+
+ // If there are dependent noexcept specs, assume everything is fine. Unlike
+ // with the equivalency check, this is safe in this case, because we don't
+ // want to merge declarations. Checks after instantiation will catch any
+ // omissions we make here.
+ // We also shortcut checking if a noexcept expression was bad.
+
+ FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(Context);
+ if (SuperNR == FunctionProtoType::NR_BadNoexcept ||
+ SuperNR == FunctionProtoType::NR_Dependent)
+ return false;
+
+ // Another case of the superset containing everything.
+ if (SuperNR == FunctionProtoType::NR_Throw)
return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+ ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
+
// It does not. If the subset contains everything, we've failed.
- if (!Subset->hasExceptionSpec() || Subset->hasAnyExceptionSpec()) {
+ if (SubEST == EST_None || SubEST == EST_MSAny) {
+ Diag(SubLoc, DiagID);
+ if (NoteID.getDiagID() != 0)
+ Diag(SuperLoc, NoteID);
+ return true;
+ }
+
+ FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context);
+ if (SubNR == FunctionProtoType::NR_BadNoexcept ||
+ SubNR == FunctionProtoType::NR_Dependent)
+ return false;
+
+ // Another case of the subset containing everything.
+ if (SubNR == FunctionProtoType::NR_Throw) {
+ Diag(SubLoc, DiagID);
+ if (NoteID.getDiagID() != 0)
+ Diag(SuperLoc, NoteID);
+ return true;
+ }
+
+ // If the subset contains nothing, we're done.
+ if (SubEST == EST_DynamicNone || SubNR == FunctionProtoType::NR_Nothrow)
+ return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+
+ // Otherwise, if the superset contains nothing, we've failed.
+ if (SuperEST == EST_DynamicNone || SuperNR == FunctionProtoType::NR_Nothrow) {
Diag(SubLoc, DiagID);
if (NoteID.getDiagID() != 0)
Diag(SuperLoc, NoteID);
return true;
}
- // Neither contains everything. Do a proper comparison.
+ assert(SuperEST == EST_Dynamic && SubEST == EST_Dynamic &&
+ "Exception spec subset: non-dynamic case slipped through.");
+
+ // Neither contains everything or nothing. Do a proper comparison.
for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(),
SubE = Subset->exception_end(); SubI != SubE; ++SubI) {
// Take one type from the subset.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
index 415ab3f..20b92b8 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
@@ -16,6 +16,7 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/AnalysisBasedWarnings.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
@@ -56,7 +57,7 @@ using namespace sema;
/// referenced), false otherwise.
///
bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
- bool UnknownObjCClass) {
+ const ObjCInterfaceDecl *UnknownObjCClass) {
if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) {
// If there were any diagnostics suppressed by template argument deduction,
// emit them now.
@@ -68,7 +69,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
Diag(Suppressed[I].first, Suppressed[I].second);
// Clear out the list of suppressed diagnostics, so that we don't emit
- // them again for this specialization. However, we don't remove this
+ // them again for this specialization. However, we don't obsolete this
// entry from the table, because we want to avoid ever emitting these
// diagnostics again.
Suppressed.clear();
@@ -82,13 +83,28 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
return true;
}
- // See if the decl is deprecated.
- if (const DeprecatedAttr *DA = D->getAttr<DeprecatedAttr>())
- EmitDeprecationWarning(D, DA->getMessage(), Loc, UnknownObjCClass);
+ // See if this is a deleted function.
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->isDeleted()) {
+ Diag(Loc, diag::err_deleted_function_use);
+ Diag(D->getLocation(), diag::note_unavailable_here) << true;
+ return true;
+ }
+ }
- // See if the decl is unavailable
- if (const UnavailableAttr *UA = D->getAttr<UnavailableAttr>()) {
- if (UA->getMessage().empty()) {
+ // See if this declaration is unavailable or deprecated.
+ std::string Message;
+ switch (D->getAvailability(&Message)) {
+ case AR_Available:
+ case AR_NotYetIntroduced:
+ break;
+
+ case AR_Deprecated:
+ EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass);
+ break;
+
+ case AR_Unavailable:
+ if (Message.empty()) {
if (!UnknownObjCClass)
Diag(Loc, diag::err_unavailable) << D->getDeclName();
else
@@ -97,17 +113,9 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
}
else
Diag(Loc, diag::err_unavailable_message)
- << D->getDeclName() << UA->getMessage();
- Diag(D->getLocation(), diag::note_unavailable_here) << 0;
- }
-
- // See if this is a deleted function.
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- if (FD->isDeleted()) {
- Diag(Loc, diag::err_deleted_function_use);
- Diag(D->getLocation(), diag::note_unavailable_here) << true;
- return true;
- }
+ << D->getDeclName() << Message;
+ Diag(D->getLocation(), diag::note_unavailable_here) << 0;
+ break;
}
// Warn if this is used but marked unused.
@@ -117,6 +125,23 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
return false;
}
+/// \brief Retrieve the message suffix that should be added to a
+/// diagnostic complaining about the given function being deleted or
+/// unavailable.
+std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) {
+ // FIXME: C++0x implicitly-deleted special member functions could be
+ // detected here so that we could improve diagnostics to say, e.g.,
+ // "base class 'A' had a deleted copy constructor".
+ if (FD->isDeleted())
+ return std::string();
+
+ std::string Message;
+ if (FD->getAvailability(&Message))
+ return ": " + Message;
+
+ return std::string();
+}
+
/// DiagnoseSentinelCalls - This routine checks on method dispatch calls
/// (and other functions in future), which have been declared with sentinel
/// attribute. It warns if call does not have the sentinel argument.
@@ -232,13 +257,13 @@ SourceRange Sema::getExprRange(ExprTy *E) const {
//===----------------------------------------------------------------------===//
/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
-void Sema::DefaultFunctionArrayConversion(Expr *&E) {
+ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) {
QualType Ty = E->getType();
assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");
if (Ty->isFunctionType())
- ImpCastExprToType(E, Context.getPointerType(Ty),
- CK_FunctionToPointerDecay);
+ E = ImpCastExprToType(E, Context.getPointerType(Ty),
+ CK_FunctionToPointerDecay).take();
else if (Ty->isArrayType()) {
// In C90 mode, arrays only promote to pointers if the array expression is
// an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has
@@ -252,25 +277,48 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) {
// T" can be converted to an rvalue of type "pointer to T".
//
if (getLangOptions().C99 || getLangOptions().CPlusPlus || E->isLValue())
- ImpCastExprToType(E, Context.getArrayDecayedType(Ty),
- CK_ArrayToPointerDecay);
+ E = ImpCastExprToType(E, Context.getArrayDecayedType(Ty),
+ CK_ArrayToPointerDecay).take();
+ }
+ return Owned(E);
+}
+
+static void CheckForNullPointerDereference(Sema &S, Expr *E) {
+ // Check to see if we are dereferencing a null pointer. If so,
+ // and if not volatile-qualified, this is undefined behavior that the
+ // optimizer will delete, so warn about it. People sometimes try to use this
+ // to get a deterministic trap and are surprised by clang's behavior. This
+ // only handles the pattern "*null", which is a very syntactic check.
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts()))
+ if (UO->getOpcode() == UO_Deref &&
+ UO->getSubExpr()->IgnoreParenCasts()->
+ isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) &&
+ !UO->getType().isVolatileQualified()) {
+ S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
+ S.PDiag(diag::warn_indirection_through_null)
+ << UO->getSubExpr()->getSourceRange());
+ S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
+ S.PDiag(diag::note_indirection_through_null));
}
}
-void Sema::DefaultLvalueConversion(Expr *&E) {
+ExprResult Sema::DefaultLvalueConversion(Expr *E) {
// C++ [conv.lval]p1:
// A glvalue of a non-function, non-array type T can be
// converted to a prvalue.
- if (!E->isGLValue()) return;
+ if (!E->isGLValue()) return Owned(E);
QualType T = E->getType();
assert(!T.isNull() && "r-value conversion on typeless expression?");
// Create a load out of an ObjCProperty l-value, if necessary.
if (E->getObjectKind() == OK_ObjCProperty) {
- ConvertPropertyForRValue(E);
+ ExprResult Res = ConvertPropertyForRValue(E);
+ if (Res.isInvalid())
+ return Owned(E);
+ E = Res.take();
if (!E->isGLValue())
- return;
+ return Owned(E);
}
// We don't want to throw lvalue-to-rvalue casts on top of
@@ -279,7 +327,7 @@ void Sema::DefaultLvalueConversion(Expr *&E) {
(E->getType() == Context.OverloadTy ||
T->isDependentType() ||
T->isRecordType()))
- return;
+ return Owned(E);
// The C standard is actually really unclear on this point, and
// DR106 tells us what the result should be but not why. It's
@@ -287,7 +335,9 @@ void Sema::DefaultLvalueConversion(Expr *&E) {
// lvalue-to-rvalue at all. Note that expressions of unqualified
// 'void' type are never l-values, but qualified void can be.
if (T->isVoidType())
- return;
+ return Owned(E);
+
+ CheckForNullPointerDereference(*this, E);
// C++ [conv.lval]p1:
// [...] If T is a non-class type, the type of the prvalue is the
@@ -301,27 +351,34 @@ void Sema::DefaultLvalueConversion(Expr *&E) {
if (T.hasQualifiers())
T = T.getUnqualifiedType();
- if (const ArraySubscriptExpr *ae = dyn_cast<ArraySubscriptExpr>(E))
- CheckArrayAccess(ae);
+ CheckArrayAccess(E);
- E = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
- E, 0, VK_RValue);
+ return Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
+ E, 0, VK_RValue));
}
-void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) {
- DefaultFunctionArrayConversion(E);
- DefaultLvalueConversion(E);
+ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E) {
+ ExprResult Res = DefaultFunctionArrayConversion(E);
+ if (Res.isInvalid())
+ return ExprError();
+ Res = DefaultLvalueConversion(Res.take());
+ if (Res.isInvalid())
+ return ExprError();
+ return move(Res);
}
/// UsualUnaryConversions - Performs various conversions that are common to most
/// operators (C99 6.3). The conversions of array and function types are
-/// sometimes surpressed. For example, the array->pointer conversion doesn't
+/// sometimes suppressed. For example, the array->pointer conversion doesn't
/// apply if the array is an argument to the sizeof or address (&) operators.
/// In these instances, this routine should *not* be called.
-Expr *Sema::UsualUnaryConversions(Expr *&E) {
+ExprResult Sema::UsualUnaryConversions(Expr *E) {
// First, convert to an r-value.
- DefaultFunctionArrayLvalueConversion(E);
+ ExprResult Res = DefaultFunctionArrayLvalueConversion(E);
+ if (Res.isInvalid())
+ return Owned(E);
+ E = Res.take();
QualType Ty = E->getType();
assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
@@ -345,60 +402,66 @@ Expr *Sema::UsualUnaryConversions(Expr *&E) {
QualType PTy = Context.isPromotableBitField(E);
if (!PTy.isNull()) {
- ImpCastExprToType(E, PTy, CK_IntegralCast);
- return E;
+ E = ImpCastExprToType(E, PTy, CK_IntegralCast).take();
+ return Owned(E);
}
if (Ty->isPromotableIntegerType()) {
QualType PT = Context.getPromotedIntegerType(Ty);
- ImpCastExprToType(E, PT, CK_IntegralCast);
- return E;
+ E = ImpCastExprToType(E, PT, CK_IntegralCast).take();
+ return Owned(E);
}
}
-
- return E;
+ return Owned(E);
}
/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
/// do not have a prototype. Arguments that have type float are promoted to
/// double. All other argument types are converted by UsualUnaryConversions().
-void Sema::DefaultArgumentPromotion(Expr *&Expr) {
- QualType Ty = Expr->getType();
+ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
+ QualType Ty = E->getType();
assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type");
- UsualUnaryConversions(Expr);
+ ExprResult Res = UsualUnaryConversions(E);
+ if (Res.isInvalid())
+ return Owned(E);
+ E = Res.take();
// If this is a 'float' (CVR qualified or typedef) promote to double.
if (Ty->isSpecificBuiltinType(BuiltinType::Float))
- return ImpCastExprToType(Expr, Context.DoubleTy, CK_FloatingCast);
+ E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).take();
+
+ return Owned(E);
}
/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
/// will warn if the resulting type is not a POD type, and rejects ObjC
-/// interfaces passed by value. This returns true if the argument type is
-/// completely illegal.
-bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT,
+/// interfaces passed by value.
+ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
FunctionDecl *FDecl) {
- DefaultArgumentPromotion(Expr);
+ ExprResult ExprRes = DefaultArgumentPromotion(E);
+ if (ExprRes.isInvalid())
+ return ExprError();
+ E = ExprRes.take();
// __builtin_va_start takes the second argument as a "varargs" argument, but
// it doesn't actually do anything with it. It doesn't need to be non-pod
// etc.
if (FDecl && FDecl->getBuiltinID() == Builtin::BI__builtin_va_start)
- return false;
+ return Owned(E);
- if (Expr->getType()->isObjCObjectType() &&
- DiagRuntimeBehavior(Expr->getLocStart(), 0,
+ if (E->getType()->isObjCObjectType() &&
+ DiagRuntimeBehavior(E->getLocStart(), 0,
PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
- << Expr->getType() << CT))
- return true;
+ << E->getType() << CT))
+ return ExprError();
- if (!Expr->getType()->isPODType() &&
- DiagRuntimeBehavior(Expr->getLocStart(), 0,
+ if (!E->getType()->isPODType() &&
+ DiagRuntimeBehavior(E->getLocStart(), 0,
PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
- << Expr->getType() << CT))
- return true;
+ << E->getType() << CT))
+ return ExprError();
- return false;
+ return Owned(E);
}
/// UsualArithmeticConversions - Performs various conversions that are common to
@@ -407,19 +470,24 @@ bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT,
/// responsible for emitting appropriate error diagnostics.
/// FIXME: verify the conversion rules for "complex int" are consistent with
/// GCC.
-QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
+QualType Sema::UsualArithmeticConversions(ExprResult &lhsExpr, ExprResult &rhsExpr,
bool isCompAssign) {
- if (!isCompAssign)
- UsualUnaryConversions(lhsExpr);
+ if (!isCompAssign) {
+ lhsExpr = UsualUnaryConversions(lhsExpr.take());
+ if (lhsExpr.isInvalid())
+ return QualType();
+ }
- UsualUnaryConversions(rhsExpr);
+ rhsExpr = UsualUnaryConversions(rhsExpr.take());
+ if (rhsExpr.isInvalid())
+ return QualType();
// For conversion purposes, we ignore any qualifiers.
// For example, "const float" and "float" are equivalent.
QualType lhs =
- Context.getCanonicalType(lhsExpr->getType()).getUnqualifiedType();
+ Context.getCanonicalType(lhsExpr.get()->getType()).getUnqualifiedType();
QualType rhs =
- Context.getCanonicalType(rhsExpr->getType()).getUnqualifiedType();
+ Context.getCanonicalType(rhsExpr.get()->getType()).getUnqualifiedType();
// If both types are identical, no conversion is needed.
if (lhs == rhs)
@@ -434,11 +502,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
QualType lhs_unpromoted = lhs;
if (lhs->isPromotableIntegerType())
lhs = Context.getPromotedIntegerType(lhs);
- QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(lhsExpr);
+ QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(lhsExpr.get());
if (!LHSBitfieldPromoteTy.isNull())
lhs = LHSBitfieldPromoteTy;
if (lhs != lhs_unpromoted && !isCompAssign)
- ImpCastExprToType(lhsExpr, lhs, CK_IntegralCast);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), lhs, CK_IntegralCast);
// If both types are identical, no conversion is needed.
if (lhs == rhs)
@@ -455,11 +523,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
if (!RHSComplexFloat && !rhs->isRealFloatingType()) {
if (rhs->isIntegerType()) {
QualType fp = cast<ComplexType>(lhs)->getElementType();
- ImpCastExprToType(rhsExpr, fp, CK_IntegralToFloating);
- ImpCastExprToType(rhsExpr, lhs, CK_FloatingRealToComplex);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), fp, CK_IntegralToFloating);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingRealToComplex);
} else {
assert(rhs->isComplexIntegerType());
- ImpCastExprToType(rhsExpr, lhs, CK_IntegralComplexToFloatingComplex);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralComplexToFloatingComplex);
}
return lhs;
}
@@ -469,11 +537,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
// int -> float -> _Complex float
if (lhs->isIntegerType()) {
QualType fp = cast<ComplexType>(rhs)->getElementType();
- ImpCastExprToType(lhsExpr, fp, CK_IntegralToFloating);
- ImpCastExprToType(lhsExpr, rhs, CK_FloatingRealToComplex);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), fp, CK_IntegralToFloating);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingRealToComplex);
} else {
assert(lhs->isComplexIntegerType());
- ImpCastExprToType(lhsExpr, rhs, CK_IntegralComplexToFloatingComplex);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralComplexToFloatingComplex);
}
}
return rhs;
@@ -495,13 +563,13 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
if (LHSComplexFloat && RHSComplexFloat) {
if (order > 0) {
// _Complex float -> _Complex double
- ImpCastExprToType(rhsExpr, lhs, CK_FloatingComplexCast);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingComplexCast);
return lhs;
} else if (order < 0) {
// _Complex float -> _Complex double
if (!isCompAssign)
- ImpCastExprToType(lhsExpr, rhs, CK_FloatingComplexCast);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingComplexCast);
return rhs;
}
return lhs;
@@ -513,8 +581,8 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
if (order > 0) { // LHS is wider
// float -> _Complex double
QualType fp = cast<ComplexType>(lhs)->getElementType();
- ImpCastExprToType(rhsExpr, fp, CK_FloatingCast);
- ImpCastExprToType(rhsExpr, lhs, CK_FloatingRealToComplex);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), fp, CK_FloatingCast);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingRealToComplex);
return lhs;
}
@@ -522,11 +590,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
QualType result = (order == 0 ? lhs : Context.getComplexType(rhs));
// double -> _Complex double
- ImpCastExprToType(rhsExpr, result, CK_FloatingRealToComplex);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_FloatingRealToComplex);
// _Complex float -> _Complex double
if (!isCompAssign && order < 0)
- ImpCastExprToType(lhsExpr, result, CK_FloatingComplexCast);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_FloatingComplexCast);
return result;
}
@@ -539,8 +607,8 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
// float -> _Complex double
if (!isCompAssign) {
QualType fp = cast<ComplexType>(rhs)->getElementType();
- ImpCastExprToType(lhsExpr, fp, CK_FloatingCast);
- ImpCastExprToType(lhsExpr, rhs, CK_FloatingRealToComplex);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), fp, CK_FloatingCast);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingRealToComplex);
}
return rhs;
}
@@ -550,11 +618,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
// double -> _Complex double
if (!isCompAssign)
- ImpCastExprToType(lhsExpr, result, CK_FloatingRealToComplex);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_FloatingRealToComplex);
// _Complex float -> _Complex double
if (order > 0)
- ImpCastExprToType(rhsExpr, result, CK_FloatingComplexCast);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_FloatingComplexCast);
return result;
}
@@ -568,13 +636,13 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
if (LHSFloat && RHSFloat) {
int order = Context.getFloatingTypeOrder(lhs, rhs);
if (order > 0) {
- ImpCastExprToType(rhsExpr, lhs, CK_FloatingCast);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingCast);
return lhs;
}
assert(order < 0 && "illegal float comparison");
if (!isCompAssign)
- ImpCastExprToType(lhsExpr, rhs, CK_FloatingCast);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingCast);
return rhs;
}
@@ -582,7 +650,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
if (LHSFloat) {
if (rhs->isIntegerType()) {
// Convert rhs to the lhs floating point type.
- ImpCastExprToType(rhsExpr, lhs, CK_IntegralToFloating);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralToFloating);
return lhs;
}
@@ -591,11 +659,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
QualType result = Context.getComplexType(lhs);
// _Complex int -> _Complex float
- ImpCastExprToType(rhsExpr, result, CK_IntegralComplexToFloatingComplex);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_IntegralComplexToFloatingComplex);
// float -> _Complex float
if (!isCompAssign)
- ImpCastExprToType(lhsExpr, result, CK_FloatingRealToComplex);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_FloatingRealToComplex);
return result;
}
@@ -604,7 +672,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
if (lhs->isIntegerType()) {
// Convert lhs to the rhs floating point type.
if (!isCompAssign)
- ImpCastExprToType(lhsExpr, rhs, CK_IntegralToFloating);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralToFloating);
return rhs;
}
@@ -614,10 +682,10 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
// _Complex int -> _Complex float
if (!isCompAssign)
- ImpCastExprToType(lhsExpr, result, CK_IntegralComplexToFloatingComplex);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_IntegralComplexToFloatingComplex);
// float -> _Complex float
- ImpCastExprToType(rhsExpr, result, CK_FloatingRealToComplex);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_FloatingRealToComplex);
return result;
}
@@ -633,21 +701,21 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
assert(order && "inequal types with equal element ordering");
if (order > 0) {
// _Complex int -> _Complex long
- ImpCastExprToType(rhsExpr, lhs, CK_IntegralComplexCast);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralComplexCast);
return lhs;
}
if (!isCompAssign)
- ImpCastExprToType(lhsExpr, rhs, CK_IntegralComplexCast);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralComplexCast);
return rhs;
} else if (lhsComplexInt) {
// int -> _Complex int
- ImpCastExprToType(rhsExpr, lhs, CK_IntegralRealToComplex);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralRealToComplex);
return lhs;
} else if (rhsComplexInt) {
// int -> _Complex int
if (!isCompAssign)
- ImpCastExprToType(lhsExpr, rhs, CK_IntegralRealToComplex);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralRealToComplex);
return rhs;
}
@@ -659,29 +727,29 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
if (lhsSigned == rhsSigned) {
// Same signedness; use the higher-ranked type
if (compare >= 0) {
- ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast);
return lhs;
} else if (!isCompAssign)
- ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast);
return rhs;
} else if (compare != (lhsSigned ? 1 : -1)) {
// The unsigned type has greater than or equal rank to the
// signed type, so use the unsigned type
if (rhsSigned) {
- ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast);
return lhs;
} else if (!isCompAssign)
- ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast);
return rhs;
} else if (Context.getIntWidth(lhs) != Context.getIntWidth(rhs)) {
// The two types are different widths; if we are here, that
// means the signed type is larger than the unsigned type, so
// use the signed type.
if (lhsSigned) {
- ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast);
return lhs;
} else if (!isCompAssign)
- ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast);
return rhs;
} else {
// The signed type is higher-ranked than the unsigned type,
@@ -690,9 +758,9 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
// to the signed type.
QualType result =
Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs);
- ImpCastExprToType(rhsExpr, result, CK_IntegralCast);
+ rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_IntegralCast);
if (!isCompAssign)
- ImpCastExprToType(lhsExpr, result, CK_IntegralCast);
+ lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_IntegralCast);
return result;
}
}
@@ -702,6 +770,163 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
//===----------------------------------------------------------------------===//
+ExprResult
+Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc,
+ SourceLocation DefaultLoc,
+ SourceLocation RParenLoc,
+ Expr *ControllingExpr,
+ MultiTypeArg types,
+ MultiExprArg exprs) {
+ unsigned NumAssocs = types.size();
+ assert(NumAssocs == exprs.size());
+
+ ParsedType *ParsedTypes = types.release();
+ Expr **Exprs = exprs.release();
+
+ TypeSourceInfo **Types = new TypeSourceInfo*[NumAssocs];
+ for (unsigned i = 0; i < NumAssocs; ++i) {
+ if (ParsedTypes[i])
+ (void) GetTypeFromParser(ParsedTypes[i], &Types[i]);
+ else
+ Types[i] = 0;
+ }
+
+ ExprResult ER = CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
+ ControllingExpr, Types, Exprs,
+ NumAssocs);
+ delete [] Types;
+ return ER;
+}
+
+ExprResult
+Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
+ SourceLocation DefaultLoc,
+ SourceLocation RParenLoc,
+ Expr *ControllingExpr,
+ TypeSourceInfo **Types,
+ Expr **Exprs,
+ unsigned NumAssocs) {
+ bool TypeErrorFound = false,
+ IsResultDependent = ControllingExpr->isTypeDependent(),
+ ContainsUnexpandedParameterPack
+ = ControllingExpr->containsUnexpandedParameterPack();
+
+ for (unsigned i = 0; i < NumAssocs; ++i) {
+ if (Exprs[i]->containsUnexpandedParameterPack())
+ ContainsUnexpandedParameterPack = true;
+
+ if (Types[i]) {
+ if (Types[i]->getType()->containsUnexpandedParameterPack())
+ ContainsUnexpandedParameterPack = true;
+
+ if (Types[i]->getType()->isDependentType()) {
+ IsResultDependent = true;
+ } else {
+ // C1X 6.5.1.1p2 "The type name in a generic association shall specify a
+ // complete object type other than a variably modified type."
+ unsigned D = 0;
+ if (Types[i]->getType()->isIncompleteType())
+ D = diag::err_assoc_type_incomplete;
+ else if (!Types[i]->getType()->isObjectType())
+ D = diag::err_assoc_type_nonobject;
+ else if (Types[i]->getType()->isVariablyModifiedType())
+ D = diag::err_assoc_type_variably_modified;
+
+ if (D != 0) {
+ Diag(Types[i]->getTypeLoc().getBeginLoc(), D)
+ << Types[i]->getTypeLoc().getSourceRange()
+ << Types[i]->getType();
+ TypeErrorFound = true;
+ }
+
+ // C1X 6.5.1.1p2 "No two generic associations in the same generic
+ // selection shall specify compatible types."
+ for (unsigned j = i+1; j < NumAssocs; ++j)
+ if (Types[j] && !Types[j]->getType()->isDependentType() &&
+ Context.typesAreCompatible(Types[i]->getType(),
+ Types[j]->getType())) {
+ Diag(Types[j]->getTypeLoc().getBeginLoc(),
+ diag::err_assoc_compatible_types)
+ << Types[j]->getTypeLoc().getSourceRange()
+ << Types[j]->getType()
+ << Types[i]->getType();
+ Diag(Types[i]->getTypeLoc().getBeginLoc(),
+ diag::note_compat_assoc)
+ << Types[i]->getTypeLoc().getSourceRange()
+ << Types[i]->getType();
+ TypeErrorFound = true;
+ }
+ }
+ }
+ }
+ if (TypeErrorFound)
+ return ExprError();
+
+ // If we determined that the generic selection is result-dependent, don't
+ // try to compute the result expression.
+ if (IsResultDependent)
+ return Owned(new (Context) GenericSelectionExpr(
+ Context, KeyLoc, ControllingExpr,
+ Types, Exprs, NumAssocs, DefaultLoc,
+ RParenLoc, ContainsUnexpandedParameterPack));
+
+ llvm::SmallVector<unsigned, 1> CompatIndices;
+ unsigned DefaultIndex = -1U;
+ for (unsigned i = 0; i < NumAssocs; ++i) {
+ if (!Types[i])
+ DefaultIndex = i;
+ else if (Context.typesAreCompatible(ControllingExpr->getType(),
+ Types[i]->getType()))
+ CompatIndices.push_back(i);
+ }
+
+ // C1X 6.5.1.1p2 "The controlling expression of a generic selection shall have
+ // type compatible with at most one of the types named in its generic
+ // association list."
+ if (CompatIndices.size() > 1) {
+ // We strip parens here because the controlling expression is typically
+ // parenthesized in macro definitions.
+ ControllingExpr = ControllingExpr->IgnoreParens();
+ Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match)
+ << ControllingExpr->getSourceRange() << ControllingExpr->getType()
+ << (unsigned) CompatIndices.size();
+ for (llvm::SmallVector<unsigned, 1>::iterator I = CompatIndices.begin(),
+ E = CompatIndices.end(); I != E; ++I) {
+ Diag(Types[*I]->getTypeLoc().getBeginLoc(),
+ diag::note_compat_assoc)
+ << Types[*I]->getTypeLoc().getSourceRange()
+ << Types[*I]->getType();
+ }
+ return ExprError();
+ }
+
+ // C1X 6.5.1.1p2 "If a generic selection has no default generic association,
+ // its controlling expression shall have type compatible with exactly one of
+ // the types named in its generic association list."
+ if (DefaultIndex == -1U && CompatIndices.size() == 0) {
+ // We strip parens here because the controlling expression is typically
+ // parenthesized in macro definitions.
+ ControllingExpr = ControllingExpr->IgnoreParens();
+ Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_no_match)
+ << ControllingExpr->getSourceRange() << ControllingExpr->getType();
+ return ExprError();
+ }
+
+ // C1X 6.5.1.1p3 "If a generic selection has a generic association with a
+ // type name that is compatible with the type of the controlling expression,
+ // then the result expression of the generic selection is the expression
+ // in that generic association. Otherwise, the result expression of the
+ // generic selection is the expression in the default generic association."
+ unsigned ResultIndex =
+ CompatIndices.size() ? CompatIndices[0] : DefaultIndex;
+
+ return Owned(new (Context) GenericSelectionExpr(
+ Context, KeyLoc, ControllingExpr,
+ Types, Exprs, NumAssocs, DefaultLoc,
+ RParenLoc, ContainsUnexpandedParameterPack,
+ ResultIndex));
+}
+
/// ActOnStringLiteral - The specified tokens were lexed as pasted string
/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string
/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
@@ -721,8 +946,10 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
StringTokLocs.push_back(StringToks[i].getLocation());
QualType StrTy = Context.CharTy;
- if (Literal.AnyWide) StrTy = Context.getWCharType();
- if (Literal.Pascal) StrTy = Context.UnsignedCharTy;
+ if (Literal.AnyWide)
+ StrTy = Context.getWCharType();
+ else if (Literal.Pascal)
+ StrTy = Context.UnsignedCharTy;
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings)
@@ -738,7 +965,7 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
return Owned(StringLiteral::Create(Context, Literal.GetString(),
Literal.GetStringLength(),
- Literal.AnyWide, StrTy,
+ Literal.AnyWide, Literal.Pascal, StrTy,
&StringTokLocs[0],
StringTokLocs.size()));
}
@@ -783,11 +1010,20 @@ diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
// diagnose this.
if (!S.CurContext->isFunctionOrMethod()) return CR_NoCapture;
- // This particular madness can happen in ill-formed default
- // arguments; claim it's okay and let downstream code handle it.
- if (isa<ParmVarDecl>(var) &&
- S.CurContext == var->getDeclContext()->getParent())
- return CR_NoCapture;
+ // Certain madnesses can happen with parameter declarations, which
+ // we want to ignore.
+ if (isa<ParmVarDecl>(var)) {
+ // - If the parameter still belongs to the translation unit, then
+ // we're actually just using one parameter in the declaration of
+ // the next. This is useful in e.g. VLAs.
+ if (isa<TranslationUnitDecl>(var->getDeclContext()))
+ return CR_NoCapture;
+
+ // - This particular madness can happen in ill-formed default
+ // arguments; claim it's okay and let downstream code handle it.
+ if (S.CurContext == var->getDeclContext()->getParent())
+ return CR_NoCapture;
+ }
DeclarationName functionName;
if (FunctionDecl *fn = dyn_cast<FunctionDecl>(var->getDeclContext()))
@@ -889,8 +1125,18 @@ static CaptureResult shouldCaptureValueReference(Sema &S, SourceLocation loc,
// Build a copy expression.
Expr *copyExpr = 0;
- if (!byRef && S.getLangOptions().CPlusPlus &&
- !type->isDependentType() && type->isStructureOrClassType()) {
+ const RecordType *rtype;
+ if (!byRef && S.getLangOptions().CPlusPlus && !type->isDependentType() &&
+ (rtype = type->getAs<RecordType>())) {
+
+ // The capture logic needs the destructor, so make sure we mark it.
+ // Usually this is unnecessary because most local variables have
+ // their destructors marked at declaration time, but parameters are
+ // an exception because it's technically only the call site that
+ // actually requires the destructor.
+ if (isa<ParmVarDecl>(var))
+ S.FinalizeVarWithDestructor(var, rtype);
+
// According to the blocks spec, the capture of a variable from
// the stack requires a const copy constructor. This is not true
// of the copy/move done to move a __block variable to the heap.
@@ -974,8 +1220,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
MarkDeclarationReferenced(NameInfo.getLoc(), D);
Expr *E = DeclRefExpr::Create(Context,
- SS? (NestedNameSpecifier *)SS->getScopeRep() : 0,
- SS? SS->getRange() : SourceRange(),
+ SS? SS->getWithLocInContext(Context)
+ : NestedNameSpecifierLoc(),
D, NameInfo, Ty, VK);
// Just in case we're building an illegal pointer-to-member.
@@ -1261,12 +1507,24 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
return IMA_Error_StaticContext;
}
+ CXXRecordDecl *
+ contextClass = cast<CXXMethodDecl>(DC)->getParent()->getCanonicalDecl();
+
+ // [class.mfct.non-static]p3:
+ // ...is used in the body of a non-static member function of class X,
+ // if name lookup (3.4.1) resolves the name in the id-expression to a
+ // non-static non-type member of some class C [...]
+ // ...if C is not X or a base class of X, the class member access expression
+ // is ill-formed.
+ if (R.getNamingClass() &&
+ contextClass != R.getNamingClass()->getCanonicalDecl() &&
+ contextClass->isProvablyNotDerivedFrom(R.getNamingClass()))
+ return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated);
+
// If we can prove that the current context is unrelated to all the
// declaring classes, it can't be an implicit member reference (in
// which case it's an error if any of those members are selected).
- if (IsProvablyNotDerivedFrom(SemaRef,
- cast<CXXMethodDecl>(DC)->getParent(),
- Classes))
+ if (IsProvablyNotDerivedFrom(SemaRef, contextClass, Classes))
return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated);
return (hasNonInstance ? IMA_Mixed : IMA_Instance);
@@ -1350,10 +1608,13 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
TemplateArgumentListInfo TList;
if (ULE->hasExplicitTemplateArgs())
ULE->copyTemplateArgumentsInto(TList);
+
+ CXXScopeSpec SS;
+ SS.Adopt(ULE->getQualifierLoc());
CXXDependentScopeMemberExpr *DepExpr =
CXXDependentScopeMemberExpr::Create(
Context, DepThis, DepThisType, true, SourceLocation(),
- ULE->getQualifier(), ULE->getQualifierRange(), NULL,
+ SS.getWithLocInContext(Context), NULL,
R.getLookupNameInfo(), &TList);
CallsUndergoingInstantiation.back()->setCallee(DepExpr);
} else {
@@ -1479,11 +1740,10 @@ bool Sema::canSynthesizeProvisionalIvar(ObjCPropertyDecl *Property) {
return true;
}
-static ObjCIvarDecl *SynthesizeProvisionalIvar(Sema &SemaRef,
- LookupResult &Lookup,
- IdentifierInfo *II,
- SourceLocation NameLoc) {
- ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl();
+ObjCIvarDecl *Sema::SynthesizeProvisionalIvar(LookupResult &Lookup,
+ IdentifierInfo *II,
+ SourceLocation NameLoc) {
+ ObjCMethodDecl *CurMeth = getCurMethodDecl();
bool LookForIvars;
if (Lookup.empty())
LookForIvars = true;
@@ -1503,7 +1763,7 @@ static ObjCIvarDecl *SynthesizeProvisionalIvar(Sema &SemaRef,
if (!ClassImpDecl)
return 0;
bool DynamicImplSeen = false;
- ObjCPropertyDecl *property = SemaRef.LookupPropertyDecl(IDecl, II);
+ ObjCPropertyDecl *property = LookupPropertyDecl(IDecl, II);
if (!property)
return 0;
if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II)) {
@@ -1515,9 +1775,9 @@ static ObjCIvarDecl *SynthesizeProvisionalIvar(Sema &SemaRef,
return 0;
}
if (!DynamicImplSeen) {
- QualType PropType = SemaRef.Context.getCanonicalType(property->getType());
- ObjCIvarDecl *Ivar = ObjCIvarDecl::Create(SemaRef.Context, ClassImpDecl,
- NameLoc,
+ QualType PropType = Context.getCanonicalType(property->getType());
+ ObjCIvarDecl *Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
+ NameLoc, NameLoc,
II, PropType, /*Dinfo=*/0,
ObjCIvarDecl::Private,
(Expr *)0, true);
@@ -1619,7 +1879,7 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
// Synthesize ivars lazily.
if (getLangOptions().ObjCDefaultSynthProperties &&
getLangOptions().ObjCNonFragileABI2) {
- if (SynthesizeProvisionalIvar(*this, R, II, NameLoc)) {
+ if (SynthesizeProvisionalIvar(R, II, NameLoc)) {
if (const ObjCPropertyDecl *Property =
canSynthesizeProvisionalIvar(II)) {
Diag(NameLoc, diag::warn_synthesized_ivar_access) << II;
@@ -1850,13 +2110,35 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
if (SelfExpr.isInvalid())
return ExprError();
- Expr *SelfE = SelfExpr.take();
- DefaultLvalueConversion(SelfE);
+ SelfExpr = DefaultLvalueConversion(SelfExpr.take());
+ if (SelfExpr.isInvalid())
+ return ExprError();
MarkDeclarationReferenced(Loc, IV);
+ Expr *base = SelfExpr.take();
+ base = base->IgnoreParenImpCasts();
+ if (const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(base)) {
+ const NamedDecl *ND = DE->getDecl();
+ if (!isa<ImplicitParamDecl>(ND)) {
+ // relax the rule such that it is allowed to have a shadow 'self'
+ // where stand-alone ivar can be found in this 'self' object.
+ // This is to match gcc's behavior.
+ ObjCInterfaceDecl *selfIFace = 0;
+ if (const ObjCObjectPointerType *OPT =
+ base->getType()->getAsObjCInterfacePointerType())
+ selfIFace = OPT->getInterfaceDecl();
+ if (!selfIFace ||
+ !selfIFace->lookupInstanceVariable(IV->getIdentifier())) {
+ Diag(Loc, diag::error_implicit_ivar_access)
+ << IV->getDeclName();
+ Diag(ND->getLocation(), diag::note_declared_at);
+ return ExprError();
+ }
+ }
+ }
return Owned(new (Context)
ObjCIvarRefExpr(IV, IV->getType(), Loc,
- SelfE, true, true));
+ SelfExpr.take(), true, true));
}
} else if (CurMethod->isInstanceMethod()) {
// We should warn if a local variable hides an ivar.
@@ -1902,14 +2184,14 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
/// * Finally we cast from the declaring class to the "true"
/// declaring class of the member. This conversion does not
/// obey access control.
-bool
-Sema::PerformObjectMemberConversion(Expr *&From,
+ExprResult
+Sema::PerformObjectMemberConversion(Expr *From,
NestedNameSpecifier *Qualifier,
NamedDecl *FoundDecl,
NamedDecl *Member) {
CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext());
if (!RD)
- return false;
+ return Owned(From);
QualType DestRecordType;
QualType DestType;
@@ -1929,7 +2211,7 @@ Sema::PerformObjectMemberConversion(Expr *&From,
}
} else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member)) {
if (Method->isStatic())
- return false;
+ return Owned(From);
DestType = Method->getThisType(Context);
DestRecordType = DestType->getPointeeType();
@@ -1943,15 +2225,15 @@ Sema::PerformObjectMemberConversion(Expr *&From,
}
} else {
// No conversion necessary.
- return false;
+ return Owned(From);
}
if (DestType->isDependentType() || FromType->isDependentType())
- return false;
+ return Owned(From);
// If the unqualified types are the same, no conversion is necessary.
if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
- return false;
+ return Owned(From);
SourceRange FromRange = From->getSourceRange();
SourceLocation FromLoc = FromRange.getBegin();
@@ -1990,12 +2272,12 @@ Sema::PerformObjectMemberConversion(Expr *&From,
CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, QRecordType,
FromLoc, FromRange, &BasePath))
- return true;
+ return ExprError();
if (PointerConversions)
QType = Context.getPointerType(QType);
- ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase,
- VK, &BasePath);
+ From = ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase,
+ VK, &BasePath).take();
FromType = QType;
FromRecordType = QRecordType;
@@ -2003,7 +2285,7 @@ Sema::PerformObjectMemberConversion(Expr *&From,
// If the qualifier type was the same as the destination type,
// we're done.
if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
- return false;
+ return Owned(From);
}
}
@@ -2026,13 +2308,13 @@ Sema::PerformObjectMemberConversion(Expr *&From,
CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, URecordType,
FromLoc, FromRange, &BasePath))
- return true;
+ return ExprError();
QualType UType = URecordType;
if (PointerConversions)
UType = Context.getPointerType(UType);
- ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase,
- VK, &BasePath);
+ From = ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase,
+ VK, &BasePath).take();
FromType = UType;
FromRecordType = URecordType;
}
@@ -2046,11 +2328,10 @@ Sema::PerformObjectMemberConversion(Expr *&From,
if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType,
FromLoc, FromRange, &BasePath,
IgnoreAccess))
- return true;
+ return ExprError();
- ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase,
- VK, &BasePath);
- return false;
+ return ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase,
+ VK, &BasePath);
}
/// \brief Build a MemberExpr AST node.
@@ -2061,14 +2342,7 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
QualType Ty,
ExprValueKind VK, ExprObjectKind OK,
const TemplateArgumentListInfo *TemplateArgs = 0) {
- NestedNameSpecifier *Qualifier = 0;
- SourceRange QualifierRange;
- if (SS.isSet()) {
- Qualifier = (NestedNameSpecifier *) SS.getScopeRep();
- QualifierRange = SS.getRange();
- }
-
- return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange,
+ return MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C),
Member, FoundDecl, MemberNameInfo,
TemplateArgs, Ty, VK, OK);
}
@@ -2123,10 +2397,12 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
}
S.MarkDeclarationReferenced(MemberNameInfo.getLoc(), Field);
- if (S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),
- FoundDecl, Field))
+ ExprResult Base =
+ S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),
+ FoundDecl, Field);
+ if (Base.isInvalid())
return ExprError();
- return S.Owned(BuildMemberExpr(S.Context, BaseExpr, IsArrow, SS,
+ return S.Owned(BuildMemberExpr(S.Context, Base.take(), IsArrow, SS,
Field, FoundDecl, MemberNameInfo,
MemberType, VK, OK));
}
@@ -2234,7 +2510,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
/// were not overloaded, and it doesn't promise that the declaration
/// will in fact be used.
static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) {
- if (isa<TypedefDecl>(D)) {
+ if (isa<TypedefNameDecl>(D)) {
S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName();
return true;
}
@@ -2276,8 +2552,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
UnresolvedLookupExpr *ULE
= UnresolvedLookupExpr::Create(Context, R.getNamingClass(),
- (NestedNameSpecifier*) SS.getScopeRep(),
- SS.getRange(), R.getLookupNameInfo(),
+ SS.getWithLocInContext(Context),
+ R.getLookupNameInfo(),
NeedsADL, R.isOverloadedResult(),
R.begin(), R.end());
@@ -2433,6 +2709,16 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
break;
case Decl::Function: {
+ const FunctionType *fty = type->castAs<FunctionType>();
+
+ // If we're referring to a function with an __unknown_anytype
+ // result type, make the entire expression __unknown_anytype.
+ if (fty->getResultType() == Context.UnknownAnyTy) {
+ type = Context.UnknownAnyTy;
+ valueKind = VK_RValue;
+ break;
+ }
+
// Functions are l-values in C++.
if (getLangOptions().CPlusPlus) {
valueKind = VK_LValue;
@@ -2444,10 +2730,10 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
// used for checking compatibility. Therefore, when referencing
// the function, we pretend that we don't have the full function
// type.
- if (!cast<FunctionDecl>(VD)->hasPrototype())
- if (const FunctionProtoType *proto = type->getAs<FunctionProtoType>())
- type = Context.getFunctionNoProtoType(proto->getResultType(),
- proto->getExtInfo());
+ if (!cast<FunctionDecl>(VD)->hasPrototype() &&
+ isa<FunctionProtoType>(fty))
+ type = Context.getFunctionNoProtoType(fty->getResultType(),
+ fty->getExtInfo());
// Functions are r-values in C.
valueKind = VK_RValue;
@@ -2455,6 +2741,16 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
}
case Decl::CXXMethod:
+ // If we're referring to a method with an __unknown_anytype
+ // result type, make the entire expression __unknown_anytype.
+ // This should only be possible with a type written directly.
+ if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(VD->getType()))
+ if (proto->getResultType() == Context.UnknownAnyTy) {
+ type = Context.UnknownAnyTy;
+ valueKind = VK_RValue;
+ break;
+ }
+
// C++ methods are l-values if static, r-values if non-static.
if (cast<CXXMethodDecl>(VD)->isStatic()) {
valueKind = VK_LValue;
@@ -2478,8 +2774,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
return ExprError();
}
-ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
- tok::TokenKind Kind) {
+ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
PredefinedExpr::IdentType IT;
switch (Kind) {
@@ -2606,9 +2901,14 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
bool isExact = (result == APFloat::opOK);
Res = FloatingLiteral::Create(Context, Val, isExact, Ty, Tok.getLocation());
- if (getLangOptions().SinglePrecisionConstants && Ty == Context.DoubleTy)
- ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast);
-
+ if (Ty == Context.DoubleTy) {
+ if (getLangOptions().SinglePrecisionConstants) {
+ Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take();
+ } else if (getLangOptions().OpenCL && !getOpenCLOptions().cl_khr_fp64) {
+ Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64);
+ Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take();
+ }
+ }
} else if (!Literal.isIntegerLiteral()) {
return ExprError();
} else {
@@ -2716,10 +3016,10 @@ ExprResult Sema::ActOnParenExpr(SourceLocation L,
/// The UsualUnaryConversions() function is *not* called by this routine.
/// See C99 6.3.2.1p[2-4] for more details.
-bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
- SourceLocation OpLoc,
- SourceRange ExprRange,
- bool isSizeof) {
+bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType exprType,
+ SourceLocation OpLoc,
+ SourceRange ExprRange,
+ UnaryExprOrTypeTrait ExprKind) {
if (exprType->isDependentType())
return false;
@@ -2730,30 +3030,47 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
if (const ReferenceType *Ref = exprType->getAs<ReferenceType>())
exprType = Ref->getPointeeType();
+ // [OpenCL 1.1 6.11.12] "The vec_step built-in function takes a built-in
+ // scalar or vector data type argument..."
+ // Every built-in scalar type (OpenCL 1.1 6.1.1) is either an arithmetic
+ // type (C99 6.2.5p18) or void.
+ if (ExprKind == UETT_VecStep) {
+ if (!(exprType->isArithmeticType() || exprType->isVoidType() ||
+ exprType->isVectorType())) {
+ Diag(OpLoc, diag::err_vecstep_non_scalar_vector_type)
+ << exprType << ExprRange;
+ return true;
+ }
+ }
+
// C99 6.5.3.4p1:
if (exprType->isFunctionType()) {
// alignof(function) is allowed as an extension.
- if (isSizeof)
- Diag(OpLoc, diag::ext_sizeof_function_type) << ExprRange;
+ if (ExprKind == UETT_SizeOf)
+ Diag(OpLoc, diag::ext_sizeof_function_type)
+ << ExprRange;
return false;
}
- // Allow sizeof(void)/alignof(void) as an extension.
+ // Allow sizeof(void)/alignof(void) as an extension. vec_step(void) is not
+ // an extension, as void is a built-in scalar type (OpenCL 1.1 6.1.1).
if (exprType->isVoidType()) {
- Diag(OpLoc, diag::ext_sizeof_void_type)
- << (isSizeof ? "sizeof" : "__alignof") << ExprRange;
+ if (ExprKind != UETT_VecStep)
+ Diag(OpLoc, diag::ext_sizeof_void_type)
+ << ExprKind << ExprRange;
return false;
}
if (RequireCompleteType(OpLoc, exprType,
PDiag(diag::err_sizeof_alignof_incomplete_type)
- << int(!isSizeof) << ExprRange))
+ << ExprKind << ExprRange))
return true;
// Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode.
if (LangOpts.ObjCNonFragileABI && exprType->isObjCObjectType()) {
Diag(OpLoc, diag::err_sizeof_nonfragile_interface)
- << exprType << isSizeof << ExprRange;
+ << exprType << (ExprKind == UETT_SizeOf)
+ << ExprRange;
return true;
}
@@ -2783,109 +3100,132 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E, SourceLocation OpLoc,
if (isa<FieldDecl>(ME->getMemberDecl()))
return false;
- return S.CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false);
+ return S.CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, ExprRange,
+ UETT_AlignOf);
+}
+
+bool Sema::CheckVecStepExpr(Expr *E, SourceLocation OpLoc,
+ SourceRange ExprRange) {
+ E = E->IgnoreParens();
+
+ // Cannot know anything else if the expression is dependent.
+ if (E->isTypeDependent())
+ return false;
+
+ return CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, ExprRange,
+ UETT_VecStep);
}
/// \brief Build a sizeof or alignof expression given a type operand.
ExprResult
-Sema::CreateSizeOfAlignOfExpr(TypeSourceInfo *TInfo,
- SourceLocation OpLoc,
- bool isSizeOf, SourceRange R) {
+Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
+ SourceLocation OpLoc,
+ UnaryExprOrTypeTrait ExprKind,
+ SourceRange R) {
if (!TInfo)
return ExprError();
QualType T = TInfo->getType();
if (!T->isDependentType() &&
- CheckSizeOfAlignOfOperand(T, OpLoc, R, isSizeOf))
+ CheckUnaryExprOrTypeTraitOperand(T, OpLoc, R, ExprKind))
return ExprError();
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
- return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, TInfo,
- Context.getSizeType(), OpLoc,
- R.getEnd()));
+ return Owned(new (Context) UnaryExprOrTypeTraitExpr(ExprKind, TInfo,
+ Context.getSizeType(),
+ OpLoc, R.getEnd()));
}
/// \brief Build a sizeof or alignof expression given an expression
/// operand.
ExprResult
-Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
- bool isSizeOf, SourceRange R) {
+Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
+ UnaryExprOrTypeTrait ExprKind,
+ SourceRange R) {
// Verify that the operand is valid.
bool isInvalid = false;
if (E->isTypeDependent()) {
// Delay type-checking for type-dependent expressions.
- } else if (!isSizeOf) {
+ } else if (ExprKind == UETT_AlignOf) {
isInvalid = CheckAlignOfExpr(*this, E, OpLoc, R);
+ } else if (ExprKind == UETT_VecStep) {
+ isInvalid = CheckVecStepExpr(E, OpLoc, R);
} else if (E->getBitField()) { // C99 6.5.3.4p1.
Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0;
isInvalid = true;
} else if (E->getType()->isPlaceholderType()) {
- ExprResult PE = CheckPlaceholderExpr(E, OpLoc);
+ ExprResult PE = CheckPlaceholderExpr(E);
if (PE.isInvalid()) return ExprError();
- return CreateSizeOfAlignOfExpr(PE.take(), OpLoc, isSizeOf, R);
+ return CreateUnaryExprOrTypeTraitExpr(PE.take(), OpLoc, ExprKind, R);
} else {
- isInvalid = CheckSizeOfAlignOfOperand(E->getType(), OpLoc, R, true);
+ isInvalid = CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, R,
+ UETT_SizeOf);
}
if (isInvalid)
return ExprError();
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
- return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, E,
- Context.getSizeType(), OpLoc,
- R.getEnd()));
+ return Owned(new (Context) UnaryExprOrTypeTraitExpr(ExprKind, E,
+ Context.getSizeType(),
+ OpLoc, R.getEnd()));
}
-/// ActOnSizeOfAlignOfExpr - Handle @c sizeof(type) and @c sizeof @c expr and
-/// the same for @c alignof and @c __alignof
+/// ActOnUnaryExprOrTypeTraitExpr - Handle @c sizeof(type) and @c sizeof @c
+/// expr and the same for @c alignof and @c __alignof
/// Note that the ArgRange is invalid if isType is false.
ExprResult
-Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
- void *TyOrEx, const SourceRange &ArgRange) {
+Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
+ UnaryExprOrTypeTrait ExprKind, bool isType,
+ void *TyOrEx, const SourceRange &ArgRange) {
// If error parsing type, ignore.
if (TyOrEx == 0) return ExprError();
if (isType) {
TypeSourceInfo *TInfo;
(void) GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrEx), &TInfo);
- return CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeof, ArgRange);
+ return CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, ArgRange);
}
Expr *ArgEx = (Expr *)TyOrEx;
ExprResult Result
- = CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange());
+ = CreateUnaryExprOrTypeTraitExpr(ArgEx, OpLoc, ExprKind,
+ ArgEx->getSourceRange());
return move(Result);
}
-static QualType CheckRealImagOperand(Sema &S, Expr *&V, SourceLocation Loc,
+static QualType CheckRealImagOperand(Sema &S, ExprResult &V, SourceLocation Loc,
bool isReal) {
- if (V->isTypeDependent())
+ if (V.get()->isTypeDependent())
return S.Context.DependentTy;
// _Real and _Imag are only l-values for normal l-values.
- if (V->getObjectKind() != OK_Ordinary)
- S.DefaultLvalueConversion(V);
+ if (V.get()->getObjectKind() != OK_Ordinary) {
+ V = S.DefaultLvalueConversion(V.take());
+ if (V.isInvalid())
+ return QualType();
+ }
// These operators return the element type of a complex type.
- if (const ComplexType *CT = V->getType()->getAs<ComplexType>())
+ if (const ComplexType *CT = V.get()->getType()->getAs<ComplexType>())
return CT->getElementType();
// Otherwise they pass through real integer and floating point types here.
- if (V->getType()->isArithmeticType())
- return V->getType();
+ if (V.get()->getType()->isArithmeticType())
+ return V.get()->getType();
// Test for placeholders.
- ExprResult PR = S.CheckPlaceholderExpr(V, Loc);
+ ExprResult PR = S.CheckPlaceholderExpr(V.get());
if (PR.isInvalid()) return QualType();
- if (PR.take() != V) {
- V = PR.take();
+ if (PR.get() != V.get()) {
+ V = move(PR);
return CheckRealImagOperand(S, V, Loc, isReal);
}
// Reject anything else.
- S.Diag(Loc, diag::err_realimag_invalid_type) << V->getType()
+ S.Diag(Loc, diag::err_realimag_invalid_type) << V.get()->getType()
<< (isReal ? "__real" : "__imag");
return QualType();
}
@@ -2955,9 +3295,16 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Expr *RHSExp = Idx;
// Perform default conversions.
- if (!LHSExp->getType()->getAs<VectorType>())
- DefaultFunctionArrayLvalueConversion(LHSExp);
- DefaultFunctionArrayLvalueConversion(RHSExp);
+ if (!LHSExp->getType()->getAs<VectorType>()) {
+ ExprResult Result = DefaultFunctionArrayLvalueConversion(LHSExp);
+ if (Result.isInvalid())
+ return ExprError();
+ LHSExp = Result.take();
+ }
+ ExprResult Result = DefaultFunctionArrayLvalueConversion(RHSExp);
+ if (Result.isInvalid())
+ return ExprError();
+ RHSExp = Result.take();
QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
ExprValueKind VK = VK_LValue;
@@ -3010,8 +3357,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
// force the promotion here.
Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
LHSExp->getSourceRange();
- ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy),
- CK_ArrayToPointerDecay);
+ LHSExp = ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy),
+ CK_ArrayToPointerDecay).take();
LHSTy = LHSExp->getType();
BaseExpr = LHSExp;
@@ -3021,8 +3368,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
// Same as previous, except for 123[f().a] case
Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
RHSExp->getSourceRange();
- ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy),
- CK_ArrayToPointerDecay);
+ RHSExp = ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy),
+ CK_ArrayToPointerDecay).take();
RHSTy = RHSExp->getType();
BaseExpr = RHSExp;
@@ -3269,8 +3616,7 @@ Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,
// must have pointer type, and the accessed type is the pointee.
return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, BaseType,
IsArrow, OpLoc,
- SS.getScopeRep(),
- SS.getRange(),
+ SS.getWithLocInContext(Context),
FirstQualifierInScope,
NameInfo, TemplateArgs));
}
@@ -3441,10 +3787,15 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
// Explicit member accesses.
} else {
+ ExprResult BaseResult = Owned(Base);
ExprResult Result =
- LookupMemberExpr(R, Base, IsArrow, OpLoc,
+ LookupMemberExpr(R, BaseResult, IsArrow, OpLoc,
SS, /*ObjCImpDecl*/ 0, TemplateArgs != 0);
+ if (BaseResult.isInvalid())
+ return ExprError();
+ Base = BaseResult.take();
+
if (Result.isInvalid()) {
Owned(Base);
return ExprError();
@@ -3477,7 +3828,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
}
R.setBaseObjectType(BaseType);
- NestedNameSpecifier *Qualifier = SS.getScopeRep();
const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();
DeclarationName MemberName = MemberNameInfo.getName();
SourceLocation MemberLoc = MemberNameInfo.getLoc();
@@ -3522,7 +3872,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
= UnresolvedMemberExpr::Create(Context, R.isUnresolvableResult(),
BaseExpr, BaseExprType,
IsArrow, OpLoc,
- Qualifier, SS.getRange(),
+ SS.getWithLocInContext(Context),
MemberNameInfo,
TemplateArgs, R.begin(), R.end());
@@ -3569,8 +3919,12 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
// Perform a property load on the base regardless of whether we
// actually need it for the declaration.
- if (BaseExpr->getObjectKind() == OK_ObjCProperty)
- ConvertPropertyForRValue(BaseExpr);
+ if (BaseExpr->getObjectKind() == OK_ObjCProperty) {
+ ExprResult Result = ConvertPropertyForRValue(BaseExpr);
+ if (Result.isInvalid())
+ return ExprError();
+ BaseExpr = Result.take();
+ }
if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow,
@@ -3591,12 +3945,20 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
}
if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {
+ ExprValueKind valueKind;
+ QualType type;
+ if (MemberFn->isInstance()) {
+ valueKind = VK_RValue;
+ type = Context.BoundMemberTy;
+ } else {
+ valueKind = VK_LValue;
+ type = MemberFn->getType();
+ }
+
MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
MemberFn, FoundDecl, MemberNameInfo,
- MemberFn->getType(),
- MemberFn->isInstance() ? VK_RValue : VK_LValue,
- OK_Ordinary));
+ type, valueKind, OK_Ordinary));
}
assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
@@ -3629,9 +3991,9 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
/// types would be profitable. The redefinition type is whatever
/// this translation unit tried to typedef to id/Class; we store
/// it to the side and then re-use it in places like this.
-static bool ShouldTryAgainWithRedefinitionType(Sema &S, Expr *&base) {
+static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) {
const ObjCObjectPointerType *opty
- = base->getType()->getAs<ObjCObjectPointerType>();
+ = base.get()->getType()->getAs<ObjCObjectPointerType>();
if (!opty) return false;
const ObjCObjectType *ty = opty->getObjectType();
@@ -3651,7 +4013,7 @@ static bool ShouldTryAgainWithRedefinitionType(Sema &S, Expr *&base) {
if (opty && !opty->getObjectType()->getInterface() != 0)
return false;
- S.ImpCastExprToType(base, redef, CK_BitCast);
+ base = S.ImpCastExprToType(base.take(), redef, CK_BitCast);
return true;
}
@@ -3666,17 +4028,22 @@ static bool ShouldTryAgainWithRedefinitionType(Sema &S, Expr *&base) {
/// The ObjCImpDecl bit is a gross hack that will need to be properly
/// fixed for ObjC++.
ExprResult
-Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
+Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
bool &IsArrow, SourceLocation OpLoc,
CXXScopeSpec &SS,
Decl *ObjCImpDecl, bool HasTemplateArgs) {
- assert(BaseExpr && "no base expression");
+ assert(BaseExpr.get() && "no base expression");
// Perform default conversions.
- DefaultFunctionArrayConversion(BaseExpr);
- if (IsArrow) DefaultLvalueConversion(BaseExpr);
+ BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take());
- QualType BaseType = BaseExpr->getType();
+ if (IsArrow) {
+ BaseExpr = DefaultLvalueConversion(BaseExpr.take());
+ if (BaseExpr.isInvalid())
+ return ExprError();
+ }
+
+ QualType BaseType = BaseExpr.get()->getType();
assert(!BaseType->isDependentType());
DeclarationName MemberName = R.getLookupName();
@@ -3700,19 +4067,21 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// overloaded operator->, but that should have been dealt with
// by now.
Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
- << BaseType << int(IsArrow) << BaseExpr->getSourceRange()
+ << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
<< FixItHint::CreateReplacement(OpLoc, ".");
IsArrow = false;
+ } else if (BaseType == Context.BoundMemberTy) {
+ goto fail;
} else {
Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
- << BaseType << BaseExpr->getSourceRange();
+ << BaseType << BaseExpr.get()->getSourceRange();
return ExprError();
}
}
// Handle field access to simple records.
if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
- if (LookupMemberExprInRecord(*this, R, BaseExpr->getSourceRange(),
+ if (LookupMemberExprInRecord(*this, R, BaseExpr.get()->getSourceRange(),
RTy, OpLoc, SS, HasTemplateArgs))
return ExprError();
@@ -3735,7 +4104,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// But we only actually find it this way on objects of type 'id',
// apparently.
if (OTy->isObjCId() && Member->isStr("isa"))
- return Owned(new (Context) ObjCIsaExpr(BaseExpr, IsArrow, MemberLoc,
+ return Owned(new (Context) ObjCIsaExpr(BaseExpr.take(), IsArrow, MemberLoc,
Context.getObjCClassType()));
if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
@@ -3768,7 +4137,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
<< IDecl->getDeclName() << MemberName
- << BaseExpr->getSourceRange();
+ << BaseExpr.get()->getSourceRange();
return ExprError();
}
}
@@ -3814,7 +4183,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
}
return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(),
- MemberLoc, BaseExpr,
+ MemberLoc, BaseExpr.take(),
IsArrow));
}
@@ -3822,8 +4191,11 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
const ObjCObjectPointerType *OPT;
if (!IsArrow && (OPT = BaseType->getAs<ObjCObjectPointerType>())) {
// This actually uses the base as an r-value.
- DefaultLvalueConversion(BaseExpr);
- assert(Context.hasSameUnqualifiedType(BaseType, BaseExpr->getType()));
+ BaseExpr = DefaultLvalueConversion(BaseExpr.take());
+ if (BaseExpr.isInvalid())
+ return ExprError();
+
+ assert(Context.hasSameUnqualifiedType(BaseType, BaseExpr.get()->getType()));
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
@@ -3843,7 +4215,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
VK_LValue,
OK_ObjCProperty,
MemberLoc,
- BaseExpr));
+ BaseExpr.take()));
}
if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {
@@ -3867,11 +4239,12 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD, PType,
VK, OK,
- MemberLoc, BaseExpr));
+ MemberLoc, BaseExpr.take()));
}
}
-
- if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
+ // Use of id.member can only be for a property reference. Do not
+ // use the 'id' redefinition in this case.
+ if (IsArrow && ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
@@ -3937,7 +4310,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// FIXME: we must check that the setter has property type.
return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
PType, VK, OK,
- MemberLoc, BaseExpr));
+ MemberLoc, BaseExpr.take()));
}
if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
@@ -3949,7 +4322,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
}
// Normal property access.
- return HandleExprPropertyRefExpr(OPT, BaseExpr, MemberName, MemberLoc,
+ return HandleExprPropertyRefExpr(OPT, BaseExpr.get(), MemberName, MemberLoc,
SourceLocation(), QualType(), false);
}
@@ -3957,13 +4330,13 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
if (BaseType->isExtVectorType()) {
// FIXME: this expr should store IsArrow.
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
- ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr->getValueKind());
+ ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind());
QualType ret = CheckExtVectorComponent(*this, BaseType, VK, OpLoc,
Member, MemberLoc);
if (ret.isNull())
return ExprError();
- return Owned(new (Context) ExtVectorElementExpr(ret, VK, BaseExpr,
+ return Owned(new (Context) ExtVectorElementExpr(ret, VK, BaseExpr.take(),
*Member, MemberLoc));
}
@@ -3972,7 +4345,8 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
if (IsArrow &&
BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) &&
!Context.ObjCSelRedefinitionType->isObjCSelType()) {
- ImpCastExprToType(BaseExpr, Context.ObjCSelRedefinitionType, CK_BitCast);
+ BaseExpr = ImpCastExprToType(BaseExpr.take(), Context.ObjCSelRedefinitionType,
+ CK_BitCast);
return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
}
@@ -3991,7 +4365,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&
MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
- << BaseType << int(IsArrow) << BaseExpr->getSourceRange()
+ << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
<< FixItHint::CreateReplacement(OpLoc, "->");
// Recurse as an -> access.
@@ -4006,11 +4380,11 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
bool TryCall = false;
bool Overloaded = false;
UnresolvedSet<8> AllOverloads;
- if (const OverloadExpr *Overloads = dyn_cast<OverloadExpr>(BaseExpr)) {
+ if (const OverloadExpr *Overloads = dyn_cast<OverloadExpr>(BaseExpr.get())) {
AllOverloads.append(Overloads->decls_begin(), Overloads->decls_end());
TryCall = true;
Overloaded = true;
- } else if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(BaseExpr)) {
+ } else if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(BaseExpr.get())) {
if (FunctionDecl* Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) {
AllOverloads.addDecl(Fun);
TryCall = true;
@@ -4024,22 +4398,25 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
bool HasViableZeroArgOverload = false;
for (OverloadExpr::decls_iterator it = AllOverloads.begin(),
DeclsEnd = AllOverloads.end(); it != DeclsEnd; ++it) {
- const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*it);
- QualType ResultTy = OverloadDecl->getResultType();
- if ((!IsArrow && ResultTy->isRecordType()) ||
- (IsArrow && ResultTy->isPointerType() &&
- ResultTy->getPointeeType()->isRecordType())) {
- ViableOverloads.addDecl(*it);
- if (OverloadDecl->getMinRequiredArguments() == 0) {
- HasViableZeroArgOverload = true;
+ // Our overload set may include TemplateDecls, which we'll ignore for the
+ // purposes of determining whether we can issue a '()' fixit.
+ if (const FunctionDecl *OverloadDecl = dyn_cast<FunctionDecl>(*it)) {
+ QualType ResultTy = OverloadDecl->getResultType();
+ if ((!IsArrow && ResultTy->isRecordType()) ||
+ (IsArrow && ResultTy->isPointerType() &&
+ ResultTy->getPointeeType()->isRecordType())) {
+ ViableOverloads.addDecl(*it);
+ if (OverloadDecl->getMinRequiredArguments() == 0) {
+ HasViableZeroArgOverload = true;
+ }
}
}
}
if (!HasViableZeroArgOverload || ViableOverloads.size() != 1) {
- Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
- << 1 << 0
- << BaseExpr->getSourceRange();
+ Diag(BaseExpr.get()->getExprLoc(), diag::err_member_reference_needs_call)
+ << (AllOverloads.size() > 1) << 0
+ << BaseExpr.get()->getSourceRange();
int ViableOverloadCount = ViableOverloads.size();
int I;
for (I = 0; I < ViableOverloadCount; ++I) {
@@ -4052,7 +4429,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
diag::note_member_ref_possible_intended_overload);
}
if (I != ViableOverloadCount) {
- Diag(BaseExpr->getExprLoc(), diag::note_ovl_too_many_candidates)
+ Diag(BaseExpr.get()->getExprLoc(), diag::note_ovl_too_many_candidates)
<< int(ViableOverloadCount - I);
}
return ExprError();
@@ -4068,6 +4445,16 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
}
} else if ((Fun = BaseType->getAs<FunctionType>())) {
TryCall = true;
+ } else if (BaseType == Context.BoundMemberTy) {
+ // Look for the bound-member type. If it's still overloaded,
+ // give up, although we probably should have fallen into the
+ // OverloadExpr case above if we actually have an overloaded
+ // bound member.
+ QualType fnType = Expr::findBoundMemberType(BaseExpr.get());
+ if (!fnType.isNull()) {
+ TryCall = true;
+ Fun = fnType->castAs<FunctionType>();
+ }
}
if (TryCall) {
@@ -4088,24 +4475,24 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// can emit a fixit and carry on pretending that BaseExpr was actually a
// CallExpr.
SourceLocation ParenInsertionLoc =
- PP.getLocForEndOfToken(BaseExpr->getLocEnd());
- Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
+ PP.getLocForEndOfToken(BaseExpr.get()->getLocEnd());
+ Diag(BaseExpr.get()->getExprLoc(), diag::err_member_reference_needs_call)
<< int(Overloaded) << 1
- << BaseExpr->getSourceRange()
+ << BaseExpr.get()->getSourceRange()
<< FixItHint::CreateInsertion(ParenInsertionLoc, "()");
- ExprResult NewBase = ActOnCallExpr(0, BaseExpr, ParenInsertionLoc,
+ ExprResult NewBase = ActOnCallExpr(0, BaseExpr.take(), ParenInsertionLoc,
MultiExprArg(*this, 0, 0),
ParenInsertionLoc);
if (NewBase.isInvalid())
return ExprError();
- BaseExpr = NewBase.takeAs<Expr>();
- DefaultFunctionArrayConversion(BaseExpr);
+ BaseExpr = NewBase;
+ BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take());
return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
}
Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)
- << BaseType << BaseExpr->getSourceRange();
+ << BaseType << BaseExpr.get()->getSourceRange();
return ExprError();
}
@@ -4167,8 +4554,12 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
NameInfo, TemplateArgs);
} else {
LookupResult R(*this, NameInfo, LookupMemberName);
- Result = LookupMemberExpr(R, Base, IsArrow, OpLoc,
+ ExprResult BaseResult = Owned(Base);
+ Result = LookupMemberExpr(R, BaseResult, IsArrow, OpLoc,
SS, ObjCImpDecl, TemplateArgs != 0);
+ if (BaseResult.isInvalid())
+ return ExprError();
+ Base = BaseResult.take();
if (Result.isInvalid()) {
Owned(Base);
@@ -4313,6 +4704,13 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
<< NumArgsInProto << NumArgs << Fn->getSourceRange()
<< SourceRange(Args[NumArgsInProto]->getLocStart(),
Args[NumArgs-1]->getLocEnd());
+
+ // Emit the location of the prototype.
+ if (FDecl && !FDecl->getBuiltinID())
+ Diag(FDecl->getLocStart(),
+ diag::note_typecheck_call_too_many_args)
+ << FDecl;
+
// This deletes the extra arguments.
Call->setNumArgs(Context, NumArgsInProto);
return true;
@@ -4394,16 +4792,37 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
// If this is a variadic call, handle args passed through "...".
if (CallType != VariadicDoesNotApply) {
- // Promote the arguments (C99 6.5.2.2p7).
- for (unsigned i = ArgIx; i != NumArgs; ++i) {
- Expr *Arg = Args[i];
- Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType, FDecl);
- AllArgs.push_back(Arg);
+
+ // Assume that extern "C" functions with variadic arguments that
+ // return __unknown_anytype aren't *really* variadic.
+ if (Proto->getResultType() == Context.UnknownAnyTy &&
+ FDecl && FDecl->isExternC()) {
+ for (unsigned i = ArgIx; i != NumArgs; ++i) {
+ ExprResult arg;
+ if (isa<ExplicitCastExpr>(Args[i]->IgnoreParens()))
+ arg = DefaultFunctionArrayLvalueConversion(Args[i]);
+ else
+ arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl);
+ Invalid |= arg.isInvalid();
+ AllArgs.push_back(arg.take());
+ }
+
+ // Otherwise do argument promotion, (C99 6.5.2.2p7).
+ } else {
+ for (unsigned i = ArgIx; i != NumArgs; ++i) {
+ ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl);
+ Invalid |= Arg.isInvalid();
+ AllArgs.push_back(Arg.take());
+ }
}
}
return Invalid;
}
+/// Given a function expression of unknown-any type, try to rebuild it
+/// to have a function type.
+static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn);
+
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations.
@@ -4464,94 +4883,39 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs,
RParenLoc));
- Expr *NakedFn = Fn->IgnoreParens();
-
- // Determine whether this is a call to an unresolved member function.
- if (UnresolvedMemberExpr *MemE = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
- // If lookup was unresolved but not dependent (i.e. didn't find
- // an unresolved using declaration), it has to be an overloaded
- // function set, which means it must contain either multiple
- // declarations (all methods or method templates) or a single
- // method template.
- assert((MemE->getNumDecls() > 1) ||
- isa<FunctionTemplateDecl>(
- (*MemE->decls_begin())->getUnderlyingDecl()));
- (void)MemE;
+ if (Fn->getType() == Context.UnknownAnyTy) {
+ ExprResult result = rebuildUnknownAnyFunction(*this, Fn);
+ if (result.isInvalid()) return ExprError();
+ Fn = result.take();
+ }
+ if (Fn->getType() == Context.BoundMemberTy) {
return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
RParenLoc);
}
+ }
- // Determine whether this is a call to a member function.
- if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(NakedFn)) {
- NamedDecl *MemDecl = MemExpr->getMemberDecl();
- if (isa<CXXMethodDecl>(MemDecl))
+ // Check for overloaded calls. This can happen even in C due to extensions.
+ if (Fn->getType() == Context.OverloadTy) {
+ OverloadExpr::FindResult find = OverloadExpr::find(Fn);
+
+ // We aren't supposed to apply this logic if there's an '&' involved.
+ if (!find.IsAddressOfOperand) {
+ OverloadExpr *ovl = find.Expression;
+ if (isa<UnresolvedLookupExpr>(ovl)) {
+ UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl);
+ return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs,
+ RParenLoc, ExecConfig);
+ } else {
return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
RParenLoc);
- }
-
- // Determine whether this is a call to a pointer-to-member function.
- if (BinaryOperator *BO = dyn_cast<BinaryOperator>(NakedFn)) {
- if (BO->getOpcode() == BO_PtrMemD ||
- BO->getOpcode() == BO_PtrMemI) {
- if (const FunctionProtoType *FPT
- = BO->getType()->getAs<FunctionProtoType>()) {
- QualType ResultTy = FPT->getCallResultType(Context);
- ExprValueKind VK = Expr::getValueKindForType(FPT->getResultType());
-
- // Check that the object type isn't more qualified than the
- // member function we're calling.
- Qualifiers FuncQuals = Qualifiers::fromCVRMask(FPT->getTypeQuals());
- Qualifiers ObjectQuals
- = BO->getOpcode() == BO_PtrMemD
- ? BO->getLHS()->getType().getQualifiers()
- : BO->getLHS()->getType()->getAs<PointerType>()
- ->getPointeeType().getQualifiers();
-
- Qualifiers Difference = ObjectQuals - FuncQuals;
- Difference.removeObjCGCAttr();
- Difference.removeAddressSpace();
- if (Difference) {
- std::string QualsString = Difference.getAsString();
- Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals)
- << BO->getType().getUnqualifiedType()
- << QualsString
- << (QualsString.find(' ') == std::string::npos? 1 : 2);
- }
-
- CXXMemberCallExpr *TheCall
- = new (Context) CXXMemberCallExpr(Context, Fn, Args,
- NumArgs, ResultTy, VK,
- RParenLoc);
-
- if (CheckCallReturnType(FPT->getResultType(),
- BO->getRHS()->getSourceRange().getBegin(),
- TheCall, 0))
- return ExprError();
-
- if (ConvertArgumentsForCall(TheCall, BO, 0, FPT, Args, NumArgs,
- RParenLoc))
- return ExprError();
-
- return MaybeBindToTemporary(TheCall);
- }
- return ExprError(Diag(Fn->getLocStart(),
- diag::err_typecheck_call_not_function)
- << Fn->getType() << Fn->getSourceRange());
}
}
}
// If we're directly calling a function, get the appropriate declaration.
- // Also, in C++, keep track of whether we should perform argument-dependent
- // lookup and whether there were any explicitly-specified template arguments.
Expr *NakedFn = Fn->IgnoreParens();
- if (isa<UnresolvedLookupExpr>(NakedFn)) {
- UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(NakedFn);
- return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs,
- RParenLoc, ExecConfig);
- }
NamedDecl *NDecl = 0;
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn))
@@ -4560,6 +4924,8 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
if (isa<DeclRefExpr>(NakedFn))
NDecl = cast<DeclRefExpr>(NakedFn)->getDecl();
+ else if (isa<MemberExpr>(NakedFn))
+ NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc,
ExecConfig);
@@ -4595,7 +4961,10 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl);
// Promote the function operand.
- UsualUnaryConversions(Fn);
+ ExprResult Result = UsualUnaryConversions(Fn);
+ if (Result.isInvalid())
+ return ExprError();
+ Fn = Result.take();
// Make the call expr early, before semantic checks. This guarantees cleanup
// of arguments and function on error.
@@ -4621,6 +4990,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
return CheckBuiltinFunctionCall(BuiltinID, TheCall);
+ retry:
const FunctionType *FuncT;
if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) {
// C99 6.5.2.2p1 - "The expression that denotes the called function shall
@@ -4633,6 +5003,15 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
Fn->getType()->getAs<BlockPointerType>()) {
FuncT = BPT->getPointeeType()->castAs<FunctionType>();
} else {
+ // Handle calls to expressions of unknown-any type.
+ if (Fn->getType() == Context.UnknownAnyTy) {
+ ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn);
+ if (rewrite.isInvalid()) return ExprError();
+ Fn = rewrite.take();
+ TheCall->setCallee(Fn);
+ goto retry;
+ }
+
return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
<< Fn->getType() << Fn->getSourceRange());
}
@@ -4703,7 +5082,12 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
Arg = ArgE.takeAs<Expr>();
} else {
- DefaultArgumentPromotion(Arg);
+ ExprResult ArgE = DefaultArgumentPromotion(Arg);
+
+ if (ArgE.isInvalid())
+ return true;
+
+ Arg = ArgE.takeAs<Expr>();
}
if (RequireCompleteType(Arg->getSourceRange().getBegin(),
@@ -4819,12 +5203,12 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist,
/// Prepares for a scalar cast, performing all the necessary stages
/// except the final cast and returning the kind required.
-static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) {
+static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) {
// Both Src and Dest are scalar types, i.e. arithmetic or pointer.
// Also, callers should have filtered out the invalid cases with
// pointers. Everything else should be possible.
- QualType SrcTy = Src->getType();
+ QualType SrcTy = Src.get()->getType();
if (S.Context.hasSameUnqualifiedType(SrcTy, DestTy))
return CK_NoOp;
@@ -4854,7 +5238,7 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) {
case Type::STK_Integral:
switch (DestTy->getScalarTypeKind()) {
case Type::STK_Pointer:
- if (Src->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull))
+ if (Src.get()->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull))
return CK_NullToPointer;
return CK_IntegralToPointer;
case Type::STK_Bool:
@@ -4864,12 +5248,12 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) {
case Type::STK_Floating:
return CK_IntegralToFloating;
case Type::STK_IntegralComplex:
- S.ImpCastExprToType(Src, DestTy->getAs<ComplexType>()->getElementType(),
- CK_IntegralCast);
+ Src = S.ImpCastExprToType(Src.take(), DestTy->getAs<ComplexType>()->getElementType(),
+ CK_IntegralCast);
return CK_IntegralRealToComplex;
case Type::STK_FloatingComplex:
- S.ImpCastExprToType(Src, DestTy->getAs<ComplexType>()->getElementType(),
- CK_IntegralToFloating);
+ Src = S.ImpCastExprToType(Src.take(), DestTy->getAs<ComplexType>()->getElementType(),
+ CK_IntegralToFloating);
return CK_FloatingRealToComplex;
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
@@ -4885,12 +5269,12 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) {
case Type::STK_Integral:
return CK_FloatingToIntegral;
case Type::STK_FloatingComplex:
- S.ImpCastExprToType(Src, DestTy->getAs<ComplexType>()->getElementType(),
- CK_FloatingCast);
+ Src = S.ImpCastExprToType(Src.take(), DestTy->getAs<ComplexType>()->getElementType(),
+ CK_FloatingCast);
return CK_FloatingRealToComplex;
case Type::STK_IntegralComplex:
- S.ImpCastExprToType(Src, DestTy->getAs<ComplexType>()->getElementType(),
- CK_FloatingToIntegral);
+ Src = S.ImpCastExprToType(Src.take(), DestTy->getAs<ComplexType>()->getElementType(),
+ CK_FloatingToIntegral);
return CK_IntegralRealToComplex;
case Type::STK_Pointer:
llvm_unreachable("valid float->pointer cast?");
@@ -4909,14 +5293,14 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) {
QualType ET = SrcTy->getAs<ComplexType>()->getElementType();
if (S.Context.hasSameType(ET, DestTy))
return CK_FloatingComplexToReal;
- S.ImpCastExprToType(Src, ET, CK_FloatingComplexToReal);
+ Src = S.ImpCastExprToType(Src.take(), ET, CK_FloatingComplexToReal);
return CK_FloatingCast;
}
case Type::STK_Bool:
return CK_FloatingComplexToBoolean;
case Type::STK_Integral:
- S.ImpCastExprToType(Src, SrcTy->getAs<ComplexType>()->getElementType(),
- CK_FloatingComplexToReal);
+ Src = S.ImpCastExprToType(Src.take(), SrcTy->getAs<ComplexType>()->getElementType(),
+ CK_FloatingComplexToReal);
return CK_FloatingToIntegral;
case Type::STK_Pointer:
llvm_unreachable("valid complex float->pointer cast?");
@@ -4935,14 +5319,14 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) {
QualType ET = SrcTy->getAs<ComplexType>()->getElementType();
if (S.Context.hasSameType(ET, DestTy))
return CK_IntegralComplexToReal;
- S.ImpCastExprToType(Src, ET, CK_IntegralComplexToReal);
+ Src = S.ImpCastExprToType(Src.take(), ET, CK_IntegralComplexToReal);
return CK_IntegralCast;
}
case Type::STK_Bool:
return CK_IntegralComplexToBoolean;
case Type::STK_Floating:
- S.ImpCastExprToType(Src, SrcTy->getAs<ComplexType>()->getElementType(),
- CK_IntegralComplexToReal);
+ Src = S.ImpCastExprToType(Src.take(), SrcTy->getAs<ComplexType>()->getElementType(),
+ CK_IntegralComplexToReal);
return CK_IntegralToFloating;
case Type::STK_Pointer:
llvm_unreachable("valid complex int->pointer cast?");
@@ -4957,15 +5341,20 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) {
}
/// CheckCastTypes - Check type constraints for casting between types.
-bool Sema::CheckCastTypes(SourceRange TyR, QualType castType,
- Expr *&castExpr, CastKind& Kind, ExprValueKind &VK,
- CXXCastPath &BasePath, bool FunctionalStyle) {
+ExprResult Sema::CheckCastTypes(SourceRange TyR, QualType castType,
+ Expr *castExpr, CastKind& Kind, ExprValueKind &VK,
+ CXXCastPath &BasePath, bool FunctionalStyle) {
+ if (castExpr->getType() == Context.UnknownAnyTy)
+ return checkUnknownAnyCast(TyR, castType, castExpr, Kind, VK, BasePath);
+
if (getLangOptions().CPlusPlus)
return CXXCheckCStyleCast(SourceRange(TyR.getBegin(),
castExpr->getLocEnd()),
castType, VK, castExpr, Kind, BasePath,
FunctionalStyle);
+ assert(!castExpr->getType()->isPlaceholderType());
+
// We only support r-value casts in C.
VK = VK_RValue;
@@ -4973,18 +5362,24 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType,
// type needs to be scalar.
if (castType->isVoidType()) {
// We don't necessarily do lvalue-to-rvalue conversions on this.
- IgnoredValueConversions(castExpr);
+ ExprResult castExprRes = IgnoredValueConversions(castExpr);
+ if (castExprRes.isInvalid())
+ return ExprError();
+ castExpr = castExprRes.take();
// Cast to void allows any expr type.
Kind = CK_ToVoid;
- return false;
+ return Owned(castExpr);
}
- DefaultFunctionArrayLvalueConversion(castExpr);
+ ExprResult castExprRes = DefaultFunctionArrayLvalueConversion(castExpr);
+ if (castExprRes.isInvalid())
+ return ExprError();
+ castExpr = castExprRes.take();
if (RequireCompleteType(TyR.getBegin(), castType,
diag::err_typecheck_cast_to_incomplete))
- return true;
+ return ExprError();
if (!castType->isScalarType() && !castType->isVectorType()) {
if (Context.hasSameUnqualifiedType(castType, castExpr->getType()) &&
@@ -4994,7 +5389,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType,
Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar)
<< castType << castExpr->getSourceRange();
Kind = CK_NoOp;
- return false;
+ return Owned(castExpr);
}
if (castType->isUnionType()) {
@@ -5011,16 +5406,19 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType,
break;
}
}
- if (Field == FieldEnd)
- return Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type)
+ if (Field == FieldEnd) {
+ Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type)
<< castExpr->getType() << castExpr->getSourceRange();
+ return ExprError();
+ }
Kind = CK_ToUnion;
- return false;
+ return Owned(castExpr);
}
// Reject any other conversions to non-scalar types.
- return Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar)
+ Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar)
<< castType << castExpr->getSourceRange();
+ return ExprError();
}
// The type we're casting to is known to be a scalar or vector.
@@ -5028,49 +5426,73 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType,
// Require the operand to be a scalar or vector.
if (!castExpr->getType()->isScalarType() &&
!castExpr->getType()->isVectorType()) {
- return Diag(castExpr->getLocStart(),
+ Diag(castExpr->getLocStart(),
diag::err_typecheck_expect_scalar_operand)
<< castExpr->getType() << castExpr->getSourceRange();
+ return ExprError();
}
if (castType->isExtVectorType())
return CheckExtVectorCast(TyR, castType, castExpr, Kind);
- if (castType->isVectorType())
- return CheckVectorCast(TyR, castType, castExpr->getType(), Kind);
- if (castExpr->getType()->isVectorType())
- return CheckVectorCast(TyR, castExpr->getType(), castType, Kind);
+ if (castType->isVectorType()) {
+ if (castType->getAs<VectorType>()->getVectorKind() ==
+ VectorType::AltiVecVector &&
+ (castExpr->getType()->isIntegerType() ||
+ castExpr->getType()->isFloatingType())) {
+ Kind = CK_VectorSplat;
+ return Owned(castExpr);
+ } else if (CheckVectorCast(TyR, castType, castExpr->getType(), Kind)) {
+ return ExprError();
+ } else
+ return Owned(castExpr);
+ }
+ if (castExpr->getType()->isVectorType()) {
+ if (CheckVectorCast(TyR, castExpr->getType(), castType, Kind))
+ return ExprError();
+ else
+ return Owned(castExpr);
+ }
// The source and target types are both scalars, i.e.
// - arithmetic types (fundamental, enum, and complex)
// - all kinds of pointers
// Note that member pointers were filtered out with C++, above.
- if (isa<ObjCSelectorExpr>(castExpr))
- return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr);
+ if (isa<ObjCSelectorExpr>(castExpr)) {
+ Diag(castExpr->getLocStart(), diag::err_cast_selector_expr);
+ return ExprError();
+ }
// If either type is a pointer, the other type has to be either an
// integer or a pointer.
if (!castType->isArithmeticType()) {
QualType castExprType = castExpr->getType();
if (!castExprType->isIntegralType(Context) &&
- castExprType->isArithmeticType())
- return Diag(castExpr->getLocStart(),
- diag::err_cast_pointer_from_non_pointer_int)
+ castExprType->isArithmeticType()) {
+ Diag(castExpr->getLocStart(),
+ diag::err_cast_pointer_from_non_pointer_int)
<< castExprType << castExpr->getSourceRange();
+ return ExprError();
+ }
} else if (!castExpr->getType()->isArithmeticType()) {
- if (!castType->isIntegralType(Context) && castType->isArithmeticType())
- return Diag(castExpr->getLocStart(),
- diag::err_cast_pointer_to_non_pointer_int)
+ if (!castType->isIntegralType(Context) && castType->isArithmeticType()) {
+ Diag(castExpr->getLocStart(), diag::err_cast_pointer_to_non_pointer_int)
<< castType << castExpr->getSourceRange();
+ return ExprError();
+ }
}
- Kind = PrepareScalarCast(*this, castExpr, castType);
+ castExprRes = Owned(castExpr);
+ Kind = PrepareScalarCast(*this, castExprRes, castType);
+ if (castExprRes.isInvalid())
+ return ExprError();
+ castExpr = castExprRes.take();
if (Kind == CK_BitCast)
CheckCastAlign(castExpr, castType, TyR);
- return false;
+ return Owned(castExpr);
}
bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
@@ -5093,8 +5515,8 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
return false;
}
-bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr,
- CastKind &Kind) {
+ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
+ Expr *CastExpr, CastKind &Kind) {
assert(DestTy->isExtVectorType() && "Not an extended vector type!");
QualType SrcTy = CastExpr->getType();
@@ -5102,11 +5524,13 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr,
// If SrcTy is a VectorType, the total size must match to explicitly cast to
// an ExtVectorType.
if (SrcTy->isVectorType()) {
- if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy))
- return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
+ if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy)) {
+ Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
<< DestTy << SrcTy << R;
+ return ExprError();
+ }
Kind = CK_BitCast;
- return false;
+ return Owned(CastExpr);
}
// All non-pointer scalars can be cast to ExtVector type. The appropriate
@@ -5118,11 +5542,14 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr,
<< DestTy << SrcTy << R;
QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType();
- ImpCastExprToType(CastExpr, DestElemTy,
- PrepareScalarCast(*this, CastExpr, DestElemTy));
+ ExprResult CastExprRes = Owned(CastExpr);
+ CastKind CK = PrepareScalarCast(*this, CastExprRes, DestElemTy);
+ if (CastExprRes.isInvalid())
+ return ExprError();
+ CastExpr = ImpCastExprToType(CastExprRes.take(), DestElemTy, CK).take();
Kind = CK_VectorSplat;
- return false;
+ return Owned(CastExpr);
}
ExprResult
@@ -5150,12 +5577,15 @@ Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
CastKind Kind = CK_Invalid;
ExprValueKind VK = VK_RValue;
CXXCastPath BasePath;
- if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr,
- Kind, VK, BasePath))
+ ExprResult CastResult =
+ CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr,
+ Kind, VK, BasePath);
+ if (CastResult.isInvalid())
return ExprError();
+ castExpr = CastResult.take();
return Owned(CStyleCastExpr::Create(Context,
- Ty->getType().getNonLValueExprType(Context),
+ Ty->getType().getNonLValueExprType(Context),
VK, Kind, castExpr, &BasePath, Ty,
LParenLoc, RParenLoc));
}
@@ -5185,9 +5615,9 @@ Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
TypeSourceInfo *TInfo) {
ParenListExpr *PE = cast<ParenListExpr>(Op);
QualType Ty = TInfo->getType();
- bool isAltiVecLiteral = false;
+ bool isVectorLiteral = false;
- // Check for an altivec literal,
+ // Check for an altivec or OpenCL literal,
// i.e. all the elements are integer constants.
if (getLangOptions().AltiVec && Ty->isVectorType()) {
if (PE->getNumExprs() == 0) {
@@ -5196,18 +5626,45 @@ Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
}
if (PE->getNumExprs() == 1) {
if (!PE->getExpr(0)->getType()->isVectorType())
- isAltiVecLiteral = true;
+ isVectorLiteral = true;
}
else
- isAltiVecLiteral = true;
+ isVectorLiteral = true;
}
- // If this is an altivec initializer, '(' type ')' '(' init, ..., init ')'
+ // If this is a vector initializer, '(' type ')' '(' init, ..., init ')'
// then handle it as such.
- if (isAltiVecLiteral) {
+ if (isVectorLiteral) {
llvm::SmallVector<Expr *, 8> initExprs;
- for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i)
- initExprs.push_back(PE->getExpr(i));
+ // '(...)' form of vector initialization in AltiVec: the number of
+ // initializers must be one or must match the size of the vector.
+ // If a single value is specified in the initializer then it will be
+ // replicated to all the components of the vector
+ if (Ty->getAs<VectorType>()->getVectorKind() ==
+ VectorType::AltiVecVector) {
+ unsigned numElems = Ty->getAs<VectorType>()->getNumElements();
+ // The number of initializers must be one or must match the size of the
+ // vector. If a single value is specified in the initializer then it will
+ // be replicated to all the components of the vector
+ if (PE->getNumExprs() == 1) {
+ QualType ElemTy = Ty->getAs<VectorType>()->getElementType();
+ ExprResult Literal = Owned(PE->getExpr(0));
+ Literal = ImpCastExprToType(Literal.take(), ElemTy,
+ PrepareScalarCast(*this, Literal, ElemTy));
+ return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take());
+ }
+ else if (PE->getNumExprs() < numElems) {
+ Diag(PE->getExprLoc(),
+ diag::err_incorrect_number_of_vector_initializers);
+ return ExprError();
+ }
+ else
+ for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i)
+ initExprs.push_back(PE->getExpr(i));
+ }
+ else
+ for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i)
+ initExprs.push_back(PE->getExpr(i));
// FIXME: This means that pretty-printing the final AST will produce curly
// braces instead of the original commas.
@@ -5265,11 +5722,8 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHS, Expr *RHS,
// In this case, check to make sure that we got here from a "NULL"
// string in the source code.
NullExpr = NullExpr->IgnoreParenImpCasts();
- SourceManager& SM = Context.getSourceManager();
- SourceLocation Loc = SM.getInstantiationLoc(NullExpr->getExprLoc());
- unsigned Len =
- Lexer::MeasureTokenLength(Loc, SM, Context.getLangOptions());
- if (Len != 4 || memcmp(SM.getCharacterData(Loc), "NULL", 4))
+ SourceLocation loc = NullExpr->getExprLoc();
+ if (!findMacroSpelling(loc, "NULL"))
return false;
}
@@ -5283,23 +5737,17 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHS, Expr *RHS,
/// Note that lhs is not null here, even if this is the gnu "x ?: y" extension.
/// In that case, lhs = cond.
/// C99 6.5.15
-QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
+QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS,
ExprValueKind &VK, ExprObjectKind &OK,
SourceLocation QuestionLoc) {
- // If both LHS and RHS are overloaded functions, try to resolve them.
- if (Context.hasSameType(LHS->getType(), RHS->getType()) &&
- LHS->getType()->isSpecificBuiltinType(BuiltinType::Overload)) {
- ExprResult LHSResult = CheckPlaceholderExpr(LHS, QuestionLoc);
- if (LHSResult.isInvalid())
- return QualType();
- ExprResult RHSResult = CheckPlaceholderExpr(RHS, QuestionLoc);
- if (RHSResult.isInvalid())
- return QualType();
+ ExprResult lhsResult = CheckPlaceholderExpr(LHS.get());
+ if (!lhsResult.isUsable()) return QualType();
+ LHS = move(lhsResult);
- LHS = LHSResult.take();
- RHS = RHSResult.take();
- }
+ ExprResult rhsResult = CheckPlaceholderExpr(RHS.get());
+ if (!rhsResult.isUsable()) return QualType();
+ RHS = move(rhsResult);
// C++ is sufficiently different to merit its own checker.
if (getLangOptions().CPlusPlus)
@@ -5308,12 +5756,19 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
VK = VK_RValue;
OK = OK_Ordinary;
- UsualUnaryConversions(Cond);
- UsualUnaryConversions(LHS);
- UsualUnaryConversions(RHS);
- QualType CondTy = Cond->getType();
- QualType LHSTy = LHS->getType();
- QualType RHSTy = RHS->getType();
+ Cond = UsualUnaryConversions(Cond.take());
+ if (Cond.isInvalid())
+ return QualType();
+ LHS = UsualUnaryConversions(LHS.take());
+ if (LHS.isInvalid())
+ return QualType();
+ RHS = UsualUnaryConversions(RHS.take());
+ if (RHS.isInvalid())
+ return QualType();
+
+ QualType CondTy = Cond.get()->getType();
+ QualType LHSTy = LHS.get()->getType();
+ QualType RHSTy = RHS.get()->getType();
// first, check the condition.
if (!CondTy->isScalarType()) { // C99 6.5.15p2
@@ -5321,14 +5776,14 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// Throw an error if its not either.
if (getLangOptions().OpenCL) {
if (!CondTy->isVectorType()) {
- Diag(Cond->getLocStart(),
+ Diag(Cond.get()->getLocStart(),
diag::err_typecheck_cond_expect_scalar_or_vector)
<< CondTy;
return QualType();
}
}
else {
- Diag(Cond->getLocStart(), diag::err_typecheck_cond_expect_scalar)
+ Diag(Cond.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar)
<< CondTy;
return QualType();
}
@@ -5344,25 +5799,27 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (getLangOptions().OpenCL && CondTy->isVectorType()) {
// Both operands should be of scalar type.
if (!LHSTy->isScalarType()) {
- Diag(LHS->getLocStart(), diag::err_typecheck_cond_expect_scalar)
+ Diag(LHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar)
<< CondTy;
return QualType();
}
if (!RHSTy->isScalarType()) {
- Diag(RHS->getLocStart(), diag::err_typecheck_cond_expect_scalar)
+ Diag(RHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar)
<< CondTy;
return QualType();
}
// Implicity convert these scalars to the type of the condition.
- ImpCastExprToType(LHS, CondTy, CK_IntegralCast);
- ImpCastExprToType(RHS, CondTy, CK_IntegralCast);
+ LHS = ImpCastExprToType(LHS.take(), CondTy, CK_IntegralCast);
+ RHS = ImpCastExprToType(RHS.take(), CondTy, CK_IntegralCast);
}
// If both operands have arithmetic type, do the usual arithmetic conversions
// to find a common type: C99 6.5.15p3,5.
if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
UsualArithmeticConversions(LHS, RHS);
- return LHS->getType();
+ if (LHS.isInvalid() || RHS.isInvalid())
+ return QualType();
+ return LHS.get()->getType();
}
// If both operands are the same structure or union type, the result is that
@@ -5380,32 +5837,34 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// The following || allows only one side to be void (a GCC-ism).
if (LHSTy->isVoidType() || RHSTy->isVoidType()) {
if (!LHSTy->isVoidType())
- Diag(RHS->getLocStart(), diag::ext_typecheck_cond_one_void)
- << RHS->getSourceRange();
+ Diag(RHS.get()->getLocStart(), diag::ext_typecheck_cond_one_void)
+ << RHS.get()->getSourceRange();
if (!RHSTy->isVoidType())
- Diag(LHS->getLocStart(), diag::ext_typecheck_cond_one_void)
- << LHS->getSourceRange();
- ImpCastExprToType(LHS, Context.VoidTy, CK_ToVoid);
- ImpCastExprToType(RHS, Context.VoidTy, CK_ToVoid);
+ Diag(LHS.get()->getLocStart(), diag::ext_typecheck_cond_one_void)
+ << LHS.get()->getSourceRange();
+ LHS = ImpCastExprToType(LHS.take(), Context.VoidTy, CK_ToVoid);
+ RHS = ImpCastExprToType(RHS.take(), Context.VoidTy, CK_ToVoid);
return Context.VoidTy;
}
// C99 6.5.15p6 - "if one operand is a null pointer constant, the result has
// the type of the other operand."
if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) &&
- RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+ RHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
// promote the null to a pointer.
- ImpCastExprToType(RHS, LHSTy, CK_NullToPointer);
+ RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_NullToPointer);
return LHSTy;
}
if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) &&
- LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(LHS, RHSTy, CK_NullToPointer);
+ LHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+ LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_NullToPointer);
return RHSTy;
}
// All objective-c pointer type analysis is done here.
QualType compositeType = FindCompositeObjCPointerType(LHS, RHS,
QuestionLoc);
+ if (LHS.isInvalid() || RHS.isInvalid())
+ return QualType();
if (!compositeType.isNull())
return compositeType;
@@ -5415,12 +5874,12 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) {
if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) {
QualType destType = Context.getPointerType(Context.VoidTy);
- ImpCastExprToType(LHS, destType, CK_BitCast);
- ImpCastExprToType(RHS, destType, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast);
return destType;
}
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
- << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+ << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
// We have 2 block pointer types.
@@ -5435,18 +5894,18 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
rhptee.getUnqualifiedType())) {
Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers)
- << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+ << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
// In this situation, we assume void* type. No especially good
// reason, but this is what gcc does, and we do have to pick
// to get a consistent AST.
QualType incompatTy = Context.getPointerType(Context.VoidTy);
- ImpCastExprToType(LHS, incompatTy, CK_BitCast);
- ImpCastExprToType(RHS, incompatTy, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast);
return incompatTy;
}
// The block pointer types are compatible.
- ImpCastExprToType(LHS, LHSTy, CK_BitCast);
- ImpCastExprToType(RHS, LHSTy, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.take(), LHSTy, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast);
return LHSTy;
}
@@ -5463,9 +5922,9 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
= Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
// Add qualifiers if necessary.
- ImpCastExprToType(LHS, destType, CK_NoOp);
+ LHS = ImpCastExprToType(LHS.take(), destType, CK_NoOp);
// Promote to void*.
- ImpCastExprToType(RHS, destType, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast);
return destType;
}
if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
@@ -5473,9 +5932,9 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
= Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
// Add qualifiers if necessary.
- ImpCastExprToType(RHS, destType, CK_NoOp);
+ RHS = ImpCastExprToType(RHS.take(), destType, CK_NoOp);
// Promote to void*.
- ImpCastExprToType(LHS, destType, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast);
return destType;
}
@@ -5486,13 +5945,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
rhptee.getUnqualifiedType())) {
Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers)
- << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+ << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
// In this situation, we assume void* type. No especially good
// reason, but this is what gcc does, and we do have to pick
// to get a consistent AST.
QualType incompatTy = Context.getPointerType(Context.VoidTy);
- ImpCastExprToType(LHS, incompatTy, CK_BitCast);
- ImpCastExprToType(RHS, incompatTy, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast);
return incompatTy;
}
// The pointer types are compatible.
@@ -5502,8 +5961,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// type.
// FIXME: Need to calculate the composite type.
// FIXME: Need to add qualifiers
- ImpCastExprToType(LHS, LHSTy, CK_BitCast);
- ImpCastExprToType(RHS, LHSTy, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.take(), LHSTy, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast);
return LHSTy;
}
@@ -5511,69 +5970,69 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// null pointers have been filtered out by this point.
if (RHSTy->isPointerType() && LHSTy->isIntegerType()) {
Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
- << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
- ImpCastExprToType(LHS, RHSTy, CK_IntegralToPointer);
+ << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_IntegralToPointer);
return RHSTy;
}
if (LHSTy->isPointerType() && RHSTy->isIntegerType()) {
Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
- << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
- ImpCastExprToType(RHS, LHSTy, CK_IntegralToPointer);
+ << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_IntegralToPointer);
return LHSTy;
}
// Emit a better diagnostic if one of the expressions is a null pointer
// constant and the other is not a pointer type. In this case, the user most
// likely forgot to take the address of the other expression.
- if (DiagnoseConditionalForNull(LHS, RHS, QuestionLoc))
+ if (DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc))
return QualType();
// Otherwise, the operands are not compatible.
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
- << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+ << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
/// FindCompositeObjCPointerType - Helper method to find composite type of
/// two objective-c pointer types of the two input expressions.
-QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
+QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
SourceLocation QuestionLoc) {
- QualType LHSTy = LHS->getType();
- QualType RHSTy = RHS->getType();
+ QualType LHSTy = LHS.get()->getType();
+ QualType RHSTy = RHS.get()->getType();
// Handle things like Class and struct objc_class*. Here we case the result
// to the pseudo-builtin, because that will be implicitly cast back to the
// redefinition type if an attempt is made to access its fields.
if (LHSTy->isObjCClassType() &&
(Context.hasSameType(RHSTy, Context.ObjCClassRedefinitionType))) {
- ImpCastExprToType(RHS, LHSTy, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast);
return LHSTy;
}
if (RHSTy->isObjCClassType() &&
(Context.hasSameType(LHSTy, Context.ObjCClassRedefinitionType))) {
- ImpCastExprToType(LHS, RHSTy, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast);
return RHSTy;
}
// And the same for struct objc_object* / id
if (LHSTy->isObjCIdType() &&
(Context.hasSameType(RHSTy, Context.ObjCIdRedefinitionType))) {
- ImpCastExprToType(RHS, LHSTy, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast);
return LHSTy;
}
if (RHSTy->isObjCIdType() &&
(Context.hasSameType(LHSTy, Context.ObjCIdRedefinitionType))) {
- ImpCastExprToType(LHS, RHSTy, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast);
return RHSTy;
}
// And the same for struct objc_selector* / SEL
if (Context.isObjCSelType(LHSTy) &&
(Context.hasSameType(RHSTy, Context.ObjCSelRedefinitionType))) {
- ImpCastExprToType(RHS, LHSTy, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast);
return LHSTy;
}
if (Context.isObjCSelType(RHSTy) &&
(Context.hasSameType(LHSTy, Context.ObjCSelRedefinitionType))) {
- ImpCastExprToType(LHS, RHSTy, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast);
return RHSTy;
}
// Check constraints for Objective-C object pointers types.
@@ -5620,15 +6079,15 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
else {
Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)
<< LHSTy << RHSTy
- << LHS->getSourceRange() << RHS->getSourceRange();
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
QualType incompatTy = Context.getObjCIdType();
- ImpCastExprToType(LHS, incompatTy, CK_BitCast);
- ImpCastExprToType(RHS, incompatTy, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast);
return incompatTy;
}
// The object pointer types are compatible.
- ImpCastExprToType(LHS, compositeType, CK_BitCast);
- ImpCastExprToType(RHS, compositeType, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.take(), compositeType, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.take(), compositeType, CK_BitCast);
return compositeType;
}
// Check Objective-C object pointer types and 'void *'
@@ -5639,9 +6098,9 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
= Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
// Add qualifiers if necessary.
- ImpCastExprToType(LHS, destType, CK_NoOp);
+ LHS = ImpCastExprToType(LHS.take(), destType, CK_NoOp);
// Promote to void*.
- ImpCastExprToType(RHS, destType, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast);
return destType;
}
if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {
@@ -5651,9 +6110,9 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
= Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
// Add qualifiers if necessary.
- ImpCastExprToType(RHS, destType, CK_NoOp);
+ RHS = ImpCastExprToType(RHS.take(), destType, CK_NoOp);
// Promote to void*.
- ImpCastExprToType(LHS, destType, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast);
return destType;
}
return QualType();
@@ -5681,7 +6140,10 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
&& commonExpr->isOrdinaryOrBitFieldObject()
&& RHSExpr->isOrdinaryOrBitFieldObject()
&& Context.hasSameType(commonExpr->getType(), RHSExpr->getType()))) {
- UsualUnaryConversions(commonExpr);
+ ExprResult commonRes = UsualUnaryConversions(commonExpr);
+ if (commonRes.isInvalid())
+ return ExprError();
+ commonExpr = commonRes.take();
}
opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(),
@@ -5693,19 +6155,21 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
- QualType result = CheckConditionalOperands(CondExpr, LHSExpr, RHSExpr,
+ ExprResult Cond = Owned(CondExpr), LHS = Owned(LHSExpr), RHS = Owned(RHSExpr);
+ QualType result = CheckConditionalOperands(Cond, LHS, RHS,
VK, OK, QuestionLoc);
- if (result.isNull())
+ if (result.isNull() || Cond.isInvalid() || LHS.isInvalid() ||
+ RHS.isInvalid())
return ExprError();
if (!commonExpr)
- return Owned(new (Context) ConditionalOperator(CondExpr, QuestionLoc,
- LHSExpr, ColonLoc,
- RHSExpr, result, VK, OK));
+ return Owned(new (Context) ConditionalOperator(Cond.take(), QuestionLoc,
+ LHS.take(), ColonLoc,
+ RHS.take(), result, VK, OK));
return Owned(new (Context)
- BinaryConditionalOperator(commonExpr, opaqueValue, CondExpr, LHSExpr,
- RHSExpr, QuestionLoc, ColonLoc, result, VK, OK));
+ BinaryConditionalOperator(commonExpr, opaqueValue, Cond.take(), LHS.take(),
+ RHS.take(), QuestionLoc, ColonLoc, result, VK, OK));
}
// checkPointerTypesForAssignment - This is a very tricky routine (despite
@@ -5736,6 +6200,12 @@ checkPointerTypesForAssignment(Sema &S, QualType lhsType, QualType rhsType) {
if (lhq.getAddressSpace() != rhq.getAddressSpace())
ConvTy = Sema::IncompatiblePointerDiscardsQualifiers;
+ // It's okay to add or remove GC qualifiers when converting to
+ // and from void*.
+ else if (lhq.withoutObjCGCAttr().compatiblyIncludes(rhq.withoutObjCGCAttr())
+ && (lhptee->isVoidType() || rhptee->isVoidType()))
+ ; // keep old
+
// For GCC compatibility, other qualifier mismatches are treated
// as still compatible in C.
else ConvTy = Sema::CompatiblePointerDiscardsQualifiers;
@@ -5885,7 +6355,7 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc,
// adds casts to this they'll be wasted, but fortunately that doesn't
// usually happen on valid code.
OpaqueValueExpr rhs(Loc, rhsType, VK_RValue);
- Expr *rhsPtr = &rhs;
+ ExprResult rhsPtr = &rhs;
CastKind K = CK_Invalid;
return CheckAssignmentConstraints(lhsType, rhsPtr, K);
@@ -5909,9 +6379,9 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc,
///
/// Sets 'Kind' for any result kind except Incompatible.
Sema::AssignConvertType
-Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs,
+Sema::CheckAssignmentConstraints(QualType lhsType, ExprResult &rhs,
CastKind &Kind) {
- QualType rhsType = rhs->getType();
+ QualType rhsType = rhs.get()->getType();
// Get canonical types. We're not formatting these types, just comparing
// them.
@@ -5950,7 +6420,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs,
QualType elType = cast<ExtVectorType>(lhsType)->getElementType();
if (elType != rhsType) {
Kind = PrepareScalarCast(*this, rhs, elType);
- ImpCastExprToType(rhs, elType, Kind);
+ rhs = ImpCastExprToType(rhs.take(), elType, Kind);
}
Kind = CK_VectorSplat;
return Compatible;
@@ -6151,10 +6621,11 @@ Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs,
/// \brief Constructs a transparent union from an expression that is
/// used to initialize the transparent union.
-static void ConstructTransparentUnion(ASTContext &C, Expr *&E,
+static void ConstructTransparentUnion(Sema &S, ASTContext &C, ExprResult &EResult,
QualType UnionType, FieldDecl *Field) {
// Build an initializer list that designates the appropriate member
// of the transparent union.
+ Expr *E = EResult.take();
InitListExpr *Initializer = new (C) InitListExpr(C, SourceLocation(),
&E, 1,
SourceLocation());
@@ -6164,13 +6635,14 @@ static void ConstructTransparentUnion(ASTContext &C, Expr *&E,
// Build a compound literal constructing a value of the transparent
// union type from this initializer list.
TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType);
- E = new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType,
- VK_RValue, Initializer, false);
+ EResult = S.Owned(
+ new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType,
+ VK_RValue, Initializer, false));
}
Sema::AssignConvertType
-Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) {
- QualType FromType = rExpr->getType();
+Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, ExprResult &rExpr) {
+ QualType FromType = rExpr.get()->getType();
// If the ArgType is a Union type, we want to handle a potential
// transparent_union GCC extension.
@@ -6191,25 +6663,23 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) {
// 2) null pointer constant
if (FromType->isPointerType())
if (FromType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
- ImpCastExprToType(rExpr, it->getType(), CK_BitCast);
+ rExpr = ImpCastExprToType(rExpr.take(), it->getType(), CK_BitCast);
InitField = *it;
break;
}
- if (rExpr->isNullPointerConstant(Context,
+ if (rExpr.get()->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(rExpr, it->getType(), CK_NullToPointer);
+ rExpr = ImpCastExprToType(rExpr.take(), it->getType(), CK_NullToPointer);
InitField = *it;
break;
}
}
- Expr *rhs = rExpr;
CastKind Kind = CK_Invalid;
- if (CheckAssignmentConstraints(it->getType(), rhs, Kind)
+ if (CheckAssignmentConstraints(it->getType(), rExpr, Kind)
== Compatible) {
- ImpCastExprToType(rhs, it->getType(), Kind);
- rExpr = rhs;
+ rExpr = ImpCastExprToType(rExpr.take(), it->getType(), Kind);
InitField = *it;
break;
}
@@ -6218,20 +6688,23 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) {
if (!InitField)
return Incompatible;
- ConstructTransparentUnion(Context, rExpr, ArgType, InitField);
+ ConstructTransparentUnion(*this, Context, rExpr, ArgType, InitField);
return Compatible;
}
Sema::AssignConvertType
-Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
+Sema::CheckSingleAssignmentConstraints(QualType lhsType, ExprResult &rExpr) {
if (getLangOptions().CPlusPlus) {
if (!lhsType->isRecordType()) {
// C++ 5.17p3: If the left operand is not of class type, the
// expression is implicitly converted (C++ 4) to the
// cv-unqualified type of the left operand.
- if (PerformImplicitConversion(rExpr, lhsType.getUnqualifiedType(),
- AA_Assigning))
+ ExprResult Res = PerformImplicitConversion(rExpr.get(),
+ lhsType.getUnqualifiedType(),
+ AA_Assigning);
+ if (Res.isInvalid())
return Incompatible;
+ rExpr = move(Res);
return Compatible;
}
@@ -6244,9 +6717,9 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
if ((lhsType->isPointerType() ||
lhsType->isObjCObjectPointerType() ||
lhsType->isBlockPointerType())
- && rExpr->isNullPointerConstant(Context,
+ && rExpr.get()->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(rExpr, lhsType, CK_NullToPointer);
+ rExpr = ImpCastExprToType(rExpr.take(), lhsType, CK_NullToPointer);
return Compatible;
}
@@ -6256,8 +6729,11 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
// expressions that suppress this implicit conversion (&, sizeof).
//
// Suppress this for references: C++ 8.5.3p5.
- if (!lhsType->isReferenceType())
- DefaultFunctionArrayLvalueConversion(rExpr);
+ if (!lhsType->isReferenceType()) {
+ rExpr = DefaultFunctionArrayLvalueConversion(rExpr.take());
+ if (rExpr.isInvalid())
+ return Incompatible;
+ }
CastKind Kind = CK_Invalid;
Sema::AssignConvertType result =
@@ -6269,25 +6745,25 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
// so that we can use references in built-in functions even in C.
// The getNonReferenceType() call makes sure that the resulting expression
// does not have reference type.
- if (result != Incompatible && rExpr->getType() != lhsType)
- ImpCastExprToType(rExpr, lhsType.getNonLValueExprType(Context), Kind);
+ if (result != Incompatible && rExpr.get()->getType() != lhsType)
+ rExpr = ImpCastExprToType(rExpr.take(), lhsType.getNonLValueExprType(Context), Kind);
return result;
}
-QualType Sema::InvalidOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
+QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &lex, ExprResult &rex) {
Diag(Loc, diag::err_typecheck_invalid_operands)
- << lex->getType() << rex->getType()
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getType() << rex.get()->getType()
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
return QualType();
}
-QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
+QualType Sema::CheckVectorOperands(SourceLocation Loc, ExprResult &lex, ExprResult &rex) {
// For conversion purposes, we ignore any qualifiers.
// For example, "const float" and "float" are equivalent.
QualType lhsType =
- Context.getCanonicalType(lex->getType()).getUnqualifiedType();
+ Context.getCanonicalType(lex.get()->getType()).getUnqualifiedType();
QualType rhsType =
- Context.getCanonicalType(rex->getType()).getUnqualifiedType();
+ Context.getCanonicalType(rex.get()->getType()).getUnqualifiedType();
// If the vector types are identical, return.
if (lhsType == rhsType)
@@ -6301,17 +6777,17 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
if (LV->getElementType() == RV->getElementType() &&
LV->getNumElements() == RV->getNumElements()) {
if (lhsType->isExtVectorType()) {
- ImpCastExprToType(rex, lhsType, CK_BitCast);
+ rex = ImpCastExprToType(rex.take(), lhsType, CK_BitCast);
return lhsType;
}
- ImpCastExprToType(lex, rhsType, CK_BitCast);
+ lex = ImpCastExprToType(lex.take(), rhsType, CK_BitCast);
return rhsType;
} else if (Context.getTypeSize(lhsType) ==Context.getTypeSize(rhsType)){
// If we are allowing lax vector conversions, and LHS and RHS are both
// vectors, the total size only needs to be the same. This is a
// bitcast; no bits are changed but the result type is different.
- ImpCastExprToType(rex, lhsType, CK_BitCast);
+ rex = ImpCastExprToType(rex.take(), lhsType, CK_BitCast);
return lhsType;
}
}
@@ -6321,7 +6797,7 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
// Handle the case of equivalent AltiVec and GCC vector types
if (lhsType->isVectorType() && rhsType->isVectorType() &&
Context.areCompatibleVectorTypes(lhsType, rhsType)) {
- ImpCastExprToType(lex, rhsType, CK_BitCast);
+ lex = ImpCastExprToType(lex.take(), rhsType, CK_BitCast);
return rhsType;
}
@@ -6340,9 +6816,9 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
if (EltTy->isIntegralType(Context) && rhsType->isIntegralType(Context)) {
int order = Context.getIntegerTypeOrder(EltTy, rhsType);
if (order > 0)
- ImpCastExprToType(rex, EltTy, CK_IntegralCast);
+ rex = ImpCastExprToType(rex.take(), EltTy, CK_IntegralCast);
if (order >= 0) {
- ImpCastExprToType(rex, lhsType, CK_VectorSplat);
+ rex = ImpCastExprToType(rex.take(), lhsType, CK_VectorSplat);
if (swapped) std::swap(rex, lex);
return lhsType;
}
@@ -6351,9 +6827,9 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
rhsType->isRealFloatingType()) {
int order = Context.getFloatingTypeOrder(EltTy, rhsType);
if (order > 0)
- ImpCastExprToType(rex, EltTy, CK_FloatingCast);
+ rex = ImpCastExprToType(rex.take(), EltTy, CK_FloatingCast);
if (order >= 0) {
- ImpCastExprToType(rex, lhsType, CK_VectorSplat);
+ rex = ImpCastExprToType(rex.take(), lhsType, CK_VectorSplat);
if (swapped) std::swap(rex, lex);
return lhsType;
}
@@ -6362,72 +6838,78 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
// Vectors of different size or scalar and non-ext-vector are errors.
Diag(Loc, diag::err_typecheck_vector_not_convertable)
- << lex->getType() << rex->getType()
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getType() << rex.get()->getType()
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
return QualType();
}
QualType Sema::CheckMultiplyDivideOperands(
- Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign, bool isDiv) {
- if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+ ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isCompAssign, bool isDiv) {
+ if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType())
return CheckVectorOperands(Loc, lex, rex);
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+ if (lex.isInvalid() || rex.isInvalid())
+ return QualType();
- if (!lex->getType()->isArithmeticType() ||
- !rex->getType()->isArithmeticType())
+ if (!lex.get()->getType()->isArithmeticType() ||
+ !rex.get()->getType()->isArithmeticType())
return InvalidOperands(Loc, lex, rex);
// Check for division by zero.
if (isDiv &&
- rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
- DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_division_by_zero)
- << rex->getSourceRange());
+ rex.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
+ DiagRuntimeBehavior(Loc, rex.get(), PDiag(diag::warn_division_by_zero)
+ << rex.get()->getSourceRange());
return compType;
}
QualType Sema::CheckRemainderOperands(
- Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) {
- if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
- if (lex->getType()->hasIntegerRepresentation() &&
- rex->getType()->hasIntegerRepresentation())
+ ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isCompAssign) {
+ if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) {
+ if (lex.get()->getType()->hasIntegerRepresentation() &&
+ rex.get()->getType()->hasIntegerRepresentation())
return CheckVectorOperands(Loc, lex, rex);
return InvalidOperands(Loc, lex, rex);
}
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+ if (lex.isInvalid() || rex.isInvalid())
+ return QualType();
- if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType())
+ if (!lex.get()->getType()->isIntegerType() || !rex.get()->getType()->isIntegerType())
return InvalidOperands(Loc, lex, rex);
// Check for remainder by zero.
- if (rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
- DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_remainder_by_zero)
- << rex->getSourceRange());
+ if (rex.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
+ DiagRuntimeBehavior(Loc, rex.get(), PDiag(diag::warn_remainder_by_zero)
+ << rex.get()->getSourceRange());
return compType;
}
QualType Sema::CheckAdditionOperands( // C99 6.5.6
- Expr *&lex, Expr *&rex, SourceLocation Loc, QualType* CompLHSTy) {
- if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+ ExprResult &lex, ExprResult &rex, SourceLocation Loc, QualType* CompLHSTy) {
+ if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) {
QualType compType = CheckVectorOperands(Loc, lex, rex);
if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy);
+ if (lex.isInvalid() || rex.isInvalid())
+ return QualType();
// handle the common case first (both operands are arithmetic).
- if (lex->getType()->isArithmeticType() &&
- rex->getType()->isArithmeticType()) {
+ if (lex.get()->getType()->isArithmeticType() &&
+ rex.get()->getType()->isArithmeticType()) {
if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
// Put any potential pointer into PExp
- Expr* PExp = lex, *IExp = rex;
+ Expr* PExp = lex.get(), *IExp = rex.get();
if (IExp->getType()->isAnyPointerType())
std::swap(PExp, IExp);
@@ -6440,23 +6922,23 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6
if (PointeeTy->isVoidType()) {
if (getLangOptions().CPlusPlus) {
Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
return QualType();
}
// GNU extension: arithmetic on pointer to void
Diag(Loc, diag::ext_gnu_void_ptr)
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
} else if (PointeeTy->isFunctionType()) {
if (getLangOptions().CPlusPlus) {
Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
- << lex->getType() << lex->getSourceRange();
+ << lex.get()->getType() << lex.get()->getSourceRange();
return QualType();
}
// GNU extension: arithmetic on pointer to function
Diag(Loc, diag::ext_gnu_ptr_func_arith)
- << lex->getType() << lex->getSourceRange();
+ << lex.get()->getType() << lex.get()->getSourceRange();
} else {
// Check if we require a complete type.
if (((PExp->getType()->isPointerType() &&
@@ -6476,9 +6958,9 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6
}
if (CompLHSTy) {
- QualType LHSTy = Context.isPromotableBitField(lex);
+ QualType LHSTy = Context.isPromotableBitField(lex.get());
if (LHSTy.isNull()) {
- LHSTy = lex->getType();
+ LHSTy = lex.get()->getType();
if (LHSTy->isPromotableIntegerType())
LHSTy = Context.getPromotedIntegerType(LHSTy);
}
@@ -6492,28 +6974,30 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6
}
// C99 6.5.6
-QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
+QualType Sema::CheckSubtractionOperands(ExprResult &lex, ExprResult &rex,
SourceLocation Loc, QualType* CompLHSTy) {
- if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+ if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) {
QualType compType = CheckVectorOperands(Loc, lex, rex);
if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy);
+ if (lex.isInvalid() || rex.isInvalid())
+ return QualType();
// Enforce type constraints: C99 6.5.6p3.
// Handle the common case first (both operands are arithmetic).
- if (lex->getType()->isArithmeticType()
- && rex->getType()->isArithmeticType()) {
+ if (lex.get()->getType()->isArithmeticType() &&
+ rex.get()->getType()->isArithmeticType()) {
if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
// Either ptr - int or ptr - ptr.
- if (lex->getType()->isAnyPointerType()) {
- QualType lpointee = lex->getType()->getPointeeType();
+ if (lex.get()->getType()->isAnyPointerType()) {
+ QualType lpointee = lex.get()->getType()->getPointeeType();
// The LHS must be an completely-defined object type.
@@ -6522,7 +7006,7 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
if (lpointee->isVoidType()) {
if (getLangOptions().CPlusPlus) {
Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
return QualType();
}
@@ -6531,42 +7015,42 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
} else if (lpointee->isFunctionType()) {
if (getLangOptions().CPlusPlus) {
Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
- << lex->getType() << lex->getSourceRange();
+ << lex.get()->getType() << lex.get()->getSourceRange();
return QualType();
}
// GNU C extension: arithmetic on pointer to function
- ComplainAboutFunc = lex;
+ ComplainAboutFunc = lex.get();
} else if (!lpointee->isDependentType() &&
RequireCompleteType(Loc, lpointee,
PDiag(diag::err_typecheck_sub_ptr_object)
- << lex->getSourceRange()
- << lex->getType()))
+ << lex.get()->getSourceRange()
+ << lex.get()->getType()))
return QualType();
// Diagnose bad cases where we step over interface counts.
if (lpointee->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
Diag(Loc, diag::err_arithmetic_nonfragile_interface)
- << lpointee << lex->getSourceRange();
+ << lpointee << lex.get()->getSourceRange();
return QualType();
}
// The result type of a pointer-int computation is the pointer type.
- if (rex->getType()->isIntegerType()) {
+ if (rex.get()->getType()->isIntegerType()) {
if (ComplainAboutVoid)
Diag(Loc, diag::ext_gnu_void_ptr)
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
if (ComplainAboutFunc)
Diag(Loc, diag::ext_gnu_ptr_func_arith)
<< ComplainAboutFunc->getType()
<< ComplainAboutFunc->getSourceRange();
- if (CompLHSTy) *CompLHSTy = lex->getType();
- return lex->getType();
+ if (CompLHSTy) *CompLHSTy = lex.get()->getType();
+ return lex.get()->getType();
}
// Handle pointer-pointer subtractions.
- if (const PointerType *RHSPTy = rex->getType()->getAs<PointerType>()) {
+ if (const PointerType *RHSPTy = rex.get()->getType()->getAs<PointerType>()) {
QualType rpointee = RHSPTy->getPointeeType();
// RHS must be a completely-type object type.
@@ -6574,7 +7058,7 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
if (rpointee->isVoidType()) {
if (getLangOptions().CPlusPlus) {
Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
return QualType();
}
@@ -6582,26 +7066,26 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
} else if (rpointee->isFunctionType()) {
if (getLangOptions().CPlusPlus) {
Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
- << rex->getType() << rex->getSourceRange();
+ << rex.get()->getType() << rex.get()->getSourceRange();
return QualType();
}
// GNU extension: arithmetic on pointer to function
if (!ComplainAboutFunc)
- ComplainAboutFunc = rex;
+ ComplainAboutFunc = rex.get();
} else if (!rpointee->isDependentType() &&
RequireCompleteType(Loc, rpointee,
PDiag(diag::err_typecheck_sub_ptr_object)
- << rex->getSourceRange()
- << rex->getType()))
+ << rex.get()->getSourceRange()
+ << rex.get()->getType()))
return QualType();
if (getLangOptions().CPlusPlus) {
// Pointee types must be the same: C++ [expr.add]
if (!Context.hasSameUnqualifiedType(lpointee, rpointee)) {
Diag(Loc, diag::err_typecheck_sub_ptr_compatible)
- << lex->getType() << rex->getType()
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getType() << rex.get()->getType()
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
return QualType();
}
} else {
@@ -6610,21 +7094,21 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
Context.getCanonicalType(lpointee).getUnqualifiedType(),
Context.getCanonicalType(rpointee).getUnqualifiedType())) {
Diag(Loc, diag::err_typecheck_sub_ptr_compatible)
- << lex->getType() << rex->getType()
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getType() << rex.get()->getType()
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
return QualType();
}
}
if (ComplainAboutVoid)
Diag(Loc, diag::ext_gnu_void_ptr)
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
if (ComplainAboutFunc)
Diag(Loc, diag::ext_gnu_ptr_func_arith)
<< ComplainAboutFunc->getType()
<< ComplainAboutFunc->getSourceRange();
- if (CompLHSTy) *CompLHSTy = lex->getType();
+ if (CompLHSTy) *CompLHSTy = lex.get()->getType();
return Context.getPointerDiffType();
}
}
@@ -6638,22 +7122,26 @@ static bool isScopedEnumerationType(QualType T) {
return false;
}
-static void DiagnoseBadShiftValues(Sema& S, Expr *&lex, Expr *&rex,
+static void DiagnoseBadShiftValues(Sema& S, ExprResult &lex, ExprResult &rex,
SourceLocation Loc, unsigned Opc,
QualType LHSTy) {
llvm::APSInt Right;
// Check right/shifter operand
- if (rex->isValueDependent() || !rex->isIntegerConstantExpr(Right, S.Context))
+ if (rex.get()->isValueDependent() || !rex.get()->isIntegerConstantExpr(Right, S.Context))
return;
if (Right.isNegative()) {
- S.Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange();
+ S.DiagRuntimeBehavior(Loc, rex.get(),
+ S.PDiag(diag::warn_shift_negative)
+ << rex.get()->getSourceRange());
return;
}
llvm::APInt LeftBits(Right.getBitWidth(),
- S.Context.getTypeSize(lex->getType()));
+ S.Context.getTypeSize(lex.get()->getType()));
if (Right.uge(LeftBits)) {
- S.Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange();
+ S.DiagRuntimeBehavior(Loc, rex.get(),
+ S.PDiag(diag::warn_shift_gt_typewidth)
+ << rex.get()->getSourceRange());
return;
}
if (Opc != BO_Shl)
@@ -6664,7 +7152,7 @@ static void DiagnoseBadShiftValues(Sema& S, Expr *&lex, Expr *&rex,
// integers have defined behavior modulo one more than the maximum value
// representable in the result type, so never warn for those.
llvm::APSInt Left;
- if (lex->isValueDependent() || !lex->isIntegerConstantExpr(Left, S.Context) ||
+ if (lex.get()->isValueDependent() || !lex.get()->isIntegerConstantExpr(Left, S.Context) ||
LHSTy->hasUnsignedIntegerRepresentation())
return;
llvm::APInt ResultBits =
@@ -6681,32 +7169,32 @@ static void DiagnoseBadShiftValues(Sema& S, Expr *&lex, Expr *&rex,
if (LeftBits == ResultBits - 1) {
S.Diag(Loc, diag::warn_shift_result_overrides_sign_bit)
<< Result.toString(10) << LHSTy
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
return;
}
S.Diag(Loc, diag::warn_shift_result_gt_typewidth)
<< Result.toString(10) << Result.getMinSignedBits() << LHSTy
- << Left.getBitWidth() << lex->getSourceRange() << rex->getSourceRange();
+ << Left.getBitWidth() << lex.get()->getSourceRange() << rex.get()->getSourceRange();
}
// C99 6.5.7
-QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
+QualType Sema::CheckShiftOperands(ExprResult &lex, ExprResult &rex, SourceLocation Loc,
unsigned Opc, bool isCompAssign) {
// C99 6.5.7p2: Each of the operands shall have integer type.
- if (!lex->getType()->hasIntegerRepresentation() ||
- !rex->getType()->hasIntegerRepresentation())
+ if (!lex.get()->getType()->hasIntegerRepresentation() ||
+ !rex.get()->getType()->hasIntegerRepresentation())
return InvalidOperands(Loc, lex, rex);
// C++0x: Don't allow scoped enums. FIXME: Use something better than
// hasIntegerRepresentation() above instead of this.
- if (isScopedEnumerationType(lex->getType()) ||
- isScopedEnumerationType(rex->getType())) {
+ if (isScopedEnumerationType(lex.get()->getType()) ||
+ isScopedEnumerationType(rex.get()->getType())) {
return InvalidOperands(Loc, lex, rex);
}
// Vector shifts promote their scalar inputs to vector type.
- if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+ if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType())
return CheckVectorOperands(Loc, lex, rex);
// Shifts don't perform usual arithmetic conversions, they just do integer
@@ -6714,13 +7202,17 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
// For the LHS, do usual unary conversions, but then reset them away
// if this is a compound assignment.
- Expr *old_lex = lex;
- UsualUnaryConversions(lex);
- QualType LHSTy = lex->getType();
+ ExprResult old_lex = lex;
+ lex = UsualUnaryConversions(lex.take());
+ if (lex.isInvalid())
+ return QualType();
+ QualType LHSTy = lex.get()->getType();
if (isCompAssign) lex = old_lex;
// The RHS is simpler.
- UsualUnaryConversions(rex);
+ rex = UsualUnaryConversions(rex.take());
+ if (rex.isInvalid())
+ return QualType();
// Sanity-check shift operands
DiagnoseBadShiftValues(*this, lex, rex, Loc, Opc, LHSTy);
@@ -6740,22 +7232,24 @@ static bool IsWithinTemplateSpecialization(Decl *D) {
}
// C99 6.5.8, C++ [expr.rel]
-QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
+QualType Sema::CheckCompareOperands(ExprResult &lex, ExprResult &rex, SourceLocation Loc,
unsigned OpaqueOpc, bool isRelational) {
BinaryOperatorKind Opc = (BinaryOperatorKind) OpaqueOpc;
// Handle vector comparisons separately.
- if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+ if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType())
return CheckVectorCompareOperands(lex, rex, Loc, isRelational);
- QualType lType = lex->getType();
- QualType rType = rex->getType();
-
- Expr *LHSStripped = lex->IgnoreParenImpCasts();
- Expr *RHSStripped = rex->IgnoreParenImpCasts();
+ QualType lType = lex.get()->getType();
+ QualType rType = rex.get()->getType();
+
+ Expr *LHSStripped = lex.get()->IgnoreParenImpCasts();
+ Expr *RHSStripped = rex.get()->IgnoreParenImpCasts();
QualType LHSStrippedType = LHSStripped->getType();
QualType RHSStrippedType = RHSStripped->getType();
+
+
// Two different enums will raise a warning when compared.
if (const EnumType *LHSEnumType = LHSStrippedType->getAs<EnumType>()) {
if (const EnumType *RHSEnumType = RHSStrippedType->getAs<EnumType>()) {
@@ -6764,15 +7258,15 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
!Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType)) {
Diag(Loc, diag::warn_comparison_of_mixed_enum_types)
<< LHSStrippedType << RHSStrippedType
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
}
}
}
if (!lType->hasFloatingRepresentation() &&
!(lType->isBlockPointerType() && isRelational) &&
- !lex->getLocStart().isMacroID() &&
- !rex->getLocStart().isMacroID()) {
+ !lex.get()->getLocStart().isMacroID() &&
+ !rex.get()->getLocStart().isMacroID()) {
// For non-floating point types, check for self-comparisons of the form
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
// often indicate logic errors in the program.
@@ -6828,13 +7322,13 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) &&
!RHSStripped->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
- literalString = lex;
+ literalString = lex.get();
literalStringStripped = LHSStripped;
} else if ((isa<StringLiteral>(RHSStripped) ||
isa<ObjCEncodeExpr>(RHSStripped)) &&
!LHSStripped->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
- literalString = rex;
+ literalString = rex.get();
literalStringStripped = RHSStripped;
}
@@ -6858,15 +7352,23 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
}
// C99 6.5.8p3 / C99 6.5.9p4
- if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
+ if (lex.get()->getType()->isArithmeticType() && rex.get()->getType()->isArithmeticType()) {
UsualArithmeticConversions(lex, rex);
+ if (lex.isInvalid() || rex.isInvalid())
+ return QualType();
+ }
else {
- UsualUnaryConversions(lex);
- UsualUnaryConversions(rex);
+ lex = UsualUnaryConversions(lex.take());
+ if (lex.isInvalid())
+ return QualType();
+
+ rex = UsualUnaryConversions(rex.take());
+ if (rex.isInvalid())
+ return QualType();
}
- lType = lex->getType();
- rType = rex->getType();
+ lType = lex.get()->getType();
+ rType = rex.get()->getType();
// The result of comparisons is 'bool' in C++, 'int' in C.
QualType ResultTy = Context.getLogicalOperationType();
@@ -6877,15 +7379,15 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
} else {
// Check for comparisons of floating point operands using != and ==.
if (lType->hasFloatingRepresentation())
- CheckFloatComparison(Loc,lex,rex);
+ CheckFloatComparison(Loc, lex.get(), rex.get());
if (lType->isArithmeticType() && rType->isArithmeticType())
return ResultTy;
}
- bool LHSIsNull = lex->isNullPointerConstant(Context,
+ bool LHSIsNull = lex.get()->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull);
- bool RHSIsNull = rex->isNullPointerConstant(Context,
+ bool RHSIsNull = rex.get()->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull);
// All of the following pointer-related warnings are GCC extensions, except
@@ -6911,12 +7413,12 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
isSFINAEContext()?
diag::err_typecheck_comparison_of_fptr_to_void
: diag::ext_typecheck_comparison_of_fptr_to_void)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange();
if (isSFINAEContext())
return QualType();
- ImpCastExprToType(rex, lType, CK_BitCast);
+ rex = ImpCastExprToType(rex.take(), lType, CK_BitCast);
return ResultTy;
}
}
@@ -6934,17 +7436,17 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
isSFINAEContext()? 0 : &NonStandardCompositeType);
if (T.isNull()) {
Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange();
return QualType();
} else if (NonStandardCompositeType) {
Diag(Loc,
diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard)
<< lType << rType << T
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
}
- ImpCastExprToType(lex, T, CK_BitCast);
- ImpCastExprToType(rex, T, CK_BitCast);
+ lex = ImpCastExprToType(lex.take(), T, CK_BitCast);
+ rex = ImpCastExprToType(rex.take(), T, CK_BitCast);
return ResultTy;
}
// C99 6.5.9p2 and C99 6.5.8p2
@@ -6953,7 +7455,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
// Valid unless a relational comparison of function pointers
if (isRelational && LCanPointeeTy->isFunctionType()) {
Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange();
}
} else if (!isRelational &&
(LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
@@ -6961,15 +7463,19 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
&& !LHSIsNull && !RHSIsNull) {
Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange();
}
} else {
// Invalid
Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange();
+ }
+ if (LCanPointeeTy != RCanPointeeTy) {
+ if (LHSIsNull && !RHSIsNull)
+ lex = ImpCastExprToType(lex.take(), rType, CK_BitCast);
+ else
+ rex = ImpCastExprToType(rex.take(), lType, CK_BitCast);
}
- if (LCanPointeeTy != RCanPointeeTy)
- ImpCastExprToType(rex, lType, CK_BitCast);
return ResultTy;
}
@@ -6983,7 +7489,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (RHSIsNull &&
((lType->isPointerType() || lType->isNullPtrType()) ||
(!isRelational && lType->isMemberPointerType()))) {
- ImpCastExprToType(rex, lType,
+ rex = ImpCastExprToType(rex.take(), lType,
lType->isMemberPointerType()
? CK_NullToMemberPointer
: CK_NullToPointer);
@@ -6992,7 +7498,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (LHSIsNull &&
((rType->isPointerType() || rType->isNullPtrType()) ||
(!isRelational && rType->isMemberPointerType()))) {
- ImpCastExprToType(lex, rType,
+ lex = ImpCastExprToType(lex.take(), rType,
rType->isMemberPointerType()
? CK_NullToMemberPointer
: CK_NullToPointer);
@@ -7017,19 +7523,25 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
isSFINAEContext()? 0 : &NonStandardCompositeType);
if (T.isNull()) {
Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange();
return QualType();
} else if (NonStandardCompositeType) {
Diag(Loc,
diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard)
<< lType << rType << T
- << lex->getSourceRange() << rex->getSourceRange();
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();
}
- ImpCastExprToType(lex, T, CK_BitCast);
- ImpCastExprToType(rex, T, CK_BitCast);
+ lex = ImpCastExprToType(lex.take(), T, CK_BitCast);
+ rex = ImpCastExprToType(rex.take(), T, CK_BitCast);
return ResultTy;
}
+
+ // Handle scoped enumeration types specifically, since they don't promote
+ // to integers.
+ if (lex.get()->getType()->isEnumeralType() &&
+ Context.hasSameUnqualifiedType(lex.get()->getType(), rex.get()->getType()))
+ return ResultTy;
}
// Handle block pointer types.
@@ -7040,49 +7552,57 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (!LHSIsNull && !RHSIsNull &&
!Context.typesAreCompatible(lpointee, rpointee)) {
Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange();
}
- ImpCastExprToType(rex, lType, CK_BitCast);
+ rex = ImpCastExprToType(rex.take(), lType, CK_BitCast);
return ResultTy;
}
+
// Allow block pointers to be compared with null pointer constants.
if (!isRelational
&& ((lType->isBlockPointerType() && rType->isPointerType())
|| (lType->isPointerType() && rType->isBlockPointerType()))) {
if (!LHSIsNull && !RHSIsNull) {
- if (!((rType->isPointerType() && rType->getAs<PointerType>()
+ if (!((rType->isPointerType() && rType->castAs<PointerType>()
->getPointeeType()->isVoidType())
- || (lType->isPointerType() && lType->getAs<PointerType>()
+ || (lType->isPointerType() && lType->castAs<PointerType>()
->getPointeeType()->isVoidType())))
Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange();
}
- ImpCastExprToType(rex, lType, CK_BitCast);
+ if (LHSIsNull && !RHSIsNull)
+ lex = ImpCastExprToType(lex.take(), rType, CK_BitCast);
+ else
+ rex = ImpCastExprToType(rex.take(), lType, CK_BitCast);
return ResultTy;
}
- if ((lType->isObjCObjectPointerType() || rType->isObjCObjectPointerType())) {
- if (lType->isPointerType() || rType->isPointerType()) {
- const PointerType *LPT = lType->getAs<PointerType>();
- const PointerType *RPT = rType->getAs<PointerType>();
- bool LPtrToVoid = LPT ?
- Context.getCanonicalType(LPT->getPointeeType())->isVoidType() : false;
- bool RPtrToVoid = RPT ?
- Context.getCanonicalType(RPT->getPointeeType())->isVoidType() : false;
+ if (lType->isObjCObjectPointerType() || rType->isObjCObjectPointerType()) {
+ const PointerType *LPT = lType->getAs<PointerType>();
+ const PointerType *RPT = rType->getAs<PointerType>();
+ if (LPT || RPT) {
+ bool LPtrToVoid = LPT ? LPT->getPointeeType()->isVoidType() : false;
+ bool RPtrToVoid = RPT ? RPT->getPointeeType()->isVoidType() : false;
if (!LPtrToVoid && !RPtrToVoid &&
!Context.typesAreCompatible(lType, rType)) {
Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange();
}
- ImpCastExprToType(rex, lType, CK_BitCast);
+ if (LHSIsNull && !RHSIsNull)
+ lex = ImpCastExprToType(lex.take(), rType, CK_BitCast);
+ else
+ rex = ImpCastExprToType(rex.take(), lType, CK_BitCast);
return ResultTy;
}
if (lType->isObjCObjectPointerType() && rType->isObjCObjectPointerType()) {
if (!Context.areComparableObjCPointerTypes(lType, rType))
Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
- ImpCastExprToType(rex, lType, CK_BitCast);
+ << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange();
+ if (LHSIsNull && !RHSIsNull)
+ lex = ImpCastExprToType(lex.take(), rType, CK_BitCast);
+ else
+ rex = ImpCastExprToType(rex.take(), lType, CK_BitCast);
return ResultTy;
}
}
@@ -7104,16 +7624,16 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (DiagID) {
Diag(Loc, DiagID)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange();
if (isError)
return QualType();
}
if (lType->isIntegerType())
- ImpCastExprToType(lex, rType,
+ lex = ImpCastExprToType(lex.take(), rType,
LHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
else
- ImpCastExprToType(rex, lType,
+ rex = ImpCastExprToType(rex.take(), lType,
RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
return ResultTy;
}
@@ -7121,14 +7641,15 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
// Handle block pointers.
if (!isRelational && RHSIsNull
&& lType->isBlockPointerType() && rType->isIntegerType()) {
- ImpCastExprToType(rex, lType, CK_NullToPointer);
+ rex = ImpCastExprToType(rex.take(), lType, CK_NullToPointer);
return ResultTy;
}
if (!isRelational && LHSIsNull
&& lType->isIntegerType() && rType->isBlockPointerType()) {
- ImpCastExprToType(lex, rType, CK_NullToPointer);
+ lex = ImpCastExprToType(lex.take(), rType, CK_NullToPointer);
return ResultTy;
}
+
return InvalidOperands(Loc, lex, rex);
}
@@ -7136,7 +7657,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
/// operates on extended vector types. Instead of producing an IntTy result,
/// like a scalar comparison, a vector comparison produces a vector of integer
/// types.
-QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
+QualType Sema::CheckVectorCompareOperands(ExprResult &lex, ExprResult &rex,
SourceLocation Loc,
bool isRelational) {
// Check to make sure we're operating on vectors of the same type and width,
@@ -7145,20 +7666,20 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
if (vType.isNull())
return vType;
+ QualType lType = lex.get()->getType();
+ QualType rType = rex.get()->getType();
+
// If AltiVec, the comparison results in a numeric type, i.e.
// bool for C++, int for C
- if (getLangOptions().AltiVec)
+ if (vType->getAs<VectorType>()->getVectorKind() == VectorType::AltiVecVector)
return Context.getLogicalOperationType();
- QualType lType = lex->getType();
- QualType rType = rex->getType();
-
// For non-floating point types, check for self-comparisons of the form
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
// often indicate logic errors in the program.
if (!lType->hasFloatingRepresentation()) {
- if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens()))
- if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens()))
+ if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex.get()->IgnoreParens()))
+ if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex.get()->IgnoreParens()))
if (DRL->getDecl() == DRR->getDecl())
DiagRuntimeBehavior(Loc, 0,
PDiag(diag::warn_comparison_always)
@@ -7170,7 +7691,7 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
// Check for comparisons of floating point operands using != and ==.
if (!isRelational && lType->hasFloatingRepresentation()) {
assert (rType->hasFloatingRepresentation());
- CheckFloatComparison(Loc,lex,rex);
+ CheckFloatComparison(Loc, lex.get(), rex.get());
}
// Return the type for the comparison, which is the same as vector type for
@@ -7192,51 +7713,61 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
}
inline QualType Sema::CheckBitwiseOperands(
- Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) {
- if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
- if (lex->getType()->hasIntegerRepresentation() &&
- rex->getType()->hasIntegerRepresentation())
+ ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isCompAssign) {
+ if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) {
+ if (lex.get()->getType()->hasIntegerRepresentation() &&
+ rex.get()->getType()->hasIntegerRepresentation())
return CheckVectorOperands(Loc, lex, rex);
return InvalidOperands(Loc, lex, rex);
}
- QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+ ExprResult lexResult = Owned(lex), rexResult = Owned(rex);
+ QualType compType = UsualArithmeticConversions(lexResult, rexResult, isCompAssign);
+ if (lexResult.isInvalid() || rexResult.isInvalid())
+ return QualType();
+ lex = lexResult.take();
+ rex = rexResult.take();
- if (lex->getType()->isIntegralOrUnscopedEnumerationType() &&
- rex->getType()->isIntegralOrUnscopedEnumerationType())
+ if (lex.get()->getType()->isIntegralOrUnscopedEnumerationType() &&
+ rex.get()->getType()->isIntegralOrUnscopedEnumerationType())
return compType;
return InvalidOperands(Loc, lex, rex);
}
inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
- Expr *&lex, Expr *&rex, SourceLocation Loc, unsigned Opc) {
+ ExprResult &lex, ExprResult &rex, SourceLocation Loc, unsigned Opc) {
// Diagnose cases where the user write a logical and/or but probably meant a
// bitwise one. We do this when the LHS is a non-bool integer and the RHS
// is a constant.
- if (lex->getType()->isIntegerType() && !lex->getType()->isBooleanType() &&
- rex->getType()->isIntegerType() && !rex->isValueDependent() &&
+ if (lex.get()->getType()->isIntegerType() && !lex.get()->getType()->isBooleanType() &&
+ rex.get()->getType()->isIntegerType() && !rex.get()->isValueDependent() &&
// Don't warn in macros.
!Loc.isMacroID()) {
// If the RHS can be constant folded, and if it constant folds to something
// that isn't 0 or 1 (which indicate a potential logical operation that
// happened to fold to true/false) then warn.
Expr::EvalResult Result;
- if (rex->Evaluate(Result, Context) && !Result.HasSideEffects &&
+ if (rex.get()->Evaluate(Result, Context) && !Result.HasSideEffects &&
Result.Val.getInt() != 0 && Result.Val.getInt() != 1) {
Diag(Loc, diag::warn_logical_instead_of_bitwise)
- << rex->getSourceRange()
+ << rex.get()->getSourceRange()
<< (Opc == BO_LAnd ? "&&" : "||")
<< (Opc == BO_LAnd ? "&" : "|");
}
}
if (!Context.getLangOptions().CPlusPlus) {
- UsualUnaryConversions(lex);
- UsualUnaryConversions(rex);
+ lex = UsualUnaryConversions(lex.take());
+ if (lex.isInvalid())
+ return QualType();
+
+ rex = UsualUnaryConversions(rex.take());
+ if (rex.isInvalid())
+ return QualType();
- if (!lex->getType()->isScalarType() || !rex->getType()->isScalarType())
+ if (!lex.get()->getType()->isScalarType() || !rex.get()->getType()->isScalarType())
return InvalidOperands(Loc, lex, rex);
return Context.IntTy;
@@ -7248,9 +7779,15 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
// C++ [expr.log.and]p1
// C++ [expr.log.or]p1
// The operands are both contextually converted to type bool.
- if (PerformContextuallyConvertToBool(lex) ||
- PerformContextuallyConvertToBool(rex))
+ ExprResult lexRes = PerformContextuallyConvertToBool(lex.get());
+ if (lexRes.isInvalid())
+ return InvalidOperands(Loc, lex, rex);
+ lex = move(lexRes);
+
+ ExprResult rexRes = PerformContextuallyConvertToBool(rex.get());
+ if (rexRes.isInvalid())
return InvalidOperands(Loc, lex, rex);
+ rex = move(rexRes);
// C++ [expr.log.and]p2
// C++ [expr.log.or]p2
@@ -7281,6 +7818,35 @@ static bool IsReadonlyProperty(Expr *E, Sema &S) {
return false;
}
+static bool IsConstProperty(Expr *E, Sema &S) {
+ if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) {
+ const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E);
+ if (PropExpr->isImplicitProperty()) return false;
+
+ ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
+ QualType T = PDecl->getType();
+ if (T->isReferenceType())
+ T = T->getAs<ReferenceType>()->getPointeeType();
+ CanQualType CT = S.Context.getCanonicalType(T);
+ return CT.isConstQualified();
+ }
+ return false;
+}
+
+static bool IsReadonlyMessage(Expr *E, Sema &S) {
+ if (E->getStmtClass() != Expr::MemberExprClass)
+ return false;
+ const MemberExpr *ME = cast<MemberExpr>(E);
+ NamedDecl *Member = ME->getMemberDecl();
+ if (isa<FieldDecl>(Member)) {
+ Expr *Base = ME->getBase()->IgnoreParenImpCasts();
+ if (Base->getStmtClass() != Expr::ObjCMessageExprClass)
+ return false;
+ return cast<ObjCMessageExpr>(Base)->getMethodDecl() != 0;
+ }
+ return false;
+}
+
/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not,
/// emit an error and return true. If so, return false.
static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
@@ -7289,6 +7855,10 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
&Loc);
if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S))
IsLV = Expr::MLV_ReadonlyProperty;
+ else if (Expr::MLV_ConstQualified && IsConstProperty(E, S))
+ IsLV = Expr::MLV_Valid;
+ else if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S))
+ IsLV = Expr::MLV_InvalidMessageExpression;
if (IsLV == Expr::MLV_Valid)
return false;
@@ -7331,6 +7901,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
case Expr::MLV_NoSetterProperty:
Diag = diag::error_nosetter_property_assignment;
break;
+ case Expr::MLV_InvalidMessageExpression:
+ Diag = diag::error_readonly_message_assignment;
+ break;
case Expr::MLV_SubObjCPropertySetting:
Diag = diag::error_no_subobject_property_setting;
break;
@@ -7349,7 +7922,7 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
// C99 6.5.16.1
-QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
+QualType Sema::CheckAssignmentOperands(Expr *LHS, ExprResult &RHS,
SourceLocation Loc,
QualType CompoundType) {
// Verify that LHS is a modifiable lvalue, and emit error if not.
@@ -7357,14 +7930,21 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
return QualType();
QualType LHSType = LHS->getType();
- QualType RHSType = CompoundType.isNull() ? RHS->getType() : CompoundType;
+ QualType RHSType = CompoundType.isNull() ? RHS.get()->getType() : CompoundType;
AssignConvertType ConvTy;
if (CompoundType.isNull()) {
QualType LHSTy(LHSType);
// Simple assignment "x = y".
- if (LHS->getObjectKind() == OK_ObjCProperty)
- ConvertPropertyForLValue(LHS, RHS, LHSTy);
+ if (LHS->getObjectKind() == OK_ObjCProperty) {
+ ExprResult LHSResult = Owned(LHS);
+ ConvertPropertyForLValue(LHSResult, RHS, LHSTy);
+ if (LHSResult.isInvalid())
+ return QualType();
+ LHS = LHSResult.take();
+ }
ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
+ if (RHS.isInvalid())
+ return QualType();
// Special case of NSObject attributes on c-style pointer types.
if (ConvTy == IncompatiblePointer &&
((Context.isObjCNSObjectType(LHSType) &&
@@ -7382,7 +7962,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
// If the RHS is a unary plus or minus, check to see if they = and + are
// right next to each other. If so, the user may have typo'd "x =+ 4"
// instead of "x += 4".
- Expr *RHSCheck = RHS;
+ Expr *RHSCheck = RHS.get();
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RHSCheck))
RHSCheck = ICE->getSubExpr();
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(RHSCheck)) {
@@ -7406,32 +7986,12 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
}
if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType,
- RHS, AA_Assigning))
+ RHS.get(), AA_Assigning))
return QualType();
-
- // Check to see if the destination operand is a dereferenced null pointer. If
- // so, and if not volatile-qualified, this is undefined behavior that the
- // optimizer will delete, so warn about it. People sometimes try to use this
- // to get a deterministic trap and are surprised by clang's behavior. This
- // only handles the pattern "*null = whatever", which is a very syntactic
- // check.
- if (UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS->IgnoreParenCasts()))
- if (UO->getOpcode() == UO_Deref &&
- UO->getSubExpr()->IgnoreParenCasts()->
- isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) &&
- !UO->getType().isVolatileQualified()) {
- DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
- PDiag(diag::warn_indirection_through_null)
- << UO->getSubExpr()->getSourceRange());
- DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
- PDiag(diag::note_indirection_through_null));
- }
-
+ CheckForNullPointerDereference(*this, LHS);
// Check for trivial buffer overflows.
- if (const ArraySubscriptExpr *ae
- = dyn_cast<ArraySubscriptExpr>(LHS->IgnoreParenCasts()))
- CheckArrayAccess(ae);
+ CheckArrayAccess(LHS->IgnoreParenCasts());
// C99 6.5.16p3: The type of an assignment expression is the type of the
// left operand unless the left operand has qualified type, in which case
@@ -7445,34 +8005,34 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
}
// C99 6.5.17
-static QualType CheckCommaOperands(Sema &S, Expr *&LHS, Expr *&RHS,
+static QualType CheckCommaOperands(Sema &S, ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc) {
- S.DiagnoseUnusedExprResult(LHS);
+ S.DiagnoseUnusedExprResult(LHS.get());
- ExprResult LHSResult = S.CheckPlaceholderExpr(LHS, Loc);
- if (LHSResult.isInvalid())
+ LHS = S.CheckPlaceholderExpr(LHS.take());
+ RHS = S.CheckPlaceholderExpr(RHS.take());
+ if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
- ExprResult RHSResult = S.CheckPlaceholderExpr(RHS, Loc);
- if (RHSResult.isInvalid())
- return QualType();
- RHS = RHSResult.take();
-
// C's comma performs lvalue conversion (C99 6.3.2.1) on both its
// operands, but not unary promotions.
// C++'s comma does not do any conversions at all (C++ [expr.comma]p1).
// So we treat the LHS as a ignored value, and in C++ we allow the
// containing site to determine what should be done with the RHS.
- S.IgnoredValueConversions(LHS);
+ LHS = S.IgnoredValueConversions(LHS.take());
+ if (LHS.isInvalid())
+ return QualType();
if (!S.getLangOptions().CPlusPlus) {
- S.DefaultFunctionArrayLvalueConversion(RHS);
- if (!RHS->getType()->isVoidType())
- S.RequireCompleteType(Loc, RHS->getType(), diag::err_incomplete_type);
+ RHS = S.DefaultFunctionArrayLvalueConversion(RHS.take());
+ if (RHS.isInvalid())
+ return QualType();
+ if (!RHS.get()->getType()->isVoidType())
+ S.RequireCompleteType(Loc, RHS.get()->getType(), diag::err_incomplete_type);
}
- return RHS->getType();
+ return RHS.get()->getType();
}
/// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine
@@ -7535,7 +8095,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
S.Diag(OpLoc, diag::ext_integer_increment_complex)
<< ResType << Op->getSourceRange();
} else if (ResType->isPlaceholderType()) {
- ExprResult PR = S.CheckPlaceholderExpr(Op, OpLoc);
+ ExprResult PR = S.CheckPlaceholderExpr(Op);
if (PR.isInvalid()) return QualType();
return CheckIncrementDecrementOperand(S, PR.take(), VK, OpLoc,
isInc, isPrefix);
@@ -7562,7 +8122,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
}
}
-void Sema::ConvertPropertyForRValue(Expr *&E) {
+ExprResult Sema::ConvertPropertyForRValue(Expr *E) {
assert(E->getValueKind() == VK_LValue &&
E->getObjectKind() == OK_ObjCProperty);
const ObjCPropertyRefExpr *PRE = E->getObjCProperty();
@@ -7586,28 +8146,30 @@ void Sema::ConvertPropertyForRValue(Expr *&E) {
ExprResult Result = MaybeBindToTemporary(E);
if (!Result.isInvalid())
E = Result.take();
+
+ return Owned(E);
}
-void Sema::ConvertPropertyForLValue(Expr *&LHS, Expr *&RHS, QualType &LHSTy) {
- assert(LHS->getValueKind() == VK_LValue &&
- LHS->getObjectKind() == OK_ObjCProperty);
- const ObjCPropertyRefExpr *PRE = LHS->getObjCProperty();
+void Sema::ConvertPropertyForLValue(ExprResult &LHS, ExprResult &RHS, QualType &LHSTy) {
+ assert(LHS.get()->getValueKind() == VK_LValue &&
+ LHS.get()->getObjectKind() == OK_ObjCProperty);
+ const ObjCPropertyRefExpr *PropRef = LHS.get()->getObjCProperty();
- if (PRE->isImplicitProperty()) {
+ if (PropRef->isImplicitProperty()) {
// If using property-dot syntax notation for assignment, and there is a
// setter, RHS expression is being passed to the setter argument. So,
// type conversion (and comparison) is RHS to setter's argument type.
- if (const ObjCMethodDecl *SetterMD = PRE->getImplicitPropertySetter()) {
+ if (const ObjCMethodDecl *SetterMD = PropRef->getImplicitPropertySetter()) {
ObjCMethodDecl::param_iterator P = SetterMD->param_begin();
LHSTy = (*P)->getType();
// Otherwise, if the getter returns an l-value, just call that.
} else {
- QualType Result = PRE->getImplicitPropertyGetter()->getResultType();
+ QualType Result = PropRef->getImplicitPropertyGetter()->getResultType();
ExprValueKind VK = Expr::getValueKindForType(Result);
if (VK == VK_LValue) {
- LHS = ImplicitCastExpr::Create(Context, LHS->getType(),
- CK_GetObjCProperty, LHS, 0, VK);
+ LHS = ImplicitCastExpr::Create(Context, LHS.get()->getType(),
+ CK_GetObjCProperty, LHS.take(), 0, VK);
return;
}
}
@@ -7616,11 +8178,9 @@ void Sema::ConvertPropertyForLValue(Expr *&LHS, Expr *&RHS, QualType &LHSTy) {
if (getLangOptions().CPlusPlus && LHSTy->isRecordType()) {
InitializedEntity Entity =
InitializedEntity::InitializeParameter(Context, LHSTy);
- Expr *Arg = RHS;
- ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(),
- Owned(Arg));
+ ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), RHS);
if (!ArgE.isInvalid())
- RHS = ArgE.takeAs<Expr>();
+ RHS = ArgE;
}
}
@@ -7695,10 +8255,15 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp,
return S.Context.DependentTy;
if (OrigOp->getType() == S.Context.OverloadTy)
return S.Context.OverloadTy;
+ if (OrigOp->getType() == S.Context.UnknownAnyTy)
+ return S.Context.UnknownAnyTy;
+ if (OrigOp->getType() == S.Context.BoundMemberTy) {
+ S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+ << OrigOp->getSourceRange();
+ return QualType();
+ }
- ExprResult PR = S.CheckPlaceholderExpr(OrigOp, OpLoc);
- if (PR.isInvalid()) return QualType();
- OrigOp = PR.take();
+ assert(!OrigOp->getType()->isPlaceholderType());
// Make sure to ignore parentheses in subsequent checks
Expr *op = OrigOp->IgnoreParens();
@@ -7717,7 +8282,7 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp,
ValueDecl *dcl = getPrimaryDecl(op);
Expr::LValueClassification lval = op->ClassifyLValue(S.Context);
- if (lval == Expr::LV_ClassTemporary) {
+ if (lval == Expr::LV_ClassTemporary) {
bool sfinae = S.isSFINAEContext();
S.Diag(OpLoc, sfinae ? diag::err_typecheck_addrof_class_temporary
: diag::ext_typecheck_addrof_class_temporary)
@@ -7833,7 +8398,10 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
if (Op->isTypeDependent())
return S.Context.DependentTy;
- S.UsualUnaryConversions(Op);
+ ExprResult ConvResult = S.UsualUnaryConversions(Op);
+ if (ConvResult.isInvalid())
+ return QualType();
+ Op = ConvResult.take();
QualType OpTy = Op->getType();
QualType Result;
@@ -7847,7 +8415,7 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
OpTy->getAs<ObjCObjectPointerType>())
Result = OPT->getPointeeType();
else {
- ExprResult PR = S.CheckPlaceholderExpr(Op, OpLoc);
+ ExprResult PR = S.CheckPlaceholderExpr(Op);
if (PR.isInvalid()) return QualType();
if (PR.take() != Op)
return CheckIndirectionOperand(S, PR.take(), VK, OpLoc);
@@ -7970,7 +8538,8 @@ static void DiagnoseSelfAssignment(Sema &S, Expr *lhs, Expr *rhs,
/// built-in operations; ActOnBinOp handles overloaded operators.
ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
BinaryOperatorKind Opc,
- Expr *lhs, Expr *rhs) {
+ Expr *lhsExpr, Expr *rhsExpr) {
+ ExprResult lhs = Owned(lhsExpr), rhs = Owned(rhsExpr);
QualType ResultTy; // Result type of the binary operator.
// The following two variables are used for compound assignment operators
QualType CompLHSTy; // Type of LHS after promotions for computation
@@ -7978,16 +8547,33 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
+ // Check if a 'foo<int>' involved in a binary op, identifies a single
+ // function unambiguously (i.e. an lvalue ala 13.4)
+ // But since an assignment can trigger target based overload, exclude it in
+ // our blind search. i.e:
+ // template<class T> void f(); template<class T, class U> void f(U);
+ // f<int> == 0; // resolve f<int> blindly
+ // void (*p)(int); p = f<int>; // resolve f<int> using target
+ if (Opc != BO_Assign) {
+ ExprResult resolvedLHS = CheckPlaceholderExpr(lhs.get());
+ if (!resolvedLHS.isUsable()) return ExprError();
+ lhs = move(resolvedLHS);
+
+ ExprResult resolvedRHS = CheckPlaceholderExpr(rhs.get());
+ if (!resolvedRHS.isUsable()) return ExprError();
+ rhs = move(resolvedRHS);
+ }
+
switch (Opc) {
case BO_Assign:
- ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, QualType());
+ ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, QualType());
if (getLangOptions().CPlusPlus &&
- lhs->getObjectKind() != OK_ObjCProperty) {
- VK = lhs->getValueKind();
- OK = lhs->getObjectKind();
+ lhs.get()->getObjectKind() != OK_ObjCProperty) {
+ VK = lhs.get()->getValueKind();
+ OK = lhs.get()->getObjectKind();
}
if (!ResultTy.isNull())
- DiagnoseSelfAssignment(*this, lhs, rhs, OpLoc);
+ DiagnoseSelfAssignment(*this, lhs.get(), rhs.get(), OpLoc);
break;
case BO_PtrMemD:
case BO_PtrMemI:
@@ -8036,60 +8622,59 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
CompResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true,
Opc == BO_DivAssign);
CompLHSTy = CompResultTy;
- if (!CompResultTy.isNull())
- ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+ if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid())
+ ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy);
break;
case BO_RemAssign:
CompResultTy = CheckRemainderOperands(lhs, rhs, OpLoc, true);
CompLHSTy = CompResultTy;
- if (!CompResultTy.isNull())
- ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+ if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid())
+ ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy);
break;
case BO_AddAssign:
CompResultTy = CheckAdditionOperands(lhs, rhs, OpLoc, &CompLHSTy);
- if (!CompResultTy.isNull())
- ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+ if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid())
+ ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy);
break;
case BO_SubAssign:
CompResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc, &CompLHSTy);
- if (!CompResultTy.isNull())
- ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+ if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid())
+ ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy);
break;
case BO_ShlAssign:
case BO_ShrAssign:
CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, Opc, true);
CompLHSTy = CompResultTy;
- if (!CompResultTy.isNull())
- ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+ if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid())
+ ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy);
break;
case BO_AndAssign:
case BO_XorAssign:
case BO_OrAssign:
CompResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc, true);
CompLHSTy = CompResultTy;
- if (!CompResultTy.isNull())
- ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+ if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid())
+ ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy);
break;
case BO_Comma:
ResultTy = CheckCommaOperands(*this, lhs, rhs, OpLoc);
- if (getLangOptions().CPlusPlus) {
- VK = rhs->getValueKind();
- OK = rhs->getObjectKind();
+ if (getLangOptions().CPlusPlus && !rhs.isInvalid()) {
+ VK = rhs.get()->getValueKind();
+ OK = rhs.get()->getObjectKind();
}
break;
}
- if (ResultTy.isNull())
+ if (ResultTy.isNull() || lhs.isInvalid() || rhs.isInvalid())
return ExprError();
if (CompResultTy.isNull())
- return Owned(new (Context) BinaryOperator(lhs, rhs, Opc, ResultTy,
- VK, OK, OpLoc));
-
- if (getLangOptions().CPlusPlus && lhs->getObjectKind() != OK_ObjCProperty) {
+ return Owned(new (Context) BinaryOperator(lhs.take(), rhs.take(), Opc,
+ ResultTy, VK, OK, OpLoc));
+ if (getLangOptions().CPlusPlus && lhs.get()->getObjectKind() != OK_ObjCProperty) {
VK = VK_LValue;
- OK = lhs->getObjectKind();
+ OK = lhs.get()->getObjectKind();
}
- return Owned(new (Context) CompoundAssignOperator(lhs, rhs, Opc, ResultTy,
- VK, OK, CompLHSTy,
+ return Owned(new (Context) CompoundAssignOperator(lhs.take(), rhs.take(), Opc,
+ ResultTy, VK, OK, CompLHSTy,
CompResultTy, OpLoc));
}
@@ -8161,23 +8746,23 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
Self.PDiag(diag::warn_precedence_bitwise_rel)
<< SourceRange(lhs->getLocStart(), OpLoc)
<< BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(lhsopc),
- Self.PDiag(diag::note_precedence_bitwise_first)
- << BinOp::getOpcodeStr(Opc),
- SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd()),
Self.PDiag(diag::note_precedence_bitwise_silence)
<< BinOp::getOpcodeStr(lhsopc),
- lhs->getSourceRange());
+ lhs->getSourceRange(),
+ Self.PDiag(diag::note_precedence_bitwise_first)
+ << BinOp::getOpcodeStr(Opc),
+ SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd()));
else if (BinOp::isComparisonOp(rhsopc))
SuggestParentheses(Self, OpLoc,
Self.PDiag(diag::warn_precedence_bitwise_rel)
<< SourceRange(OpLoc, rhs->getLocEnd())
<< BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(rhsopc),
+ Self.PDiag(diag::note_precedence_bitwise_silence)
+ << BinOp::getOpcodeStr(rhsopc),
+ rhs->getSourceRange(),
Self.PDiag(diag::note_precedence_bitwise_first)
<< BinOp::getOpcodeStr(Opc),
- SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart()),
- Self.PDiag(diag::note_precedence_bitwise_silence)
- << BinOp::getOpcodeStr(rhsopc),
- rhs->getSourceRange());
+ SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart()));
}
/// \brief It accepts a '&&' expr that is inside a '||' one.
@@ -8185,14 +8770,13 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
/// in parentheses.
static void
EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc,
- Expr *E) {
- assert(isa<BinaryOperator>(E) &&
- cast<BinaryOperator>(E)->getOpcode() == BO_LAnd);
- SuggestParentheses(Self, OpLoc,
+ BinaryOperator *Bop) {
+ assert(Bop->getOpcode() == BO_LAnd);
+ SuggestParentheses(Self, Bop->getOperatorLoc(),
Self.PDiag(diag::warn_logical_and_in_logical_or)
- << E->getSourceRange(),
+ << Bop->getSourceRange() << OpLoc,
Self.PDiag(diag::note_logical_and_in_logical_or_silence),
- E->getSourceRange(),
+ Bop->getSourceRange(),
Self.PDiag(0), SourceRange());
}
@@ -8316,7 +8900,8 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
UnaryOperatorKind Opc,
- Expr *Input) {
+ Expr *InputExpr) {
+ ExprResult Input = Owned(InputExpr);
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
QualType resultType;
@@ -8325,23 +8910,28 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
case UO_PreDec:
case UO_PostInc:
case UO_PostDec:
- resultType = CheckIncrementDecrementOperand(*this, Input, VK, OpLoc,
+ resultType = CheckIncrementDecrementOperand(*this, Input.get(), VK, OpLoc,
Opc == UO_PreInc ||
Opc == UO_PostInc,
Opc == UO_PreInc ||
Opc == UO_PreDec);
break;
case UO_AddrOf:
- resultType = CheckAddressOfOperand(*this, Input, OpLoc);
+ resultType = CheckAddressOfOperand(*this, Input.get(), OpLoc);
break;
- case UO_Deref:
- DefaultFunctionArrayLvalueConversion(Input);
- resultType = CheckIndirectionOperand(*this, Input, VK, OpLoc);
+ case UO_Deref: {
+ ExprResult resolved = CheckPlaceholderExpr(Input.get());
+ if (!resolved.isUsable()) return ExprError();
+ Input = move(resolved);
+ Input = DefaultFunctionArrayLvalueConversion(Input.take());
+ resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc);
break;
+ }
case UO_Plus:
case UO_Minus:
- UsualUnaryConversions(Input);
- resultType = Input->getType();
+ Input = UsualUnaryConversions(Input.take());
+ if (Input.isInvalid()) return ExprError();
+ resultType = Input.get()->getType();
if (resultType->isDependentType())
break;
if (resultType->isArithmeticType() || // C99 6.5.3.3p1
@@ -8355,49 +8945,59 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
resultType->isPointerType())
break;
else if (resultType->isPlaceholderType()) {
- ExprResult PR = CheckPlaceholderExpr(Input, OpLoc);
- if (PR.isInvalid()) return ExprError();
- return CreateBuiltinUnaryOp(OpLoc, Opc, PR.take());
+ Input = CheckPlaceholderExpr(Input.take());
+ if (Input.isInvalid()) return ExprError();
+ return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take());
}
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
- << resultType << Input->getSourceRange());
+ << resultType << Input.get()->getSourceRange());
+
case UO_Not: // bitwise complement
- UsualUnaryConversions(Input);
- resultType = Input->getType();
+ Input = UsualUnaryConversions(Input.take());
+ if (Input.isInvalid()) return ExprError();
+ resultType = Input.get()->getType();
if (resultType->isDependentType())
break;
// C99 6.5.3.3p1. We allow complex int and float as a GCC extension.
if (resultType->isComplexType() || resultType->isComplexIntegerType())
// C99 does not support '~' for complex conjugation.
Diag(OpLoc, diag::ext_integer_complement_complex)
- << resultType << Input->getSourceRange();
+ << resultType << Input.get()->getSourceRange();
else if (resultType->hasIntegerRepresentation())
break;
else if (resultType->isPlaceholderType()) {
- ExprResult PR = CheckPlaceholderExpr(Input, OpLoc);
- if (PR.isInvalid()) return ExprError();
- return CreateBuiltinUnaryOp(OpLoc, Opc, PR.take());
+ Input = CheckPlaceholderExpr(Input.take());
+ if (Input.isInvalid()) return ExprError();
+ return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take());
} else {
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
- << resultType << Input->getSourceRange());
+ << resultType << Input.get()->getSourceRange());
}
break;
+
case UO_LNot: // logical negation
// Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
- DefaultFunctionArrayLvalueConversion(Input);
- resultType = Input->getType();
+ Input = DefaultFunctionArrayLvalueConversion(Input.take());
+ if (Input.isInvalid()) return ExprError();
+ resultType = Input.get()->getType();
if (resultType->isDependentType())
break;
- if (resultType->isScalarType()) { // C99 6.5.3.3p1
- // ok, fallthrough
+ if (resultType->isScalarType()) {
+ // C99 6.5.3.3p1: ok, fallthrough;
+ if (Context.getLangOptions().CPlusPlus) {
+ // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9:
+ // operand contextually converted to bool.
+ Input = ImpCastExprToType(Input.take(), Context.BoolTy,
+ ScalarTypeToBooleanCastKind(resultType));
+ }
} else if (resultType->isPlaceholderType()) {
- ExprResult PR = CheckPlaceholderExpr(Input, OpLoc);
- if (PR.isInvalid()) return ExprError();
- return CreateBuiltinUnaryOp(OpLoc, Opc, PR.take());
+ Input = CheckPlaceholderExpr(Input.take());
+ if (Input.isInvalid()) return ExprError();
+ return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take());
} else {
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
- << resultType << Input->getSourceRange());
+ << resultType << Input.get()->getSourceRange());
}
// LNot always has type int. C99 6.5.3.3p5.
@@ -8408,20 +9008,21 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
case UO_Imag:
resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real);
// _Real and _Imag map ordinary l-values into ordinary l-values.
- if (Input->getValueKind() != VK_RValue &&
- Input->getObjectKind() == OK_Ordinary)
- VK = Input->getValueKind();
+ if (Input.isInvalid()) return ExprError();
+ if (Input.get()->getValueKind() != VK_RValue &&
+ Input.get()->getObjectKind() == OK_Ordinary)
+ VK = Input.get()->getValueKind();
break;
case UO_Extension:
- resultType = Input->getType();
- VK = Input->getValueKind();
- OK = Input->getObjectKind();
+ resultType = Input.get()->getType();
+ VK = Input.get()->getValueKind();
+ OK = Input.get()->getObjectKind();
break;
}
- if (resultType.isNull())
+ if (resultType.isNull() || Input.isInvalid())
return ExprError();
- return Owned(new (Context) UnaryOperator(Input, Opc, resultType,
+ return Owned(new (Context) UnaryOperator(Input.take(), Opc, resultType,
VK, OK, OpLoc));
}
@@ -8488,26 +9089,28 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
LastLabelStmt = Label;
LastStmt = Label->getSubStmt();
}
- if (Expr *LastExpr = dyn_cast<Expr>(LastStmt)) {
+ if (Expr *LastE = dyn_cast<Expr>(LastStmt)) {
// Do function/array conversion on the last expression, but not
// lvalue-to-rvalue. However, initialize an unqualified type.
- DefaultFunctionArrayConversion(LastExpr);
- Ty = LastExpr->getType().getUnqualifiedType();
+ ExprResult LastExpr = DefaultFunctionArrayConversion(LastE);
+ if (LastExpr.isInvalid())
+ return ExprError();
+ Ty = LastExpr.get()->getType().getUnqualifiedType();
- if (!Ty->isDependentType() && !LastExpr->isTypeDependent()) {
- ExprResult Res = PerformCopyInitialization(
+ if (!Ty->isDependentType() && !LastExpr.get()->isTypeDependent()) {
+ LastExpr = PerformCopyInitialization(
InitializedEntity::InitializeResult(LPLoc,
Ty,
false),
SourceLocation(),
- Owned(LastExpr));
- if (Res.isInvalid())
+ LastExpr);
+ if (LastExpr.isInvalid())
return ExprError();
- if ((LastExpr = Res.takeAs<Expr>())) {
+ if (LastExpr.get() != 0) {
if (!LastLabelStmt)
- Compound->setLastStmt(LastExpr);
+ Compound->setLastStmt(LastExpr.take());
else
- LastLabelStmt->setSubStmt(LastExpr);
+ LastLabelStmt->setSubStmt(LastExpr.take());
StmtExprMayBindToTemp = true;
}
}
@@ -8779,8 +9382,8 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
// Check whether that explicit signature was synthesized by
// GetTypeForDeclarator. If so, don't save that as part of the
// written signature.
- if (ExplicitSignature.getLParenLoc() ==
- ExplicitSignature.getRParenLoc()) {
+ if (ExplicitSignature.getLocalRangeBegin() ==
+ ExplicitSignature.getLocalRangeEnd()) {
// This would be much cheaper if we stored TypeLocs instead of
// TypeSourceInfos.
TypeLoc Result = ExplicitSignature.getResultLoc();
@@ -8942,7 +9545,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
// If we don't have a function type, just build one from nothing.
} else {
FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExtInfo = FunctionType::ExtInfo(NoReturn, 0, CC_Default);
+ EPI.ExtInfo = FunctionType::ExtInfo(NoReturn, false, 0, CC_Default);
BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI);
}
@@ -8984,7 +9587,10 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
// a pointer for va_arg.
VaListType = Context.getArrayDecayedType(VaListType);
// Make sure the input expression also decays appropriately.
- UsualUnaryConversions(E);
+ ExprResult Result = UsualUnaryConversions(E);
+ if (Result.isInvalid())
+ return ExprError();
+ E = Result.take();
} else {
// Otherwise, the va_list argument must be an l-value because
// it is modified by va_arg.
@@ -9260,6 +9866,8 @@ Sema::PopExpressionEvaluationContext() {
void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
assert(D && "No declaration?");
+ D->setReferenced();
+
if (D->isUsed(false))
return;
@@ -9393,6 +10001,9 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (MSInfo->getPointOfInstantiation().isInvalid() &&
MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) {
MSInfo->setPointOfInstantiation(Loc);
+ // This is a modification of an existing AST node. Notify listeners.
+ if (ASTMutationListener *L = getASTMutationListener())
+ L->StaticDataMemberInstantiated(Var);
PendingInstantiations.push_back(std::make_pair(Var, Loc));
}
}
@@ -9624,10 +10235,13 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
return;
}
+ Diag(Loc, diagnostic) << E->getSourceRange();
+
SourceLocation Open = E->getSourceRange().getBegin();
SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd());
-
- Diag(Loc, diagnostic) << E->getSourceRange();
+ Diag(Loc, diag::note_condition_assign_silence)
+ << FixItHint::CreateInsertion(Open, "(")
+ << FixItHint::CreateInsertion(Close, ")");
if (IsOrAssign)
Diag(Loc, diag::note_condition_or_assign_to_comparison)
@@ -9635,10 +10249,6 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
else
Diag(Loc, diag::note_condition_assign_to_comparison)
<< FixItHint::CreateReplacement(Loc, "==");
-
- Diag(Loc, diag::note_condition_assign_silence)
- << FixItHint::CreateInsertion(Open, "(")
- << FixItHint::CreateInsertion(Close, ")");
}
/// \brief Redundant parentheses over an equality comparison can indicate
@@ -9648,6 +10258,9 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *parenE) {
SourceLocation parenLoc = parenE->getLocStart();
if (parenLoc.isInvalid() || parenLoc.isMacroID())
return;
+ // Don't warn for dependent expressions.
+ if (parenE->isTypeDependent())
+ return;
Expr *E = parenE->IgnoreParens();
@@ -9658,68 +10271,467 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *parenE) {
SourceLocation Loc = opE->getOperatorLoc();
Diag(Loc, diag::warn_equality_with_extra_parens) << E->getSourceRange();
- Diag(Loc, diag::note_equality_comparison_to_assign)
- << FixItHint::CreateReplacement(Loc, "=");
Diag(Loc, diag::note_equality_comparison_silence)
<< FixItHint::CreateRemoval(parenE->getSourceRange().getBegin())
<< FixItHint::CreateRemoval(parenE->getSourceRange().getEnd());
+ Diag(Loc, diag::note_equality_comparison_to_assign)
+ << FixItHint::CreateReplacement(Loc, "=");
}
}
-bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) {
+ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) {
DiagnoseAssignmentAsCondition(E);
if (ParenExpr *parenE = dyn_cast<ParenExpr>(E))
DiagnoseEqualityWithExtraParens(parenE);
- if (!E->isTypeDependent()) {
- if (E->isBoundMemberFunction(Context))
- return Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
- << E->getSourceRange();
+ ExprResult result = CheckPlaceholderExpr(E);
+ if (result.isInvalid()) return ExprError();
+ E = result.take();
+ if (!E->isTypeDependent()) {
if (getLangOptions().CPlusPlus)
return CheckCXXBooleanCondition(E); // C++ 6.4p4
- DefaultFunctionArrayLvalueConversion(E);
+ ExprResult ERes = DefaultFunctionArrayLvalueConversion(E);
+ if (ERes.isInvalid())
+ return ExprError();
+ E = ERes.take();
QualType T = E->getType();
- if (!T->isScalarType()) // C99 6.8.4.1p1
- return Diag(Loc, diag::err_typecheck_statement_requires_scalar)
- << T << E->getSourceRange();
+ if (!T->isScalarType()) { // C99 6.8.4.1p1
+ Diag(Loc, diag::err_typecheck_statement_requires_scalar)
+ << T << E->getSourceRange();
+ return ExprError();
+ }
}
- return false;
+ return Owned(E);
}
ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc,
Expr *Sub) {
if (!Sub)
return ExprError();
-
- if (CheckBooleanCondition(Sub, Loc))
+
+ return CheckBooleanCondition(Sub, Loc);
+}
+
+namespace {
+ /// A visitor for rebuilding a call to an __unknown_any expression
+ /// to have an appropriate type.
+ struct RebuildUnknownAnyFunction
+ : StmtVisitor<RebuildUnknownAnyFunction, ExprResult> {
+
+ Sema &S;
+
+ RebuildUnknownAnyFunction(Sema &S) : S(S) {}
+
+ ExprResult VisitStmt(Stmt *S) {
+ llvm_unreachable("unexpected statement!");
+ return ExprError();
+ }
+
+ ExprResult VisitExpr(Expr *expr) {
+ S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_call)
+ << expr->getSourceRange();
+ return ExprError();
+ }
+
+ /// Rebuild an expression which simply semantically wraps another
+ /// expression which it shares the type and value kind of.
+ template <class T> ExprResult rebuildSugarExpr(T *expr) {
+ ExprResult subResult = Visit(expr->getSubExpr());
+ if (subResult.isInvalid()) return ExprError();
+
+ Expr *subExpr = subResult.take();
+ expr->setSubExpr(subExpr);
+ expr->setType(subExpr->getType());
+ expr->setValueKind(subExpr->getValueKind());
+ assert(expr->getObjectKind() == OK_Ordinary);
+ return expr;
+ }
+
+ ExprResult VisitParenExpr(ParenExpr *paren) {
+ return rebuildSugarExpr(paren);
+ }
+
+ ExprResult VisitUnaryExtension(UnaryOperator *op) {
+ return rebuildSugarExpr(op);
+ }
+
+ ExprResult VisitUnaryAddrOf(UnaryOperator *op) {
+ ExprResult subResult = Visit(op->getSubExpr());
+ if (subResult.isInvalid()) return ExprError();
+
+ Expr *subExpr = subResult.take();
+ op->setSubExpr(subExpr);
+ op->setType(S.Context.getPointerType(subExpr->getType()));
+ assert(op->getValueKind() == VK_RValue);
+ assert(op->getObjectKind() == OK_Ordinary);
+ return op;
+ }
+
+ ExprResult resolveDecl(Expr *expr, ValueDecl *decl) {
+ if (!isa<FunctionDecl>(decl)) return VisitExpr(expr);
+
+ expr->setType(decl->getType());
+
+ assert(expr->getValueKind() == VK_RValue);
+ if (S.getLangOptions().CPlusPlus &&
+ !(isa<CXXMethodDecl>(decl) &&
+ cast<CXXMethodDecl>(decl)->isInstance()))
+ expr->setValueKind(VK_LValue);
+
+ return expr;
+ }
+
+ ExprResult VisitMemberExpr(MemberExpr *mem) {
+ return resolveDecl(mem, mem->getMemberDecl());
+ }
+
+ ExprResult VisitDeclRefExpr(DeclRefExpr *ref) {
+ return resolveDecl(ref, ref->getDecl());
+ }
+ };
+}
+
+/// Given a function expression of unknown-any type, try to rebuild it
+/// to have a function type.
+static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn) {
+ ExprResult result = RebuildUnknownAnyFunction(S).Visit(fn);
+ if (result.isInvalid()) return ExprError();
+ return S.DefaultFunctionArrayConversion(result.take());
+}
+
+namespace {
+ /// A visitor for rebuilding an expression of type __unknown_anytype
+ /// into one which resolves the type directly on the referring
+ /// expression. Strict preservation of the original source
+ /// structure is not a goal.
+ struct RebuildUnknownAnyExpr
+ : StmtVisitor<RebuildUnknownAnyExpr, ExprResult> {
+
+ Sema &S;
+
+ /// The current destination type.
+ QualType DestType;
+
+ RebuildUnknownAnyExpr(Sema &S, QualType castType)
+ : S(S), DestType(castType) {}
+
+ ExprResult VisitStmt(Stmt *S) {
+ llvm_unreachable("unexpected statement!");
+ return ExprError();
+ }
+
+ ExprResult VisitExpr(Expr *expr) {
+ S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_expr)
+ << expr->getSourceRange();
+ return ExprError();
+ }
+
+ ExprResult VisitCallExpr(CallExpr *call);
+ ExprResult VisitObjCMessageExpr(ObjCMessageExpr *message);
+
+ /// Rebuild an expression which simply semantically wraps another
+ /// expression which it shares the type and value kind of.
+ template <class T> ExprResult rebuildSugarExpr(T *expr) {
+ ExprResult subResult = Visit(expr->getSubExpr());
+ if (subResult.isInvalid()) return ExprError();
+ Expr *subExpr = subResult.take();
+ expr->setSubExpr(subExpr);
+ expr->setType(subExpr->getType());
+ expr->setValueKind(subExpr->getValueKind());
+ assert(expr->getObjectKind() == OK_Ordinary);
+ return expr;
+ }
+
+ ExprResult VisitParenExpr(ParenExpr *paren) {
+ return rebuildSugarExpr(paren);
+ }
+
+ ExprResult VisitUnaryExtension(UnaryOperator *op) {
+ return rebuildSugarExpr(op);
+ }
+
+ ExprResult VisitUnaryAddrOf(UnaryOperator *op) {
+ const PointerType *ptr = DestType->getAs<PointerType>();
+ if (!ptr) {
+ S.Diag(op->getOperatorLoc(), diag::err_unknown_any_addrof)
+ << op->getSourceRange();
+ return ExprError();
+ }
+ assert(op->getValueKind() == VK_RValue);
+ assert(op->getObjectKind() == OK_Ordinary);
+ op->setType(DestType);
+
+ // Build the sub-expression as if it were an object of the pointee type.
+ DestType = ptr->getPointeeType();
+ ExprResult subResult = Visit(op->getSubExpr());
+ if (subResult.isInvalid()) return ExprError();
+ op->setSubExpr(subResult.take());
+ return op;
+ }
+
+ ExprResult VisitImplicitCastExpr(ImplicitCastExpr *ice);
+
+ ExprResult resolveDecl(Expr *expr, ValueDecl *decl);
+
+ ExprResult VisitMemberExpr(MemberExpr *mem) {
+ return resolveDecl(mem, mem->getMemberDecl());
+ }
+
+ ExprResult VisitDeclRefExpr(DeclRefExpr *ref) {
+ return resolveDecl(ref, ref->getDecl());
+ }
+ };
+}
+
+/// Rebuilds a call expression which yielded __unknown_anytype.
+ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *call) {
+ Expr *callee = call->getCallee();
+
+ enum FnKind {
+ FK_MemberFunction,
+ FK_FunctionPointer,
+ FK_BlockPointer
+ };
+
+ FnKind kind;
+ QualType type = callee->getType();
+ if (type == S.Context.BoundMemberTy) {
+ assert(isa<CXXMemberCallExpr>(call) || isa<CXXOperatorCallExpr>(call));
+ kind = FK_MemberFunction;
+ type = Expr::findBoundMemberType(callee);
+ } else if (const PointerType *ptr = type->getAs<PointerType>()) {
+ type = ptr->getPointeeType();
+ kind = FK_FunctionPointer;
+ } else {
+ type = type->castAs<BlockPointerType>()->getPointeeType();
+ kind = FK_BlockPointer;
+ }
+ const FunctionType *fnType = type->castAs<FunctionType>();
+
+ // Verify that this is a legal result type of a function.
+ if (DestType->isArrayType() || DestType->isFunctionType()) {
+ unsigned diagID = diag::err_func_returning_array_function;
+ if (kind == FK_BlockPointer)
+ diagID = diag::err_block_returning_array_function;
+
+ S.Diag(call->getExprLoc(), diagID)
+ << DestType->isFunctionType() << DestType;
return ExprError();
-
- return Owned(Sub);
+ }
+
+ // Otherwise, go ahead and set DestType as the call's result.
+ call->setType(DestType.getNonLValueExprType(S.Context));
+ call->setValueKind(Expr::getValueKindForType(DestType));
+ assert(call->getObjectKind() == OK_Ordinary);
+
+ // Rebuild the function type, replacing the result type with DestType.
+ if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType))
+ DestType = S.Context.getFunctionType(DestType,
+ proto->arg_type_begin(),
+ proto->getNumArgs(),
+ proto->getExtProtoInfo());
+ else
+ DestType = S.Context.getFunctionNoProtoType(DestType,
+ fnType->getExtInfo());
+
+ // Rebuild the appropriate pointer-to-function type.
+ switch (kind) {
+ case FK_MemberFunction:
+ // Nothing to do.
+ break;
+
+ case FK_FunctionPointer:
+ DestType = S.Context.getPointerType(DestType);
+ break;
+
+ case FK_BlockPointer:
+ DestType = S.Context.getBlockPointerType(DestType);
+ break;
+ }
+
+ // Finally, we can recurse.
+ ExprResult calleeResult = Visit(callee);
+ if (!calleeResult.isUsable()) return ExprError();
+ call->setCallee(calleeResult.take());
+
+ // Bind a temporary if necessary.
+ return S.MaybeBindToTemporary(call);
}
-/// Check for operands with placeholder types and complain if found.
-/// Returns true if there was an error and no recovery was possible.
-ExprResult Sema::CheckPlaceholderExpr(Expr *E, SourceLocation Loc) {
- const BuiltinType *BT = E->getType()->getAs<BuiltinType>();
- if (!BT || !BT->isPlaceholderType()) return Owned(E);
-
- // If this is overload, check for a single overload.
- assert(BT->getKind() == BuiltinType::Overload);
-
- if (FunctionDecl *Specialization
- = ResolveSingleFunctionTemplateSpecialization(E)) {
- // The access doesn't really matter in this case.
- DeclAccessPair Found = DeclAccessPair::make(Specialization,
- Specialization->getAccess());
- E = FixOverloadedFunctionReference(E, Found, Specialization);
- if (!E) return ExprError();
- return Owned(E);
+ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *msg) {
+ ObjCMethodDecl *method = msg->getMethodDecl();
+ assert(method && "__unknown_anytype message without result type?");
+
+ // Verify that this is a legal result type of a call.
+ if (DestType->isArrayType() || DestType->isFunctionType()) {
+ S.Diag(msg->getExprLoc(), diag::err_func_returning_array_function)
+ << DestType->isFunctionType() << DestType;
+ return ExprError();
}
- Diag(Loc, diag::err_ovl_unresolvable) << E->getSourceRange();
+ assert(method->getResultType() == S.Context.UnknownAnyTy);
+ method->setResultType(DestType);
+
+ // Change the type of the message.
+ msg->setType(DestType.getNonReferenceType());
+ msg->setValueKind(Expr::getValueKindForType(DestType));
+
+ return S.MaybeBindToTemporary(msg);
+}
+
+ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *ice) {
+ // The only case we should ever see here is a function-to-pointer decay.
+ assert(ice->getCastKind() == CK_FunctionToPointerDecay);
+ assert(ice->getValueKind() == VK_RValue);
+ assert(ice->getObjectKind() == OK_Ordinary);
+
+ ice->setType(DestType);
+
+ // Rebuild the sub-expression as the pointee (function) type.
+ DestType = DestType->castAs<PointerType>()->getPointeeType();
+
+ ExprResult result = Visit(ice->getSubExpr());
+ if (!result.isUsable()) return ExprError();
+
+ ice->setSubExpr(result.take());
+ return S.Owned(ice);
+}
+
+ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, ValueDecl *decl) {
+ ExprValueKind valueKind = VK_LValue;
+ QualType type = DestType;
+
+ // We know how to make this work for certain kinds of decls:
+
+ // - functions
+ if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
+ // This is true because FunctionDecls must always have function
+ // type, so we can't be resolving the entire thing at once.
+ assert(type->isFunctionType());
+
+ if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(fn))
+ if (method->isInstance()) {
+ valueKind = VK_RValue;
+ type = S.Context.BoundMemberTy;
+ }
+
+ // Function references aren't l-values in C.
+ if (!S.getLangOptions().CPlusPlus)
+ valueKind = VK_RValue;
+
+ // - variables
+ } else if (isa<VarDecl>(decl)) {
+ if (const ReferenceType *refTy = type->getAs<ReferenceType>()) {
+ type = refTy->getPointeeType();
+ } else if (type->isFunctionType()) {
+ S.Diag(expr->getExprLoc(), diag::err_unknown_any_var_function_type)
+ << decl << expr->getSourceRange();
+ return ExprError();
+ }
+
+ // - nothing else
+ } else {
+ S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_decl)
+ << decl << expr->getSourceRange();
+ return ExprError();
+ }
+
+ decl->setType(DestType);
+ expr->setType(type);
+ expr->setValueKind(valueKind);
+ return S.Owned(expr);
+}
+
+/// Check a cast of an unknown-any type. We intentionally only
+/// trigger this for C-style casts.
+ExprResult Sema::checkUnknownAnyCast(SourceRange typeRange, QualType castType,
+ Expr *castExpr, CastKind &castKind,
+ ExprValueKind &VK, CXXCastPath &path) {
+ // Rewrite the casted expression from scratch.
+ ExprResult result = RebuildUnknownAnyExpr(*this, castType).Visit(castExpr);
+ if (!result.isUsable()) return ExprError();
+
+ castExpr = result.take();
+ VK = castExpr->getValueKind();
+ castKind = CK_NoOp;
+
+ return castExpr;
+}
+
+static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *e) {
+ Expr *orig = e;
+ unsigned diagID = diag::err_uncasted_use_of_unknown_any;
+ while (true) {
+ e = e->IgnoreParenImpCasts();
+ if (CallExpr *call = dyn_cast<CallExpr>(e)) {
+ e = call->getCallee();
+ diagID = diag::err_uncasted_call_of_unknown_any;
+ } else {
+ break;
+ }
+ }
+
+ SourceLocation loc;
+ NamedDecl *d;
+ if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) {
+ loc = ref->getLocation();
+ d = ref->getDecl();
+ } else if (MemberExpr *mem = dyn_cast<MemberExpr>(e)) {
+ loc = mem->getMemberLoc();
+ d = mem->getMemberDecl();
+ } else if (ObjCMessageExpr *msg = dyn_cast<ObjCMessageExpr>(e)) {
+ diagID = diag::err_uncasted_call_of_unknown_any;
+ loc = msg->getSelectorLoc();
+ d = msg->getMethodDecl();
+ assert(d && "unknown method returning __unknown_any?");
+ } else {
+ S.Diag(e->getExprLoc(), diag::err_unsupported_unknown_any_expr)
+ << e->getSourceRange();
+ return ExprError();
+ }
+
+ S.Diag(loc, diagID) << d << orig->getSourceRange();
+
+ // Never recoverable.
return ExprError();
}
+
+/// Check for operands with placeholder types and complain if found.
+/// Returns true if there was an error and no recovery was possible.
+ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
+ // Placeholder types are always *exactly* the appropriate builtin type.
+ QualType type = E->getType();
+
+ // Overloaded expressions.
+ if (type == Context.OverloadTy)
+ return ResolveAndFixSingleFunctionTemplateSpecialization(E, false, true,
+ E->getSourceRange(),
+ QualType(),
+ diag::err_ovl_unresolvable);
+
+ // Bound member functions.
+ if (type == Context.BoundMemberTy) {
+ Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
+ << E->getSourceRange();
+ return ExprError();
+ }
+
+ // Expressions of unknown type.
+ if (type == Context.UnknownAnyTy)
+ return diagnoseUnknownAnyExpr(*this, E);
+
+ assert(!type->isPlaceholderType());
+ return Owned(E);
+}
+
+bool Sema::CheckCaseExpression(Expr *expr) {
+ if (expr->isTypeDependent())
+ return true;
+ if (expr->isValueDependent() || expr->isIntegerConstantExpr(Context))
+ return expr->getType()->isIntegralOrEnumerationType();
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
index 6dd7aab..7f1bf59 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
@@ -28,6 +28,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace clang;
using namespace sema;
@@ -138,10 +139,11 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
LookInScope = true;
}
+ TypeDecl *NonMatchingTypeDecl = 0;
LookupResult Found(*this, &II, NameLoc, LookupOrdinaryName);
for (unsigned Step = 0; Step != 2; ++Step) {
// Look for the name first in the computed lookup context (if we
- // have one) and, if that fails to find a match, in the sope (if
+ // have one) and, if that fails to find a match, in the scope (if
// we're allowed to look there).
Found.clear();
if (Step == 0 && LookupCtx)
@@ -164,6 +166,9 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
return ParsedType::make(T);
}
+
+ if (!SearchType.isNull())
+ NonMatchingTypeDecl = Type;
}
// If the name that we found is a class template name, and it is
@@ -236,24 +241,22 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
if (isDependent) {
// We didn't find our type, but that's okay: it's dependent
// anyway.
- NestedNameSpecifier *NNS = 0;
- SourceRange Range;
- if (SS.isSet()) {
- NNS = (NestedNameSpecifier *)SS.getScopeRep();
- Range = SourceRange(SS.getRange().getBegin(), NameLoc);
- } else {
- NNS = NestedNameSpecifier::Create(Context, &II);
- Range = SourceRange(NameLoc);
- }
-
- QualType T = CheckTypenameType(ETK_None, NNS, II,
- SourceLocation(),
- Range, NameLoc);
+
+ // FIXME: What if we have no nested-name-specifier?
+ QualType T = CheckTypenameType(ETK_None, SourceLocation(),
+ SS.getWithLocInContext(Context),
+ II, NameLoc);
return ParsedType::make(T);
}
- if (ObjectTypePtr)
- Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
+ if (NonMatchingTypeDecl) {
+ QualType T = Context.getTypeDeclType(NonMatchingTypeDecl);
+ Diag(NameLoc, diag::err_destructor_expr_type_mismatch)
+ << T << SearchType;
+ Diag(NonMatchingTypeDecl->getLocation(), diag::note_destructor_type_here)
+ << T;
+ } else if (ObjectTypePtr)
+ Diag(NameLoc, diag::err_ident_in_dtor_not_a_type)
<< &II;
else
Diag(NameLoc, diag::err_destructor_class_name);
@@ -321,7 +324,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals);
if (!Context.hasSameType(T, UnqualT)) {
T = UnqualT;
- ImpCastExprToType(E, UnqualT, CK_NoOp, CastCategory(E));
+ E = ImpCastExprToType(E, UnqualT, CK_NoOp, CastCategory(E)).take();
}
}
@@ -341,7 +344,7 @@ ExprResult
Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
// Find the std::type_info type.
- if (!StdNamespace)
+ if (!getStdNamespace())
return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));
if (!CXXTypeInfoDecl) {
@@ -477,17 +480,21 @@ Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) {
ExprResult
Sema::ActOnCXXThrow(SourceLocation OpLoc, Expr *Ex) {
// Don't report an error if 'throw' is used in system headers.
- if (!getLangOptions().Exceptions &&
+ if (!getLangOptions().CXXExceptions &&
!getSourceManager().isInSystemHeader(OpLoc))
Diag(OpLoc, diag::err_exceptions_disabled) << "throw";
- if (Ex && !Ex->isTypeDependent() && CheckCXXThrowOperand(OpLoc, Ex))
- return ExprError();
+ if (Ex && !Ex->isTypeDependent()) {
+ ExprResult ExRes = CheckCXXThrowOperand(OpLoc, Ex);
+ if (ExRes.isInvalid())
+ return ExprError();
+ Ex = ExRes.take();
+ }
return Owned(new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc));
}
/// CheckCXXThrowOperand - Validate the operand of a throw.
-bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
+ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E) {
// C++ [except.throw]p3:
// A throw-expression initializes a temporary object, called the exception
// object, the type of which is determined by removing any top-level
@@ -495,10 +502,13 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
// the type from "array of T" or "function returning T" to "pointer to T"
// or "pointer to function returning T", [...]
if (E->getType().hasQualifiers())
- ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp,
- CastCategory(E));
+ E = ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp,
+ CastCategory(E)).take();
- DefaultFunctionArrayConversion(E);
+ ExprResult Res = DefaultFunctionArrayConversion(E);
+ if (Res.isInvalid())
+ return ExprError();
+ E = Res.take();
// If the type of the exception would be an incomplete type or a pointer
// to an incomplete type other than (cv) void the program is ill-formed.
@@ -513,12 +523,12 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
PDiag(isPointer ? diag::err_throw_incomplete_ptr
: diag::err_throw_incomplete)
<< E->getSourceRange()))
- return true;
+ return ExprError();
if (RequireNonAbstractType(ThrowLoc, E->getType(),
PDiag(diag::err_throw_abstract_type)
<< E->getSourceRange()))
- return true;
+ return ExprError();
}
// Initialize the exception result. This implicitly weeds out
@@ -529,16 +539,16 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
InitializedEntity Entity =
InitializedEntity::InitializeException(ThrowLoc, E->getType(),
/*NRVO=*/false);
- ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable,
- QualType(), E);
+ Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable,
+ QualType(), E);
if (Res.isInvalid())
- return true;
- E = Res.takeAs<Expr>();
+ return ExprError();
+ E = Res.take();
// If the exception has class type, we need additional handling.
const RecordType *RecordTy = Ty->getAs<RecordType>();
if (!RecordTy)
- return false;
+ return Owned(E);
CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
// If we are throwing a polymorphic class type or pointer thereof,
@@ -547,21 +557,21 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
// If a pointer is thrown, the referenced object will not be destroyed.
if (isPointer)
- return false;
+ return Owned(E);
// If the class has a non-trivial destructor, we must be able to call it.
if (RD->hasTrivialDestructor())
- return false;
+ return Owned(E);
CXXDestructorDecl *Destructor
= const_cast<CXXDestructorDecl*>(LookupDestructor(RD));
if (!Destructor)
- return false;
+ return Owned(E);
MarkDeclarationReferenced(E->getExprLoc(), Destructor);
CheckDestructorAccess(E->getExprLoc(), Destructor,
PDiag(diag::err_access_dtor_exception) << Ty);
- return false;
+ return Owned(E);
}
CXXMethodDecl *Sema::tryCaptureCXXThis() {
@@ -666,10 +676,13 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
CastKind Kind = CK_Invalid;
ExprValueKind VK = VK_RValue;
CXXCastPath BasePath;
- if (CheckCastTypes(TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0],
- Kind, VK, BasePath,
- /*FunctionalStyle=*/true))
+ ExprResult CastExpr =
+ CheckCastTypes(TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0],
+ Kind, VK, BasePath,
+ /*FunctionalStyle=*/true);
+ if (CastExpr.isInvalid())
return ExprError();
+ Exprs[0] = CastExpr.take();
exprs.release();
@@ -846,16 +859,18 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
diag::err_auto_new_ctor_multiple_expressions)
<< AllocType << TypeRange);
}
- QualType DeducedType;
- if (!DeduceAutoType(AllocType, ConstructorArgs.get()[0], DeducedType))
+ TypeSourceInfo *DeducedType = 0;
+ if (!DeduceAutoType(AllocTypeInfo, ConstructorArgs.get()[0], DeducedType))
return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
<< AllocType
<< ConstructorArgs.get()[0]->getType()
<< TypeRange
<< ConstructorArgs.get()[0]->getSourceRange());
+ if (!DeducedType)
+ return ExprError();
- AllocType = DeducedType;
- AllocTypeInfo = Context.getTrivialTypeSourceInfo(AllocType, StartLoc);
+ AllocTypeInfo = DeducedType;
+ AllocType = AllocTypeInfo->getType();
}
// Per C++0x [expr.new]p5, the type being constructed may be a
@@ -935,8 +950,8 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
}
}
- ImpCastExprToType(ArraySize, Context.getSizeType(),
- CK_IntegralCast);
+ ArraySize = ImpCastExprToType(ArraySize, Context.getSizeType(),
+ CK_IntegralCast).take();
}
FunctionDecl *OperatorNew = 0;
@@ -1090,7 +1105,10 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
else if (AllocType->isVariablyModifiedType())
return Diag(Loc, diag::err_variably_modified_new_type)
<< AllocType;
-
+ else if (unsigned AddressSpace = AllocType.getAddressSpace())
+ return Diag(Loc, diag::err_address_space_qualified_new)
+ << AllocType.getUnqualifiedType() << AddressSpace;
+
return false;
}
@@ -1384,16 +1402,16 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs);
return true;
- case OR_Deleted:
+ case OR_Deleted: {
Diag(StartLoc, diag::err_ovl_deleted_call)
<< Best->Function->isDeleted()
<< Name
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< Range;
Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
return true;
}
+ }
assert(false && "Unreachable, bad result from BestViableFunction");
return true;
}
@@ -1402,11 +1420,18 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
/// DeclareGlobalNewDelete - Declare the global forms of operator new and
/// delete. These are:
/// @code
+/// // C++03:
/// void* operator new(std::size_t) throw(std::bad_alloc);
/// void* operator new[](std::size_t) throw(std::bad_alloc);
/// void operator delete(void *) throw();
/// void operator delete[](void *) throw();
+/// // C++0x:
+/// void* operator new(std::size_t);
+/// void* operator new[](std::size_t);
+/// void operator delete(void *);
+/// void operator delete[](void *);
/// @endcode
+/// C++0x operator delete is implicitly noexcept.
/// Note that the placement and nothrow forms of new are *not* implicitly
/// declared. Their use requires including \<new\>.
void Sema::DeclareGlobalNewDelete() {
@@ -1418,10 +1443,16 @@ void Sema::DeclareGlobalNewDelete() {
// implicitly declared in global scope in each translation unit of a
// program
//
+ // C++03:
// void* operator new(std::size_t) throw(std::bad_alloc);
// void* operator new[](std::size_t) throw(std::bad_alloc);
// void operator delete(void*) throw();
// void operator delete[](void*) throw();
+ // C++0x:
+ // void* operator new(std::size_t);
+ // void* operator new[](std::size_t);
+ // void operator delete(void*);
+ // void operator delete[](void*);
//
// These implicit declarations introduce only the function names operator
// new, operator new[], operator delete, operator delete[].
@@ -1430,14 +1461,16 @@ void Sema::DeclareGlobalNewDelete() {
// "std" or "bad_alloc" as necessary to form the exception specification.
// However, we do not make these implicit declarations visible to name
// lookup.
- if (!StdBadAlloc) {
+ // Note that the C++0x versions of operator delete are deallocation functions,
+ // and thus are implicitly noexcept.
+ if (!StdBadAlloc && !getLangOptions().CPlusPlus0x) {
// The "std::bad_alloc" class has not yet been declared, so build it
// implicitly.
StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class,
getOrCreateStdNamespace(),
- SourceLocation(),
+ SourceLocation(), SourceLocation(),
&PP.getIdentifierTable().get("bad_alloc"),
- SourceLocation(), 0);
+ 0);
getStdBadAlloc()->setImplicit(true);
}
@@ -1493,21 +1526,27 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
bool HasBadAllocExceptionSpec
= (Name.getCXXOverloadedOperator() == OO_New ||
Name.getCXXOverloadedOperator() == OO_Array_New);
- if (HasBadAllocExceptionSpec) {
+ if (HasBadAllocExceptionSpec && !getLangOptions().CPlusPlus0x) {
assert(StdBadAlloc && "Must have std::bad_alloc declared");
BadAllocType = Context.getTypeDeclType(getStdBadAlloc());
}
FunctionProtoType::ExtProtoInfo EPI;
- EPI.HasExceptionSpec = true;
if (HasBadAllocExceptionSpec) {
- EPI.NumExceptions = 1;
- EPI.Exceptions = &BadAllocType;
+ if (!getLangOptions().CPlusPlus0x) {
+ EPI.ExceptionSpecType = EST_Dynamic;
+ EPI.NumExceptions = 1;
+ EPI.Exceptions = &BadAllocType;
+ }
+ } else {
+ EPI.ExceptionSpecType = getLangOptions().CPlusPlus0x ?
+ EST_BasicNoexcept : EST_DynamicNone;
}
QualType FnType = Context.getFunctionType(Return, &Argument, 1, EPI);
FunctionDecl *Alloc =
- FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), Name,
+ FunctionDecl::Create(Context, GlobalCtx, SourceLocation(),
+ SourceLocation(), Name,
FnType, /*TInfo=*/0, SC_None,
SC_None, false, true);
Alloc->setImplicit();
@@ -1516,9 +1555,9 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
- 0, Argument, /*TInfo=*/0,
- SC_None,
- SC_None, 0);
+ SourceLocation(), 0,
+ Argument, /*TInfo=*/0,
+ SC_None, SC_None, 0);
Alloc->setParams(&Param, 1);
// FIXME: Also add this declaration to the IdentifierResolver, but
@@ -1608,19 +1647,20 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
/// @code delete [] ptr; @endcode
ExprResult
Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
- bool ArrayForm, Expr *Ex) {
+ bool ArrayForm, Expr *ExE) {
// C++ [expr.delete]p1:
// The operand shall have a pointer type, or a class type having a single
// conversion function to a pointer type. The result has type void.
//
// DR599 amends "pointer type" to "pointer to object type" in both cases.
+ ExprResult Ex = Owned(ExE);
FunctionDecl *OperatorDelete = 0;
bool ArrayFormAsWritten = ArrayForm;
bool UsualArrayDeleteWantsSize = false;
- if (!Ex->isTypeDependent()) {
- QualType Type = Ex->getType();
+ if (!Ex.get()->isTypeDependent()) {
+ QualType Type = Ex.get()->getType();
if (const RecordType *Record = Type->getAs<RecordType>()) {
if (RequireCompleteType(StartLoc, Type,
@@ -1652,15 +1692,18 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
// We have a single conversion to a pointer-to-object type. Perform
// that conversion.
// TODO: don't redo the conversion calculation.
- if (!PerformImplicitConversion(Ex,
+ ExprResult Res =
+ PerformImplicitConversion(Ex.get(),
ObjectPtrConversions.front()->getConversionType(),
- AA_Converting)) {
- Type = Ex->getType();
+ AA_Converting);
+ if (Res.isUsable()) {
+ Ex = move(Res);
+ Type = Ex.get()->getType();
}
}
else if (ObjectPtrConversions.size() > 1) {
Diag(StartLoc, diag::err_ambiguous_delete_operand)
- << Type << Ex->getSourceRange();
+ << Type << Ex.get()->getSourceRange();
for (unsigned i= 0; i < ObjectPtrConversions.size(); i++)
NoteOverloadCandidate(ObjectPtrConversions[i]);
return ExprError();
@@ -1669,7 +1712,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (!Type->isPointerType())
return ExprError(Diag(StartLoc, diag::err_delete_operand)
- << Type << Ex->getSourceRange());
+ << Type << Ex.get()->getSourceRange());
QualType Pointee = Type->getAs<PointerType>()->getPointeeType();
if (Pointee->isVoidType() && !isSFINAEContext()) {
@@ -1677,27 +1720,30 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
// effectively bans deletion of "void*". However, most compilers support
// this, so we treat it as a warning unless we're in a SFINAE context.
Diag(StartLoc, diag::ext_delete_void_ptr_operand)
- << Type << Ex->getSourceRange();
+ << Type << Ex.get()->getSourceRange();
} else if (Pointee->isFunctionType() || Pointee->isVoidType())
return ExprError(Diag(StartLoc, diag::err_delete_operand)
- << Type << Ex->getSourceRange());
+ << Type << Ex.get()->getSourceRange());
else if (!Pointee->isDependentType() &&
RequireCompleteType(StartLoc, Pointee,
PDiag(diag::warn_delete_incomplete)
- << Ex->getSourceRange()))
+ << Ex.get()->getSourceRange()))
return ExprError();
-
+ else if (unsigned AddressSpace = Pointee.getAddressSpace())
+ return Diag(Ex.get()->getLocStart(),
+ diag::err_address_space_qualified_delete)
+ << Pointee.getUnqualifiedType() << AddressSpace;
// C++ [expr.delete]p2:
// [Note: a pointer to a const type can be the operand of a
// delete-expression; it is not necessary to cast away the constness
// (5.2.11) of the pointer expression before it is used as the operand
// of the delete-expression. ]
- ImpCastExprToType(Ex, Context.getPointerType(Context.VoidTy),
+ Ex = ImpCastExprToType(Ex.take(), Context.getPointerType(Context.VoidTy),
CK_NoOp);
if (Pointee->isArrayType() && !ArrayForm) {
Diag(StartLoc, diag::warn_delete_array_type)
- << Type << Ex->getSourceRange()
+ << Type << Ex.get()->getSourceRange()
<< FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]");
ArrayForm = true;
}
@@ -1740,8 +1786,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
// Look for a global declaration.
DeclareGlobalNewDelete();
DeclContext *TUDecl = Context.getTranslationUnitDecl();
+ Expr *Arg = Ex.get();
if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName,
- &Ex, 1, TUDecl, /*AllowMissing=*/false,
+ &Arg, 1, TUDecl, /*AllowMissing=*/false,
OperatorDelete))
return ExprError();
}
@@ -1752,7 +1799,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (const RecordType *RT = PointeeElem->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
if (CXXDestructorDecl *Dtor = LookupDestructor(RD)) {
- CheckDestructorAccess(Ex->getExprLoc(), Dtor,
+ CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor,
PDiag(diag::err_access_dtor) << PointeeElem);
}
}
@@ -1762,7 +1809,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm,
ArrayFormAsWritten,
UsualArrayDeleteWantsSize,
- OperatorDelete, Ex, StartLoc));
+ OperatorDelete, Ex.take(), StartLoc));
}
/// \brief Check the use of the given variable as a C++ condition in an if,
@@ -1783,18 +1830,23 @@ ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,
diag::err_invalid_use_of_array_type)
<< ConditionVar->getSourceRange());
- Expr *Condition = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar,
+ ExprResult Condition =
+ Owned(DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
+ ConditionVar,
ConditionVar->getLocation(),
ConditionVar->getType().getNonReferenceType(),
- VK_LValue);
- if (ConvertToBoolean && CheckBooleanCondition(Condition, StmtLoc))
- return ExprError();
+ VK_LValue));
+ if (ConvertToBoolean) {
+ Condition = CheckBooleanCondition(Condition.take(), StmtLoc);
+ if (Condition.isInvalid())
+ return ExprError();
+ }
- return Owned(Condition);
+ return move(Condition);
}
/// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid.
-bool Sema::CheckCXXBooleanCondition(Expr *&CondExpr) {
+ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr) {
// C++ 6.4p4:
// The value of a condition that is an initialized declaration in a statement
// other than a switch statement is the value of the declared variable
@@ -1880,20 +1932,22 @@ static ExprResult BuildCXXCastArgument(Sema &S,
/// PerformImplicitConversion - Perform an implicit conversion of the
/// expression From to the type ToType using the pre-computed implicit
-/// conversion sequence ICS. Returns true if there was an error, false
-/// otherwise. The expression From is replaced with the converted
+/// conversion sequence ICS. Returns the converted
/// expression. Action is the kind of conversion we're performing,
/// used in the error message.
-bool
-Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
+ExprResult
+Sema::PerformImplicitConversion(Expr *From, QualType ToType,
const ImplicitConversionSequence &ICS,
AssignmentAction Action, bool CStyle) {
switch (ICS.getKind()) {
- case ImplicitConversionSequence::StandardConversion:
- if (PerformImplicitConversion(From, ToType, ICS.Standard, Action,
- CStyle))
- return true;
+ case ImplicitConversionSequence::StandardConversion: {
+ ExprResult Res = PerformImplicitConversion(From, ToType, ICS.Standard,
+ Action, CStyle);
+ if (Res.isInvalid())
+ return ExprError();
+ From = Res.take();
break;
+ }
case ImplicitConversionSequence::UserDefinedConversion: {
@@ -1920,10 +1974,13 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
}
// Watch out for elipsis conversion.
if (!ICS.UserDefined.EllipsisConversion) {
- if (PerformImplicitConversion(From, BeforeToType,
- ICS.UserDefined.Before, AA_Converting,
- CStyle))
- return true;
+ ExprResult Res =
+ PerformImplicitConversion(From, BeforeToType,
+ ICS.UserDefined.Before, AA_Converting,
+ CStyle);
+ if (Res.isInvalid())
+ return ExprError();
+ From = Res.take();
}
ExprResult CastArg
@@ -1935,9 +1992,9 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
From);
if (CastArg.isInvalid())
- return true;
+ return ExprError();
- From = CastArg.takeAs<Expr>();
+ From = CastArg.take();
return PerformImplicitConversion(From, ToType, ICS.UserDefined.After,
AA_Converting, CStyle);
@@ -1947,28 +2004,27 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
ICS.DiagnoseAmbiguousConversion(*this, From->getExprLoc(),
PDiag(diag::err_typecheck_ambiguous_condition)
<< From->getSourceRange());
- return true;
+ return ExprError();
case ImplicitConversionSequence::EllipsisConversion:
assert(false && "Cannot perform an ellipsis conversion");
- return false;
+ return Owned(From);
case ImplicitConversionSequence::BadConversion:
- return true;
+ return ExprError();
}
// Everything went well.
- return false;
+ return Owned(From);
}
/// PerformImplicitConversion - Perform an implicit conversion of the
/// expression From to the type ToType by following the standard
-/// conversion sequence SCS. Returns true if there was an error, false
-/// otherwise. The expression From is replaced with the converted
+/// conversion sequence SCS. Returns the converted
/// expression. Flavor is the context in which we're performing this
/// conversion, for use in error messages.
-bool
-Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
+ExprResult
+Sema::PerformImplicitConversion(Expr *From, QualType ToType,
const StandardConversionSequence& SCS,
AssignmentAction Action, bool CStyle) {
// Overall FIXME: we are recomputing too many types here and doing far too
@@ -1986,32 +2042,20 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
MultiExprArg(*this, &From, 1),
/*FIXME:ConstructLoc*/SourceLocation(),
ConstructorArgs))
- return true;
- ExprResult FromResult =
- BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
- ToType, SCS.CopyConstructor,
- move_arg(ConstructorArgs),
- /*ZeroInit*/ false,
- CXXConstructExpr::CK_Complete,
- SourceRange());
- if (FromResult.isInvalid())
- return true;
- From = FromResult.takeAs<Expr>();
- return false;
+ return ExprError();
+ return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
+ ToType, SCS.CopyConstructor,
+ move_arg(ConstructorArgs),
+ /*ZeroInit*/ false,
+ CXXConstructExpr::CK_Complete,
+ SourceRange());
}
- ExprResult FromResult =
- BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
- ToType, SCS.CopyConstructor,
- MultiExprArg(*this, &From, 1),
- /*ZeroInit*/ false,
- CXXConstructExpr::CK_Complete,
- SourceRange());
-
- if (FromResult.isInvalid())
- return true;
-
- From = FromResult.takeAs<Expr>();
- return false;
+ return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
+ ToType, SCS.CopyConstructor,
+ MultiExprArg(*this, &From, 1),
+ /*ZeroInit*/ false,
+ CXXConstructExpr::CK_Complete,
+ SourceRange());
}
// Resolve overloaded function references.
@@ -2020,10 +2064,10 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType,
true, Found);
if (!Fn)
- return true;
+ return ExprError();
if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))
- return true;
+ return ExprError();
From = FixOverloadedFunctionReference(From, Found, Fn);
FromType = From->getType();
@@ -2038,13 +2082,15 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
case ICK_Lvalue_To_Rvalue:
// Should this get its own ICK?
if (From->getObjectKind() == OK_ObjCProperty) {
- ConvertPropertyForRValue(From);
+ ExprResult FromRes = ConvertPropertyForRValue(From);
+ if (FromRes.isInvalid())
+ return ExprError();
+ From = FromRes.take();
if (!From->isGLValue()) break;
}
// Check for trivial buffer overflows.
- if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(From))
- CheckArrayAccess(AE);
+ CheckArrayAccess(From);
FromType = FromType.getUnqualifiedType();
From = ImplicitCastExpr::Create(Context, FromType, CK_LValueToRValue,
@@ -2053,12 +2099,12 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
case ICK_Array_To_Pointer:
FromType = Context.getArrayDecayedType(FromType);
- ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay);
+ From = ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay).take();
break;
case ICK_Function_To_Pointer:
FromType = Context.getPointerType(FromType);
- ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay);
+ From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay).take();
break;
default:
@@ -2072,7 +2118,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
// If both sides are functions (or pointers/references to them), there could
// be incompatible exception declarations.
if (CheckExceptionSpecCompatibility(From, ToType))
- return true;
+ return ExprError();
// Nothing else to do.
break;
@@ -2080,19 +2126,19 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
// If both sides are functions (or pointers/references to them), there could
// be incompatible exception declarations.
if (CheckExceptionSpecCompatibility(From, ToType))
- return true;
+ return ExprError();
- ImpCastExprToType(From, ToType, CK_NoOp);
+ From = ImpCastExprToType(From, ToType, CK_NoOp).take();
break;
case ICK_Integral_Promotion:
case ICK_Integral_Conversion:
- ImpCastExprToType(From, ToType, CK_IntegralCast);
+ From = ImpCastExprToType(From, ToType, CK_IntegralCast).take();
break;
case ICK_Floating_Promotion:
case ICK_Floating_Conversion:
- ImpCastExprToType(From, ToType, CK_FloatingCast);
+ From = ImpCastExprToType(From, ToType, CK_FloatingCast).take();
break;
case ICK_Complex_Promotion:
@@ -2110,35 +2156,41 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
} else {
CK = CK_IntegralComplexCast;
}
- ImpCastExprToType(From, ToType, CK);
+ From = ImpCastExprToType(From, ToType, CK).take();
break;
}
case ICK_Floating_Integral:
if (ToType->isRealFloatingType())
- ImpCastExprToType(From, ToType, CK_IntegralToFloating);
+ From = ImpCastExprToType(From, ToType, CK_IntegralToFloating).take();
else
- ImpCastExprToType(From, ToType, CK_FloatingToIntegral);
+ From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral).take();
break;
case ICK_Compatible_Conversion:
- ImpCastExprToType(From, ToType, CK_NoOp);
+ From = ImpCastExprToType(From, ToType, CK_NoOp).take();
break;
case ICK_Pointer_Conversion: {
if (SCS.IncompatibleObjC && Action != AA_Casting) {
// Diagnose incompatible Objective-C conversions
- Diag(From->getSourceRange().getBegin(),
- diag::ext_typecheck_convert_incompatible_pointer)
- << From->getType() << ToType << Action
- << From->getSourceRange();
+ if (Action == AA_Initializing)
+ Diag(From->getSourceRange().getBegin(),
+ diag::ext_typecheck_convert_incompatible_pointer)
+ << ToType << From->getType() << Action
+ << From->getSourceRange();
+ else
+ Diag(From->getSourceRange().getBegin(),
+ diag::ext_typecheck_convert_incompatible_pointer)
+ << From->getType() << ToType << Action
+ << From->getSourceRange();
}
CastKind Kind = CK_Invalid;
CXXCastPath BasePath;
if (CheckPointerConversion(From, ToType, Kind, BasePath, CStyle))
- return true;
- ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath);
+ return ExprError();
+ From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath).take();
break;
}
@@ -2146,27 +2198,17 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
CastKind Kind = CK_Invalid;
CXXCastPath BasePath;
if (CheckMemberPointerConversion(From, ToType, Kind, BasePath, CStyle))
- return true;
+ return ExprError();
if (CheckExceptionSpecCompatibility(From, ToType))
- return true;
- ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath);
+ return ExprError();
+ From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath).take();
break;
}
- case ICK_Boolean_Conversion: {
- CastKind Kind = CK_Invalid;
- switch (FromType->getScalarTypeKind()) {
- case Type::STK_Pointer: Kind = CK_PointerToBoolean; break;
- case Type::STK_MemberPointer: Kind = CK_MemberPointerToBoolean; break;
- case Type::STK_Bool: llvm_unreachable("bool -> bool conversion?");
- case Type::STK_Integral: Kind = CK_IntegralToBoolean; break;
- case Type::STK_Floating: Kind = CK_FloatingToBoolean; break;
- case Type::STK_IntegralComplex: Kind = CK_IntegralComplexToBoolean; break;
- case Type::STK_FloatingComplex: Kind = CK_FloatingComplexToBoolean; break;
- }
- ImpCastExprToType(From, Context.BoolTy, Kind);
+ case ICK_Boolean_Conversion:
+ From = ImpCastExprToType(From, Context.BoolTy,
+ ScalarTypeToBooleanCastKind(FromType)).take();
break;
- }
case ICK_Derived_To_Base: {
CXXCastPath BasePath;
@@ -2176,20 +2218,20 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
From->getSourceRange(),
&BasePath,
CStyle))
- return true;
+ return ExprError();
- ImpCastExprToType(From, ToType.getNonReferenceType(),
+ From = ImpCastExprToType(From, ToType.getNonReferenceType(),
CK_DerivedToBase, CastCategory(From),
- &BasePath);
+ &BasePath).take();
break;
}
case ICK_Vector_Conversion:
- ImpCastExprToType(From, ToType, CK_BitCast);
+ From = ImpCastExprToType(From, ToType, CK_BitCast).take();
break;
case ICK_Vector_Splat:
- ImpCastExprToType(From, ToType, CK_VectorSplat);
+ From = ImpCastExprToType(From, ToType, CK_VectorSplat).take();
break;
case ICK_Complex_Real:
@@ -2202,17 +2244,17 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
if (Context.hasSameUnqualifiedType(ElType, From->getType())) {
// do nothing
} else if (From->getType()->isRealFloatingType()) {
- ImpCastExprToType(From, ElType,
- isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral);
+ From = ImpCastExprToType(From, ElType,
+ isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral).take();
} else {
assert(From->getType()->isIntegerType());
- ImpCastExprToType(From, ElType,
- isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast);
+ From = ImpCastExprToType(From, ElType,
+ isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast).take();
}
// y -> _Complex y
- ImpCastExprToType(From, ToType,
+ From = ImpCastExprToType(From, ToType,
isFloatingComplex ? CK_FloatingRealToComplex
- : CK_IntegralRealToComplex);
+ : CK_IntegralRealToComplex).take();
// Case 2. _Complex x -> y
} else {
@@ -2223,29 +2265,43 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
bool isFloatingComplex = ElType->isRealFloatingType();
// _Complex x -> x
- ImpCastExprToType(From, ElType,
+ From = ImpCastExprToType(From, ElType,
isFloatingComplex ? CK_FloatingComplexToReal
- : CK_IntegralComplexToReal);
+ : CK_IntegralComplexToReal).take();
// x -> y
if (Context.hasSameUnqualifiedType(ElType, ToType)) {
// do nothing
} else if (ToType->isRealFloatingType()) {
- ImpCastExprToType(From, ToType,
- isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating);
+ From = ImpCastExprToType(From, ToType,
+ isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating).take();
} else {
assert(ToType->isIntegerType());
- ImpCastExprToType(From, ToType,
- isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast);
+ From = ImpCastExprToType(From, ToType,
+ isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast).take();
}
}
break;
case ICK_Block_Pointer_Conversion: {
- ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast, VK_RValue);
+ From = ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast,
+ VK_RValue).take();
break;
}
+ case ICK_TransparentUnionConversion: {
+ ExprResult FromRes = Owned(From);
+ Sema::AssignConvertType ConvTy =
+ CheckTransparentUnionArgumentConstraints(ToType, FromRes);
+ if (FromRes.isInvalid())
+ return ExprError();
+ From = FromRes.take();
+ assert ((ConvTy == Sema::Compatible) &&
+ "Improper transparent union conversion");
+ (void)ConvTy;
+ break;
+ }
+
case ICK_Lvalue_To_Rvalue:
case ICK_Array_To_Pointer:
case ICK_Function_To_Pointer:
@@ -2265,10 +2321,11 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
// target type isn't a reference.
ExprValueKind VK = ToType->isReferenceType() ?
CastCategory(From) : VK_RValue;
- ImpCastExprToType(From, ToType.getNonLValueExprType(Context),
- CK_NoOp, VK);
+ From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context),
+ CK_NoOp, VK).take();
- if (SCS.DeprecatedStringLiteralToCharPtr)
+ if (SCS.DeprecatedStringLiteralToCharPtr &&
+ !getLangOptions().WritableStrings)
Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion)
<< ToType.getNonReferenceType();
@@ -2280,7 +2337,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
break;
}
- return false;
+ return Owned(From);
}
ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT,
@@ -2295,41 +2352,197 @@ ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT,
return BuildUnaryTypeTrait(UTT, KWLoc, TSInfo, RParen);
}
-static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T,
- SourceLocation KeyLoc) {
- // FIXME: For many of these traits, we need a complete type before we can
- // check these properties.
- assert(!T->isDependentType() &&
- "Cannot evaluate traits for dependent types.");
+/// \brief Check the completeness of a type in a unary type trait.
+///
+/// If the particular type trait requires a complete type, tries to complete
+/// it. If completing the type fails, a diagnostic is emitted and false
+/// returned. If completing the type succeeds or no completion was required,
+/// returns true.
+static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
+ UnaryTypeTrait UTT,
+ SourceLocation Loc,
+ QualType ArgTy) {
+ // C++0x [meta.unary.prop]p3:
+ // For all of the class templates X declared in this Clause, instantiating
+ // that template with a template argument that is a class template
+ // specialization may result in the implicit instantiation of the template
+ // argument if and only if the semantics of X require that the argument
+ // must be a complete type.
+ // We apply this rule to all the type trait expressions used to implement
+ // these class templates. We also try to follow any GCC documented behavior
+ // in these expressions to ensure portability of standard libraries.
+ switch (UTT) {
+ // is_complete_type somewhat obviously cannot require a complete type.
+ case UTT_IsCompleteType:
+ // Fall-through
+
+ // These traits are modeled on the type predicates in C++0x
+ // [meta.unary.cat] and [meta.unary.comp]. They are not specified as
+ // requiring a complete type, as whether or not they return true cannot be
+ // impacted by the completeness of the type.
+ case UTT_IsVoid:
+ case UTT_IsIntegral:
+ case UTT_IsFloatingPoint:
+ case UTT_IsArray:
+ case UTT_IsPointer:
+ case UTT_IsLvalueReference:
+ case UTT_IsRvalueReference:
+ case UTT_IsMemberFunctionPointer:
+ case UTT_IsMemberObjectPointer:
+ case UTT_IsEnum:
+ case UTT_IsUnion:
+ case UTT_IsClass:
+ case UTT_IsFunction:
+ case UTT_IsReference:
+ case UTT_IsArithmetic:
+ case UTT_IsFundamental:
+ case UTT_IsObject:
+ case UTT_IsScalar:
+ case UTT_IsCompound:
+ case UTT_IsMemberPointer:
+ // Fall-through
+
+ // These traits are modeled on type predicates in C++0x [meta.unary.prop]
+ // which requires some of its traits to have the complete type. However,
+ // the completeness of the type cannot impact these traits' semantics, and
+ // so they don't require it. This matches the comments on these traits in
+ // Table 49.
+ case UTT_IsConst:
+ case UTT_IsVolatile:
+ case UTT_IsSigned:
+ case UTT_IsUnsigned:
+ return true;
+
+ // C++0x [meta.unary.prop] Table 49 requires the following traits to be
+ // applied to a complete type.
+ case UTT_IsTrivial:
+ case UTT_IsStandardLayout:
+ case UTT_IsPOD:
+ case UTT_IsLiteral:
+ case UTT_IsEmpty:
+ case UTT_IsPolymorphic:
+ case UTT_IsAbstract:
+ // Fall-through
+
+ // These trait expressions are designed to help implement predicates in
+ // [meta.unary.prop] despite not being named the same. They are specified
+ // by both GCC and the Embarcadero C++ compiler, and require the complete
+ // type due to the overarching C++0x type predicates being implemented
+ // requiring the complete type.
+ case UTT_HasNothrowAssign:
+ case UTT_HasNothrowConstructor:
+ case UTT_HasNothrowCopy:
+ case UTT_HasTrivialAssign:
+ case UTT_HasTrivialConstructor:
+ case UTT_HasTrivialCopy:
+ case UTT_HasTrivialDestructor:
+ case UTT_HasVirtualDestructor:
+ // Arrays of unknown bound are expressly allowed.
+ QualType ElTy = ArgTy;
+ if (ArgTy->isIncompleteArrayType())
+ ElTy = S.Context.getAsArrayType(ArgTy)->getElementType();
+
+ // The void type is expressly allowed.
+ if (ElTy->isVoidType())
+ return true;
+
+ return !S.RequireCompleteType(
+ Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr);
+ }
+ llvm_unreachable("Type trait not handled by switch");
+}
+
+static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
+ SourceLocation KeyLoc, QualType T) {
+ assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");
+
ASTContext &C = Self.Context;
switch(UTT) {
- default: assert(false && "Unknown type trait or not implemented");
- case UTT_IsPOD: return T->isPODType();
- case UTT_IsLiteral: return T->isLiteralType();
- case UTT_IsClass: // Fallthrough
+ // Type trait expressions corresponding to the primary type category
+ // predicates in C++0x [meta.unary.cat].
+ case UTT_IsVoid:
+ return T->isVoidType();
+ case UTT_IsIntegral:
+ return T->isIntegralType(C);
+ case UTT_IsFloatingPoint:
+ return T->isFloatingType();
+ case UTT_IsArray:
+ return T->isArrayType();
+ case UTT_IsPointer:
+ return T->isPointerType();
+ case UTT_IsLvalueReference:
+ return T->isLValueReferenceType();
+ case UTT_IsRvalueReference:
+ return T->isRValueReferenceType();
+ case UTT_IsMemberFunctionPointer:
+ return T->isMemberFunctionPointerType();
+ case UTT_IsMemberObjectPointer:
+ return T->isMemberDataPointerType();
+ case UTT_IsEnum:
+ return T->isEnumeralType();
case UTT_IsUnion:
- if (const RecordType *Record = T->getAs<RecordType>()) {
- bool Union = Record->getDecl()->isUnion();
- return UTT == UTT_IsUnion ? Union : !Union;
- }
+ return T->isUnionType();
+ case UTT_IsClass:
+ return T->isClassType() || T->isStructureType();
+ case UTT_IsFunction:
+ return T->isFunctionType();
+
+ // Type trait expressions which correspond to the convenient composition
+ // predicates in C++0x [meta.unary.comp].
+ case UTT_IsReference:
+ return T->isReferenceType();
+ case UTT_IsArithmetic:
+ return T->isArithmeticType() && !T->isEnumeralType();
+ case UTT_IsFundamental:
+ return T->isFundamentalType();
+ case UTT_IsObject:
+ return T->isObjectType();
+ case UTT_IsScalar:
+ return T->isScalarType();
+ case UTT_IsCompound:
+ return T->isCompoundType();
+ case UTT_IsMemberPointer:
+ return T->isMemberPointerType();
+
+ // Type trait expressions which correspond to the type property predicates
+ // in C++0x [meta.unary.prop].
+ case UTT_IsConst:
+ return T.isConstQualified();
+ case UTT_IsVolatile:
+ return T.isVolatileQualified();
+ case UTT_IsTrivial:
+ return T->isTrivialType();
+ case UTT_IsStandardLayout:
+ return T->isStandardLayoutType();
+ case UTT_IsPOD:
+ return T->isPODType();
+ case UTT_IsLiteral:
+ return T->isLiteralType();
+ case UTT_IsEmpty:
+ if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+ return !RD->isUnion() && RD->isEmpty();
return false;
- case UTT_IsEnum: return T->isEnumeralType();
case UTT_IsPolymorphic:
- if (const RecordType *Record = T->getAs<RecordType>()) {
- // Type traits are only parsed in C++, so we've got CXXRecords.
- return cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic();
- }
+ if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+ return RD->isPolymorphic();
return false;
case UTT_IsAbstract:
- if (const RecordType *RT = T->getAs<RecordType>())
- return cast<CXXRecordDecl>(RT->getDecl())->isAbstract();
- return false;
- case UTT_IsEmpty:
- if (const RecordType *Record = T->getAs<RecordType>()) {
- return !Record->getDecl()->isUnion()
- && cast<CXXRecordDecl>(Record->getDecl())->isEmpty();
- }
+ if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+ return RD->isAbstract();
return false;
+ case UTT_IsSigned:
+ return T->isSignedIntegerType();
+ case UTT_IsUnsigned:
+ return T->isUnsignedIntegerType();
+
+ // Type trait expressions which query classes regarding their construction,
+ // destruction, and copying. Rather than being based directly on the
+ // related type predicates in the standard, they are specified by both
+ // GCC[1] and the Embarcadero C++ compiler[2], and Clang implements those
+ // specifications.
+ //
+ // 1: http://gcc.gnu/.org/onlinedocs/gcc/Type-Traits.html
+ // 2: http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index
case UTT_HasTrivialConstructor:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
// If __is_pod (type) is true then the trait is true, else if type is
@@ -2418,7 +2631,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T,
FoundAssign = true;
const FunctionProtoType *CPT
= Operator->getType()->getAs<FunctionProtoType>();
- if (!CPT->hasEmptyExceptionSpec()) {
+ if (!CPT->isNothrow(Self.Context)) {
AllNoThrow = false;
break;
}
@@ -2458,9 +2671,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T,
FoundConstructor = true;
const FunctionProtoType *CPT
= Constructor->getType()->getAs<FunctionProtoType>();
- // TODO: check whether evaluating default arguments can throw.
+ // FIXME: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- if (!CPT->hasEmptyExceptionSpec() || CPT->getNumArgs() > 1) {
+ if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1) {
AllNoThrow = false;
break;
}
@@ -2495,7 +2708,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T,
= Constructor->getType()->getAs<FunctionProtoType>();
// TODO: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- return CPT->hasEmptyExceptionSpec() && CPT->getNumArgs() == 0;
+ return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0;
}
}
}
@@ -2510,7 +2723,17 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T,
return Destructor->isVirtual();
}
return false;
+
+ // These type trait expressions are modeled on the specifications for the
+ // Embarcadero C++0x type trait functions:
+ // http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index
+ case UTT_IsCompleteType:
+ // http://docwiki.embarcadero.com/RADStudio/XE/en/Is_complete_type_(typename_T_):
+ // Returns True if and only if T is a complete type at the point of the
+ // function call.
+ return !T->isIncompleteType();
}
+ llvm_unreachable("Type trait not covered by switch");
}
ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT,
@@ -2518,23 +2741,12 @@ ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT,
TypeSourceInfo *TSInfo,
SourceLocation RParen) {
QualType T = TSInfo->getType();
-
- // According to http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
- // all traits except __is_class, __is_enum and __is_union require a the type
- // to be complete, an array of unknown bound, or void.
- if (UTT != UTT_IsClass && UTT != UTT_IsEnum && UTT != UTT_IsUnion) {
- QualType E = T;
- if (T->isIncompleteArrayType())
- E = Context.getAsArrayType(T)->getElementType();
- if (!T->isVoidType() &&
- RequireCompleteType(KWLoc, E,
- diag::err_incomplete_type_used_in_type_trait_expr))
- return ExprError();
- }
+ if (!CheckUnaryTypeTraitTypeCompleteness(*this, UTT, KWLoc, T))
+ return ExprError();
bool Value = false;
if (!T->isDependentType())
- Value = EvaluateUnaryTypeTrait(*this, UTT, T, KWLoc);
+ Value = EvaluateUnaryTypeTrait(*this, UTT, KWLoc, T);
return Owned(new (Context) UnaryTypeTraitExpr(KWLoc, UTT, TSInfo, Value,
RParen, Context.BoolTy));
@@ -2561,8 +2773,8 @@ ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT,
static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
QualType LhsT, QualType RhsT,
SourceLocation KeyLoc) {
- assert((!LhsT->isDependentType() || RhsT->isDependentType()) &&
- "Cannot evaluate traits for dependent types.");
+ assert(!LhsT->isDependentType() && !RhsT->isDependentType() &&
+ "Cannot evaluate traits of dependent types");
switch(BTT) {
case BTT_IsBaseOf: {
@@ -2594,11 +2806,12 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
return cast<CXXRecordDecl>(rhsRecord->getDecl())
->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getDecl()));
}
-
+ case BTT_IsSame:
+ return Self.Context.hasSameType(LhsT, RhsT);
case BTT_TypeCompatible:
return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(),
RhsT.getUnqualifiedType());
-
+ case BTT_IsConvertible:
case BTT_IsConvertibleTo: {
// C++0x [meta.rel]p4:
// Given the following function prototype:
@@ -2673,6 +2886,8 @@ ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT,
QualType ResultType;
switch (BTT) {
case BTT_IsBaseOf: ResultType = Context.BoolTy; break;
+ case BTT_IsConvertible: ResultType = Context.BoolTy; break;
+ case BTT_IsSame: ResultType = Context.BoolTy; break;
case BTT_TypeCompatible: ResultType = Context.IntTy; break;
case BTT_IsConvertibleTo: ResultType = Context.BoolTy; break;
}
@@ -2682,7 +2897,138 @@ ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT,
ResultType));
}
-QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex,
+ExprResult Sema::ActOnArrayTypeTrait(ArrayTypeTrait ATT,
+ SourceLocation KWLoc,
+ ParsedType Ty,
+ Expr* DimExpr,
+ SourceLocation RParen) {
+ TypeSourceInfo *TSInfo;
+ QualType T = GetTypeFromParser(Ty, &TSInfo);
+ if (!TSInfo)
+ TSInfo = Context.getTrivialTypeSourceInfo(T);
+
+ return BuildArrayTypeTrait(ATT, KWLoc, TSInfo, DimExpr, RParen);
+}
+
+static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT,
+ QualType T, Expr *DimExpr,
+ SourceLocation KeyLoc) {
+ assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");
+
+ switch(ATT) {
+ case ATT_ArrayRank:
+ if (T->isArrayType()) {
+ unsigned Dim = 0;
+ while (const ArrayType *AT = Self.Context.getAsArrayType(T)) {
+ ++Dim;
+ T = AT->getElementType();
+ }
+ return Dim;
+ }
+ return 0;
+
+ case ATT_ArrayExtent: {
+ llvm::APSInt Value;
+ uint64_t Dim;
+ if (DimExpr->isIntegerConstantExpr(Value, Self.Context, 0, false)) {
+ if (Value < llvm::APSInt(Value.getBitWidth(), Value.isUnsigned())) {
+ Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) <<
+ DimExpr->getSourceRange();
+ return false;
+ }
+ Dim = Value.getLimitedValue();
+ } else {
+ Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) <<
+ DimExpr->getSourceRange();
+ return false;
+ }
+
+ if (T->isArrayType()) {
+ unsigned D = 0;
+ bool Matched = false;
+ while (const ArrayType *AT = Self.Context.getAsArrayType(T)) {
+ if (Dim == D) {
+ Matched = true;
+ break;
+ }
+ ++D;
+ T = AT->getElementType();
+ }
+
+ if (Matched && T->isArrayType()) {
+ if (const ConstantArrayType *CAT = Self.Context.getAsConstantArrayType(T))
+ return CAT->getSize().getLimitedValue();
+ }
+ }
+ return 0;
+ }
+ }
+ llvm_unreachable("Unknown type trait or not implemented");
+}
+
+ExprResult Sema::BuildArrayTypeTrait(ArrayTypeTrait ATT,
+ SourceLocation KWLoc,
+ TypeSourceInfo *TSInfo,
+ Expr* DimExpr,
+ SourceLocation RParen) {
+ QualType T = TSInfo->getType();
+
+ // FIXME: This should likely be tracked as an APInt to remove any host
+ // assumptions about the width of size_t on the target.
+ uint64_t Value = 0;
+ if (!T->isDependentType())
+ Value = EvaluateArrayTypeTrait(*this, ATT, T, DimExpr, KWLoc);
+
+ // While the specification for these traits from the Embarcadero C++
+ // compiler's documentation says the return type is 'unsigned int', Clang
+ // returns 'size_t'. On Windows, the primary platform for the Embarcadero
+ // compiler, there is no difference. On several other platforms this is an
+ // important distinction.
+ return Owned(new (Context) ArrayTypeTraitExpr(KWLoc, ATT, TSInfo, Value,
+ DimExpr, RParen,
+ Context.getSizeType()));
+}
+
+ExprResult Sema::ActOnExpressionTrait(ExpressionTrait ET,
+ SourceLocation KWLoc,
+ Expr *Queried,
+ SourceLocation RParen) {
+ // If error parsing the expression, ignore.
+ if (!Queried)
+ return ExprError();
+
+ ExprResult Result = BuildExpressionTrait(ET, KWLoc, Queried, RParen);
+
+ return move(Result);
+}
+
+static bool EvaluateExpressionTrait(ExpressionTrait ET, Expr *E) {
+ switch (ET) {
+ case ET_IsLValueExpr: return E->isLValue();
+ case ET_IsRValueExpr: return E->isRValue();
+ }
+ llvm_unreachable("Expression trait not covered by switch");
+}
+
+ExprResult Sema::BuildExpressionTrait(ExpressionTrait ET,
+ SourceLocation KWLoc,
+ Expr *Queried,
+ SourceLocation RParen) {
+ if (Queried->isTypeDependent()) {
+ // Delay type-checking for type-dependent expressions.
+ } else if (Queried->getType()->isPlaceholderType()) {
+ ExprResult PE = CheckPlaceholderExpr(Queried);
+ if (PE.isInvalid()) return ExprError();
+ return BuildExpressionTrait(ET, KWLoc, PE.take(), RParen);
+ }
+
+ bool Value = EvaluateExpressionTrait(ET, Queried);
+
+ return Owned(new (Context) ExpressionTraitExpr(KWLoc, ET, Queried, Value,
+ RParen, Context.BoolTy));
+}
+
+QualType Sema::CheckPointerToMemberOperands(ExprResult &lex, ExprResult &rex,
ExprValueKind &VK,
SourceLocation Loc,
bool isIndirect) {
@@ -2691,11 +3037,11 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex,
// The binary operator .* [p3: ->*] binds its second operand, which shall
// be of type "pointer to member of T" (where T is a completely-defined
// class type) [...]
- QualType RType = rex->getType();
+ QualType RType = rex.get()->getType();
const MemberPointerType *MemPtr = RType->getAs<MemberPointerType>();
if (!MemPtr) {
Diag(Loc, diag::err_bad_memptr_rhs)
- << OpSpelling << RType << rex->getSourceRange();
+ << OpSpelling << RType << rex.get()->getSourceRange();
return QualType();
}
@@ -2711,7 +3057,7 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex,
// [...] to its first operand, which shall be of class T or of a class of
// which T is an unambiguous and accessible base class. [p3: a pointer to
// such a class]
- QualType LType = lex->getType();
+ QualType LType = lex.get()->getType();
if (isIndirect) {
if (const PointerType *Ptr = LType->getAs<PointerType>())
LType = Ptr->getPointeeType();
@@ -2736,20 +3082,20 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex,
if (!IsDerivedFrom(LType, Class, Paths) ||
Paths.isAmbiguous(Context.getCanonicalType(Class))) {
Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
- << (int)isIndirect << lex->getType();
+ << (int)isIndirect << lex.get()->getType();
return QualType();
}
// Cast LHS to type of use.
QualType UseType = isIndirect ? Context.getPointerType(Class) : Class;
ExprValueKind VK =
- isIndirect ? VK_RValue : CastCategory(lex);
+ isIndirect ? VK_RValue : CastCategory(lex.get());
CXXCastPath BasePath;
BuildBasePathArray(Paths, BasePath);
- ImpCastExprToType(lex, UseType, CK_DerivedToBase, VK, &BasePath);
+ lex = ImpCastExprToType(lex.take(), UseType, CK_DerivedToBase, VK, &BasePath);
}
- if (isa<CXXScalarValueInitExpr>(rex->IgnoreParens())) {
+ if (isa<CXXScalarValueInitExpr>(rex.get()->IgnoreParens())) {
// Diagnose use of pointer-to-member type which when used as
// the functional cast in a pointer-to-member expression.
Diag(Loc, diag::err_pointer_to_member_type) << isIndirect;
@@ -2761,13 +3107,6 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex,
// second operand.
// The cv qualifiers are the union of those in the pointer and the left side,
// in accordance with 5.5p5 and 5.2.5.
- // FIXME: This returns a dereferenced member function pointer as a normal
- // function type. However, the only operation valid on such functions is
- // calling them. There's also a GCC extension to get a function pointer to the
- // thing, which is another complication, because this type - unlike the type
- // that is the result of this expression - takes the class as the first
- // argument.
- // We probably need a "MemberFunctionClosureType" or something like that.
QualType Result = MemPtr->getPointeeType();
Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers());
@@ -2784,15 +3123,15 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex,
break;
case RQ_LValue:
- if (!isIndirect && !lex->Classify(Context).isLValue())
+ if (!isIndirect && !lex.get()->Classify(Context).isLValue())
Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
- << RType << 1 << lex->getSourceRange();
+ << RType << 1 << lex.get()->getSourceRange();
break;
case RQ_RValue:
- if (isIndirect || !lex->Classify(Context).isRValue())
+ if (isIndirect || !lex.get()->Classify(Context).isRValue())
Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
- << RType << 0 << lex->getSourceRange();
+ << RType << 0 << lex.get()->getSourceRange();
break;
}
}
@@ -2804,12 +3143,14 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex,
// operand is a pointer to a member function is a prvalue. The
// result of an ->* expression is an lvalue if its second operand
// is a pointer to data member and a prvalue otherwise.
- if (Result->isFunctionType())
+ if (Result->isFunctionType()) {
VK = VK_RValue;
- else if (isIndirect)
+ return Context.BoundMemberTy;
+ } else if (isIndirect) {
VK = VK_LValue;
- else
- VK = lex->getValueKind();
+ } else {
+ VK = lex.get()->getValueKind();
+ }
return Result;
}
@@ -2910,43 +3251,52 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
/// This is part of the parameter validation for the ? operator. If either
/// value operand is a class type, overload resolution is used to find a
/// conversion to a common type.
-static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
+static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS,
SourceLocation QuestionLoc) {
- Expr *Args[2] = { LHS, RHS };
+ Expr *Args[2] = { LHS.get(), RHS.get() };
OverloadCandidateSet CandidateSet(QuestionLoc);
Self.AddBuiltinOperatorCandidates(OO_Conditional, QuestionLoc, Args, 2,
CandidateSet);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(Self, QuestionLoc, Best)) {
- case OR_Success:
+ case OR_Success: {
// We found a match. Perform the conversions on the arguments and move on.
- if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0],
- Best->Conversions[0], Sema::AA_Converting) ||
- Self.PerformImplicitConversion(RHS, Best->BuiltinTypes.ParamTypes[1],
- Best->Conversions[1], Sema::AA_Converting))
+ ExprResult LHSRes =
+ Self.PerformImplicitConversion(LHS.get(), Best->BuiltinTypes.ParamTypes[0],
+ Best->Conversions[0], Sema::AA_Converting);
+ if (LHSRes.isInvalid())
+ break;
+ LHS = move(LHSRes);
+
+ ExprResult RHSRes =
+ Self.PerformImplicitConversion(RHS.get(), Best->BuiltinTypes.ParamTypes[1],
+ Best->Conversions[1], Sema::AA_Converting);
+ if (RHSRes.isInvalid())
break;
+ RHS = move(RHSRes);
if (Best->Function)
Self.MarkDeclarationReferenced(QuestionLoc, Best->Function);
return false;
-
+ }
+
case OR_No_Viable_Function:
// Emit a better diagnostic if one of the expressions is a null pointer
// constant and the other is a pointer type. In this case, the user most
// likely forgot to take the address of the other expression.
- if (Self.DiagnoseConditionalForNull(LHS, RHS, QuestionLoc))
+ if (Self.DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc))
return true;
Self.Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
- << LHS->getType() << RHS->getType()
- << LHS->getSourceRange() << RHS->getSourceRange();
+ << LHS.get()->getType() << RHS.get()->getType()
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return true;
case OR_Ambiguous:
Self.Diag(QuestionLoc, diag::err_conditional_ambiguous_ovl)
- << LHS->getType() << RHS->getType()
- << LHS->getSourceRange() << RHS->getSourceRange();
+ << LHS.get()->getType() << RHS.get()->getType()
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
// FIXME: Print the possible common types by printing the return types of
// the viable candidates.
break;
@@ -2960,16 +3310,17 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
/// \brief Perform an "extended" implicit conversion as returned by
/// TryClassUnification.
-static bool ConvertForConditional(Sema &Self, Expr *&E, QualType T) {
+static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
InitializedEntity Entity = InitializedEntity::InitializeTemporary(T);
- InitializationKind Kind = InitializationKind::CreateCopy(E->getLocStart(),
+ InitializationKind Kind = InitializationKind::CreateCopy(E.get()->getLocStart(),
SourceLocation());
- InitializationSequence InitSeq(Self, Entity, Kind, &E, 1);
- ExprResult Result = InitSeq.Perform(Self, Entity, Kind, MultiExprArg(&E, 1));
+ Expr *Arg = E.take();
+ InitializationSequence InitSeq(Self, Entity, Kind, &Arg, 1);
+ ExprResult Result = InitSeq.Perform(Self, Entity, Kind, MultiExprArg(&Arg, 1));
if (Result.isInvalid())
return true;
- E = Result.takeAs<Expr>();
+ E = Result;
return false;
}
@@ -2977,7 +3328,7 @@ static bool ConvertForConditional(Sema &Self, Expr *&E, QualType T) {
///
/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
/// extension. In this case, LHS == Cond. (But they're not aliases.)
-QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
+QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS,
ExprValueKind &VK, ExprObjectKind &OK,
SourceLocation QuestionLoc) {
// FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++
@@ -2985,9 +3336,11 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// C++0x 5.16p1
// The first expression is contextually converted to bool.
- if (!Cond->isTypeDependent()) {
- if (CheckCXXBooleanCondition(Cond))
+ if (!Cond.get()->isTypeDependent()) {
+ ExprResult CondRes = CheckCXXBooleanCondition(Cond.take());
+ if (CondRes.isInvalid())
return QualType();
+ Cond = move(CondRes);
}
// Assume r-value.
@@ -2995,28 +3348,30 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
OK = OK_Ordinary;
// Either of the arguments dependent?
- if (LHS->isTypeDependent() || RHS->isTypeDependent())
+ if (LHS.get()->isTypeDependent() || RHS.get()->isTypeDependent())
return Context.DependentTy;
// C++0x 5.16p2
// If either the second or the third operand has type (cv) void, ...
- QualType LTy = LHS->getType();
- QualType RTy = RHS->getType();
+ QualType LTy = LHS.get()->getType();
+ QualType RTy = RHS.get()->getType();
bool LVoid = LTy->isVoidType();
bool RVoid = RTy->isVoidType();
if (LVoid || RVoid) {
// ... then the [l2r] conversions are performed on the second and third
// operands ...
- DefaultFunctionArrayLvalueConversion(LHS);
- DefaultFunctionArrayLvalueConversion(RHS);
- LTy = LHS->getType();
- RTy = RHS->getType();
+ LHS = DefaultFunctionArrayLvalueConversion(LHS.take());
+ RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
+ if (LHS.isInvalid() || RHS.isInvalid())
+ return QualType();
+ LTy = LHS.get()->getType();
+ RTy = RHS.get()->getType();
// ... and one of the following shall hold:
// -- The second or the third operand (but not both) is a throw-
// expression; the result is of the type of the other and is an rvalue.
- bool LThrow = isa<CXXThrowExpr>(LHS);
- bool RThrow = isa<CXXThrowExpr>(RHS);
+ bool LThrow = isa<CXXThrowExpr>(LHS.get());
+ bool RThrow = isa<CXXThrowExpr>(RHS.get());
if (LThrow && !RThrow)
return RTy;
if (RThrow && !LThrow)
@@ -3030,7 +3385,7 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// Neither holds, error.
Diag(QuestionLoc, diag::err_conditional_void_nonvoid)
<< (LVoid ? RTy : LTy) << (LVoid ? 0 : 1)
- << LHS->getSourceRange() << RHS->getSourceRange();
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
@@ -3046,15 +3401,15 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// These return true if a single direction is already ambiguous.
QualType L2RType, R2LType;
bool HaveL2R, HaveR2L;
- if (TryClassUnification(*this, LHS, RHS, QuestionLoc, HaveL2R, L2RType))
+ if (TryClassUnification(*this, LHS.get(), RHS.get(), QuestionLoc, HaveL2R, L2RType))
return QualType();
- if (TryClassUnification(*this, RHS, LHS, QuestionLoc, HaveR2L, R2LType))
+ if (TryClassUnification(*this, RHS.get(), LHS.get(), QuestionLoc, HaveR2L, R2LType))
return QualType();
// If both can be converted, [...] the program is ill-formed.
if (HaveL2R && HaveR2L) {
Diag(QuestionLoc, diag::err_conditional_ambiguous)
- << LTy << RTy << LHS->getSourceRange() << RHS->getSourceRange();
+ << LTy << RTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
@@ -3062,13 +3417,13 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// the chosen operand and the converted operands are used in place of the
// original operands for the remainder of this section.
if (HaveL2R) {
- if (ConvertForConditional(*this, LHS, L2RType))
+ if (ConvertForConditional(*this, LHS, L2RType) || LHS.isInvalid())
return QualType();
- LTy = LHS->getType();
+ LTy = LHS.get()->getType();
} else if (HaveR2L) {
- if (ConvertForConditional(*this, RHS, R2LType))
+ if (ConvertForConditional(*this, RHS, R2LType) || RHS.isInvalid())
return QualType();
- RTy = RHS->getType();
+ RTy = RHS.get()->getType();
}
}
@@ -3081,13 +3436,13 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// l-values.
bool Same = Context.hasSameType(LTy, RTy);
if (Same &&
- LHS->isGLValue() &&
- LHS->getValueKind() == RHS->getValueKind() &&
- LHS->isOrdinaryOrBitFieldObject() &&
- RHS->isOrdinaryOrBitFieldObject()) {
- VK = LHS->getValueKind();
- if (LHS->getObjectKind() == OK_BitField ||
- RHS->getObjectKind() == OK_BitField)
+ LHS.get()->isGLValue() &&
+ LHS.get()->getValueKind() == RHS.get()->getValueKind() &&
+ LHS.get()->isOrdinaryOrBitFieldObject() &&
+ RHS.get()->isOrdinaryOrBitFieldObject()) {
+ VK = LHS.get()->getValueKind();
+ if (LHS.get()->getObjectKind() == OK_BitField ||
+ RHS.get()->getObjectKind() == OK_BitField)
OK = OK_BitField;
return LTy;
}
@@ -3106,10 +3461,12 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// C++0x 5.16p6
// LValue-to-rvalue, array-to-pointer, and function-to-pointer standard
// conversions are performed on the second and third operands.
- DefaultFunctionArrayLvalueConversion(LHS);
- DefaultFunctionArrayLvalueConversion(RHS);
- LTy = LHS->getType();
- RTy = RHS->getType();
+ LHS = DefaultFunctionArrayLvalueConversion(LHS.take());
+ RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
+ if (LHS.isInvalid() || RHS.isInvalid())
+ return QualType();
+ LTy = LHS.get()->getType();
+ RTy = RHS.get()->getType();
// After those conversions, one of the following shall hold:
// -- The second and third operands have the same type; the result
@@ -3123,18 +3480,18 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy);
ExprResult LHSCopy = PerformCopyInitialization(Entity,
SourceLocation(),
- Owned(LHS));
+ LHS);
if (LHSCopy.isInvalid())
return QualType();
ExprResult RHSCopy = PerformCopyInitialization(Entity,
SourceLocation(),
- Owned(RHS));
+ RHS);
if (RHSCopy.isInvalid())
return QualType();
- LHS = LHSCopy.takeAs<Expr>();
- RHS = RHSCopy.takeAs<Expr>();
+ LHS = LHSCopy;
+ RHS = RHSCopy;
}
return LTy;
@@ -3149,7 +3506,9 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// common type, and the result is of that type.
if (LTy->isArithmeticType() && RTy->isArithmeticType()) {
UsualArithmeticConversions(LHS, RHS);
- return LHS->getType();
+ if (LHS.isInvalid() || RHS.isInvalid())
+ return QualType();
+ return LHS.get()->getType();
}
// -- The second and third operands have pointer type, or one has pointer
@@ -3170,7 +3529,7 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
Diag(QuestionLoc,
diag::ext_typecheck_cond_incompatible_operands_nonstandard)
<< LTy << RTy << Composite
- << LHS->getSourceRange() << RHS->getSourceRange();
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return Composite;
}
@@ -3181,12 +3540,12 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
return Composite;
// Check if we are using a null with a non-pointer type.
- if (DiagnoseConditionalForNull(LHS, RHS, QuestionLoc))
+ if (DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc))
return QualType();
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
- << LHS->getType() << RHS->getType()
- << LHS->getSourceRange() << RHS->getSourceRange();
+ << LHS.get()->getType() << RHS.get()->getType()
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
@@ -3224,16 +3583,16 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
// the type of the other operand.
if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
if (T2->isMemberPointerType())
- ImpCastExprToType(E1, T2, CK_NullToMemberPointer);
+ E1 = ImpCastExprToType(E1, T2, CK_NullToMemberPointer).take();
else
- ImpCastExprToType(E1, T2, CK_NullToPointer);
+ E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).take();
return T2;
}
if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
if (T1->isMemberPointerType())
- ImpCastExprToType(E2, T1, CK_NullToMemberPointer);
+ E2 = ImpCastExprToType(E2, T1, CK_NullToMemberPointer).take();
else
- ImpCastExprToType(E2, T1, CK_NullToPointer);
+ E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).take();
return T1;
}
@@ -3763,7 +4122,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
ASTTemplateArgsPtr TemplateArgsPtr(*this,
TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
- TypeResult T = ActOnTemplateIdType(TemplateId->Template,
+ TypeResult T = ActOnTemplateIdType(TemplateId->SS,
+ TemplateId->Template,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
@@ -3811,7 +4171,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
ASTTemplateArgsPtr TemplateArgsPtr(*this,
TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
- TypeResult T = ActOnTemplateIdType(TemplateId->Template,
+ TypeResult T = ActOnTemplateIdType(TemplateId->SS,
+ TemplateId->Template,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
@@ -3834,24 +4195,25 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
Destructed, HasTrailingLParen);
}
-ExprResult Sema::BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
+ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
CXXMethodDecl *Method) {
- if (PerformObjectArgumentInitialization(Exp, /*Qualifier=*/0,
- FoundDecl, Method))
+ ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/0,
+ FoundDecl, Method);
+ if (Exp.isInvalid())
return true;
MemberExpr *ME =
- new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method,
+ new (Context) MemberExpr(Exp.take(), /*IsArrow=*/false, Method,
SourceLocation(), Method->getType(),
VK_RValue, OK_Ordinary);
QualType ResultType = Method->getResultType();
ExprValueKind VK = Expr::getValueKindForType(ResultType);
ResultType = ResultType.getNonLValueExprType(Context);
- MarkDeclarationReferenced(Exp->getLocStart(), Method);
+ MarkDeclarationReferenced(Exp.get()->getLocStart(), Method);
CXXMemberCallExpr *CE =
new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK,
- Exp->getLocEnd());
+ Exp.get()->getLocEnd());
return CE;
}
@@ -3869,46 +4231,62 @@ ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation,
/// Perform the conversions required for an expression used in a
/// context that ignores the result.
-void Sema::IgnoredValueConversions(Expr *&E) {
+ExprResult Sema::IgnoredValueConversions(Expr *E) {
// C99 6.3.2.1:
// [Except in specific positions,] an lvalue that does not have
// array type is converted to the value stored in the
// designated object (and is no longer an lvalue).
- if (E->isRValue()) return;
+ if (E->isRValue()) return Owned(E);
// We always want to do this on ObjC property references.
if (E->getObjectKind() == OK_ObjCProperty) {
- ConvertPropertyForRValue(E);
- if (E->isRValue()) return;
+ ExprResult Res = ConvertPropertyForRValue(E);
+ if (Res.isInvalid()) return Owned(E);
+ E = Res.take();
+ if (E->isRValue()) return Owned(E);
}
// Otherwise, this rule does not apply in C++, at least not for the moment.
- if (getLangOptions().CPlusPlus) return;
+ if (getLangOptions().CPlusPlus) return Owned(E);
// GCC seems to also exclude expressions of incomplete enum type.
if (const EnumType *T = E->getType()->getAs<EnumType>()) {
if (!T->getDecl()->isComplete()) {
// FIXME: stupid workaround for a codegen bug!
- ImpCastExprToType(E, Context.VoidTy, CK_ToVoid);
- return;
+ E = ImpCastExprToType(E, Context.VoidTy, CK_ToVoid).take();
+ return Owned(E);
}
}
- DefaultFunctionArrayLvalueConversion(E);
+ ExprResult Res = DefaultFunctionArrayLvalueConversion(E);
+ if (Res.isInvalid())
+ return Owned(E);
+ E = Res.take();
+
if (!E->getType()->isVoidType())
RequireCompleteType(E->getExprLoc(), E->getType(),
diag::err_incomplete_type);
+ return Owned(E);
}
-ExprResult Sema::ActOnFinishFullExpr(Expr *FullExpr) {
- if (!FullExpr)
+ExprResult Sema::ActOnFinishFullExpr(Expr *FE) {
+ ExprResult FullExpr = Owned(FE);
+
+ if (!FullExpr.get())
+ return ExprError();
+
+ if (DiagnoseUnexpandedParameterPack(FullExpr.get()))
+ return ExprError();
+
+ FullExpr = CheckPlaceholderExpr(FullExpr.take());
+ if (FullExpr.isInvalid())
return ExprError();
- if (DiagnoseUnexpandedParameterPack(FullExpr))
+ FullExpr = IgnoredValueConversions(FullExpr.take());
+ if (FullExpr.isInvalid())
return ExprError();
- IgnoredValueConversions(FullExpr);
- CheckImplicitConversions(FullExpr);
+ CheckImplicitConversions(FullExpr.get());
return MaybeCreateExprWithCleanups(FullExpr);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
index 4d03b06..2a262f0 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
@@ -62,7 +62,8 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
// Create the aggregate string with the appropriate content and location
// information.
- S = StringLiteral::Create(Context, &StrBuf[0], StrBuf.size(), false,
+ S = StringLiteral::Create(Context, &StrBuf[0], StrBuf.size(),
+ /*Wide=*/false, /*Pascal=*/false,
Context.getPointerType(Context.CharTy),
&StrLocs[0], StrLocs.size());
}
@@ -246,7 +247,10 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
if (Args[i]->isTypeDependent())
continue;
- DefaultArgumentPromotion(Args[i]);
+ ExprResult Result = DefaultArgumentPromotion(Args[i]);
+ if (Result.isInvalid())
+ return true;
+ Args[i] = Result.take();
}
unsigned DiagID = isClassMessage ? diag::warn_class_method_not_found :
@@ -305,7 +309,9 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
if (Args[i]->isTypeDependent())
continue;
- IsError |= DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0);
+ ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0);
+ IsError |= Arg.isInvalid();
+ Args[i] = Arg.take();
}
} else {
// Check for extra arguments to non-variadic methods.
@@ -318,12 +324,24 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
Args[NumArgs-1]->getLocEnd());
}
}
+ // diagnose nonnull arguments.
+ for (specific_attr_iterator<NonNullAttr>
+ i = Method->specific_attr_begin<NonNullAttr>(),
+ e = Method->specific_attr_end<NonNullAttr>(); i != e; ++i) {
+ CheckNonNullArguments(*i, Args, lbrac);
+ }
DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs);
return IsError;
}
bool Sema::isSelfExpr(Expr *RExpr) {
+ // 'self' is objc 'self' in an objc method only.
+ DeclContext *DC = CurContext;
+ while (isa<BlockDecl>(DC))
+ DC = DC->getParent();
+ if (DC && !isa<ObjCMethodDecl>(DC))
+ return false;
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RExpr))
if (ICE->getCastKind() == CK_LValueToRValue)
RExpr = ICE->getSubExpr();
@@ -381,6 +399,23 @@ ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel,
return Method;
}
+/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier
+/// list of a qualified objective pointer type.
+ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel,
+ const ObjCObjectPointerType *OPT,
+ bool Instance)
+{
+ ObjCMethodDecl *MD = 0;
+ for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
+ E = OPT->qual_end(); I != E; ++I) {
+ ObjCProtocolDecl *PROTO = (*I);
+ if ((MD = PROTO->lookupMethod(Sel, Instance))) {
+ return MD;
+ }
+ }
+ return 0;
+}
+
/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an
/// objective C interface. This is a property reference expression.
ExprResult Sema::
@@ -391,6 +426,13 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
bool Super) {
const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();
ObjCInterfaceDecl *IFace = IFaceT->getDecl();
+
+ if (MemberName.getNameKind() != DeclarationName::Identifier) {
+ Diag(MemberLoc, diag::err_invalid_property_name)
+ << MemberName << QualType(OPT, 0);
+ return ExprError();
+ }
+
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
if (IFace->isForwardDecl()) {
@@ -405,6 +447,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
if (DiagnoseUseOfDecl(PD, MemberLoc))
return ExprError();
QualType ResTy = PD->getType();
+ ResTy = ResTy.getNonLValueExprType(Context);
Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc))
@@ -448,6 +491,10 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
+
+ // May be founf in property's qualified list.
+ if (!Getter)
+ Getter = LookupMethodInQualifiedType(Sel, OPT, true);
// If this reference is in an @implementation, check for 'private' methods.
if (!Getter)
@@ -467,6 +514,11 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
SelectorTable::constructSetterName(PP.getIdentifierTable(),
PP.getSelectorTable(), Member);
ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
+
+ // May be founf in property's qualified list.
+ if (!Setter)
+ Setter = LookupMethodInQualifiedType(SetterSel, OPT, true);
+
if (!Setter) {
// If this reference is in an @implementation, also check for 'private'
// methods.
@@ -475,7 +527,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
// Look through local category implementations associated with the class.
if (!Setter)
Setter = IFace->getCategoryInstanceMethod(SetterSel);
-
+
if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
return ExprError();
@@ -868,7 +920,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
return ExprError();
}
assert(Class && "We don't know which class we're messaging?");
-
+ (void)DiagnoseUseOfDecl(Class, Loc);
// Find the method we are messaging.
if (!Method) {
if (Class->isForwardDecl()) {
@@ -1007,7 +1059,10 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// If necessary, apply function/array conversion to the receiver.
// C99 6.7.5.3p[7,8].
- DefaultFunctionArrayLvalueConversion(Receiver);
+ ExprResult Result = DefaultFunctionArrayLvalueConversion(Receiver);
+ if (Result.isInvalid())
+ return ExprError();
+ Receiver = Result.take();
ReceiverType = Receiver->getType();
}
@@ -1026,39 +1081,53 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
} else if (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType()) {
// Handle messages to Class.
- if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
- if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
- // First check the public methods in the class interface.
- Method = ClassDecl->lookupClassMethod(Sel);
-
- if (!Method)
- Method = LookupPrivateClassMethod(Sel, ClassDecl);
+ // We allow sending a message to a qualified Class ("Class<foo>"), which
+ // is ok as long as one of the protocols implements the selector (if not, warn).
+ if (const ObjCObjectPointerType *QClassTy
+ = ReceiverType->getAsObjCQualifiedClassType()) {
+ // Search protocols for class methods.
+ Method = LookupMethodInQualifiedType(Sel, QClassTy, false);
+ if (!Method) {
+ Method = LookupMethodInQualifiedType(Sel, QClassTy, true);
+ // warn if instance method found for a Class message.
+ if (Method) {
+ Diag(Loc, diag::warn_instance_method_on_class_found)
+ << Method->getSelector() << Sel;
+ Diag(Method->getLocation(), diag::note_method_declared_at);
+ }
+ }
+ } else {
+ if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
+ if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
+ // First check the public methods in the class interface.
+ Method = ClassDecl->lookupClassMethod(Sel);
- // FIXME: if we still haven't found a method, we need to look in
- // protocols (if we have qualifiers).
+ if (!Method)
+ Method = LookupPrivateClassMethod(Sel, ClassDecl);
+ }
+ if (Method && DiagnoseUseOfDecl(Method, Loc))
+ return ExprError();
}
- if (Method && DiagnoseUseOfDecl(Method, Loc))
- return ExprError();
- }
- if (!Method) {
- // If not messaging 'self', look for any factory method named 'Sel'.
- if (!Receiver || !isSelfExpr(Receiver)) {
- Method = LookupFactoryMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc),
- true);
- if (!Method) {
- // If no class (factory) method was found, check if an _instance_
- // method of the same name exists in the root class only.
- Method = LookupInstanceMethodInGlobalPool(Sel,
+ if (!Method) {
+ // If not messaging 'self', look for any factory method named 'Sel'.
+ if (!Receiver || !isSelfExpr(Receiver)) {
+ Method = LookupFactoryMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc),
+ true);
+ if (!Method) {
+ // If no class (factory) method was found, check if an _instance_
+ // method of the same name exists in the root class only.
+ Method = LookupInstanceMethodInGlobalPool(Sel,
SourceRange(LBracLoc, RBracLoc),
- true);
- if (Method)
- if (const ObjCInterfaceDecl *ID =
- dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
- if (ID->getSuperClass())
- Diag(Loc, diag::warn_root_inst_method_not_found)
- << Sel << SourceRange(LBracLoc, RBracLoc);
- }
+ true);
+ if (Method)
+ if (const ObjCInterfaceDecl *ID =
+ dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
+ if (ID->getSuperClass())
+ Diag(Loc, diag::warn_root_inst_method_not_found)
+ << Sel << SourceRange(LBracLoc, RBracLoc);
+ }
+ }
}
}
}
@@ -1070,15 +1139,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (const ObjCObjectPointerType *QIdTy
= ReceiverType->getAsObjCQualifiedIdType()) {
// Search protocols for instance methods.
- for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
- E = QIdTy->qual_end(); I != E; ++I) {
- ObjCProtocolDecl *PDecl = *I;
- if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
- break;
- // Since we aren't supporting "Class<foo>", look for a class method.
- if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
- break;
- }
+ Method = LookupMethodInQualifiedType(Sel, QIdTy, true);
+ if (!Method)
+ Method = LookupMethodInQualifiedType(Sel, QIdTy, false);
} else if (const ObjCObjectPointerType *OCIType
= ReceiverType->getAsObjCInterfacePointerType()) {
// We allow sending a message to a pointer to an interface (an object).
@@ -1088,15 +1151,11 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// The idea is to add class info to MethodPool.
Method = ClassDecl->lookupInstanceMethod(Sel);
- if (!Method) {
+ if (!Method)
// Search protocol qualifiers.
- for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(),
- E = OCIType->qual_end(); QI != E; ++QI) {
- if ((Method = (*QI)->lookupInstanceMethod(Sel)))
- break;
- }
- }
- bool forwardClass = false;
+ Method = LookupMethodInQualifiedType(Sel, OCIType, true);
+
+ const ObjCInterfaceDecl *forwardClass = 0;
if (!Method) {
// If we have implementations in scope, check "private" methods.
Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
@@ -1108,7 +1167,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (OCIType->qual_empty()) {
Method = LookupInstanceMethodInGlobalPool(Sel,
SourceRange(LBracLoc, RBracLoc));
- forwardClass = OCIType->getInterfaceDecl()->isForwardDecl();
+ if (OCIType->getInterfaceDecl()->isForwardDecl())
+ forwardClass = OCIType->getInterfaceDecl();
if (Method && !forwardClass)
Diag(Loc, diag::warn_maynot_respond)
<< OCIType->getInterfaceDecl()->getIdentifier() << Sel;
@@ -1125,37 +1185,42 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
<< ReceiverType
<< Receiver->getSourceRange();
if (ReceiverType->isPointerType())
- ImpCastExprToType(Receiver, Context.getObjCIdType(),
- CK_BitCast);
+ Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
+ CK_BitCast).take();
else {
// TODO: specialized warning on null receivers?
bool IsNull = Receiver->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull);
- ImpCastExprToType(Receiver, Context.getObjCIdType(),
- IsNull ? CK_NullToPointer : CK_IntegralToPointer);
+ Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
+ IsNull ? CK_NullToPointer : CK_IntegralToPointer).take();
}
ReceiverType = Receiver->getType();
}
- else if (getLangOptions().CPlusPlus &&
- !PerformContextuallyConvertToObjCId(Receiver)) {
- if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Receiver)) {
- Receiver = ICE->getSubExpr();
- ReceiverType = Receiver->getType();
+ else {
+ ExprResult ReceiverRes;
+ if (getLangOptions().CPlusPlus)
+ ReceiverRes = PerformContextuallyConvertToObjCId(Receiver);
+ if (ReceiverRes.isUsable()) {
+ Receiver = ReceiverRes.take();
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Receiver)) {
+ Receiver = ICE->getSubExpr();
+ ReceiverType = Receiver->getType();
+ }
+ return BuildInstanceMessage(Receiver,
+ ReceiverType,
+ SuperLoc,
+ Sel,
+ Method,
+ LBracLoc,
+ SelectorLoc,
+ RBracLoc,
+ move(ArgsIn));
+ } else {
+ // Reject other random receiver types (e.g. structs).
+ Diag(Loc, diag::err_bad_receiver_type)
+ << ReceiverType << Receiver->getSourceRange();
+ return ExprError();
}
- return BuildInstanceMessage(Receiver,
- ReceiverType,
- SuperLoc,
- Sel,
- Method,
- LBracLoc,
- SelectorLoc,
- RBracLoc,
- move(ArgsIn));
- } else {
- // Reject other random receiver types (e.g. structs).
- Diag(Loc, diag::err_bad_receiver_type)
- << ReceiverType << Receiver->getSourceRange();
- return ExprError();
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
index 5882da0..ca3fd6d 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -92,13 +92,31 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
- // C99 6.7.8p14. We have an array of character type with known size. However,
+ // We have an array of character type with known size. However,
// the size may be smaller or larger than the string we are initializing.
// FIXME: Avoid truncation for 64-bit length strings.
- if (StrLength-1 > CAT->getSize().getZExtValue())
- S.Diag(Str->getSourceRange().getBegin(),
- diag::warn_initializer_string_for_char_array_too_long)
- << Str->getSourceRange();
+ if (S.getLangOptions().CPlusPlus) {
+ if (StringLiteral *SL = dyn_cast<StringLiteral>(Str)) {
+ // For Pascal strings it's OK to strip off the terminating null character,
+ // so the example below is valid:
+ //
+ // unsigned char a[2] = "\pa";
+ if (SL->isPascal())
+ StrLength--;
+ }
+
+ // [dcl.init.string]p2
+ if (StrLength > CAT->getSize().getZExtValue())
+ S.Diag(Str->getSourceRange().getBegin(),
+ diag::err_initializer_string_for_char_array_too_long)
+ << Str->getSourceRange();
+ } else {
+ // C99 6.7.8p14.
+ if (StrLength-1 > CAT->getSize().getZExtValue())
+ S.Diag(Str->getSourceRange().getBegin(),
+ diag::warn_initializer_string_for_char_array_too_long)
+ << Str->getSourceRange();
+ }
// Set the type to the actual size that we are initializing. If we have
// something like:
@@ -386,15 +404,29 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
if (hadError) {
// Do nothing
} else if (Init < NumInits) {
- ILE->setInit(Init, ElementInit.takeAs<Expr>());
- } else if (InitSeq.getKind()
+ // For arrays, just set the expression used for value-initialization
+ // of the "holes" in the array.
+ if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement)
+ ILE->setArrayFiller(ElementInit.takeAs<Expr>());
+ else
+ ILE->setInit(Init, ElementInit.takeAs<Expr>());
+ } else {
+ // For arrays, just set the expression used for value-initialization
+ // of the rest of elements and exit.
+ if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) {
+ ILE->setArrayFiller(ElementInit.takeAs<Expr>());
+ return;
+ }
+
+ if (InitSeq.getKind()
== InitializationSequence::ConstructorInitialization) {
- // Value-initialization requires a constructor call, so
- // extend the initializer list to include the constructor
- // call and make a note that we'll need to take another pass
- // through the initializer list.
- ILE->updateInit(SemaRef.Context, Init, ElementInit.takeAs<Expr>());
- RequiresSecondPass = true;
+ // Value-initialization requires a constructor call, so
+ // extend the initializer list to include the constructor
+ // call and make a note that we'll need to take another pass
+ // through the initializer list.
+ ILE->updateInit(SemaRef.Context, Init, ElementInit.takeAs<Expr>());
+ RequiresSecondPass = true;
+ }
}
} else if (InitListExpr *InnerILE
= dyn_cast<InitListExpr>(ILE->getInit(Init)))
@@ -713,15 +745,23 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// compatible structure or union type. In the latter case, the
// initial value of the object, including unnamed members, is
// that of the expression.
+ ExprResult ExprRes = SemaRef.Owned(expr);
if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
- SemaRef.CheckSingleAssignmentConstraints(ElemType, expr)
+ SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes)
== Sema::Compatible) {
- SemaRef.DefaultFunctionArrayLvalueConversion(expr);
- UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+ if (ExprRes.isInvalid())
+ hadError = true;
+ else {
+ ExprRes = SemaRef.DefaultFunctionArrayLvalueConversion(ExprRes.take());
+ if (ExprRes.isInvalid())
+ hadError = true;
+ }
+ UpdateStructuredListElement(StructuredList, StructuredIndex,
+ ExprRes.takeAs<Expr>());
++Index;
return;
}
-
+ ExprRes.release();
// Fall through for subaggregate initialization
}
@@ -1755,11 +1795,15 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
// Pre-allocate storage for the structured initializer list.
unsigned NumElements = 0;
unsigned NumInits = 0;
- if (!StructuredList)
+ bool GotNumInits = false;
+ if (!StructuredList) {
NumInits = IList->getNumInits();
- else if (Index < IList->getNumInits()) {
- if (InitListExpr *SubList = dyn_cast<InitListExpr>(IList->getInit(Index)))
+ GotNumInits = true;
+ } else if (Index < IList->getNumInits()) {
+ if (InitListExpr *SubList = dyn_cast<InitListExpr>(IList->getInit(Index))) {
NumInits = SubList->getNumInits();
+ GotNumInits = true;
+ }
}
if (const ArrayType *AType
@@ -1768,7 +1812,7 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
NumElements = CAType->getSize().getZExtValue();
// Simple heuristic so that we don't allocate a very large
// initializer with many empty entries at the end.
- if (NumInits && NumElements > NumInits)
+ if (GotNumInits && NumElements > NumInits)
NumElements = 0;
}
} else if (const VectorType *VType = CurrentObjectType->getAs<VectorType>())
@@ -1936,6 +1980,9 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
Loc, GNUSyntax, Init.takeAs<Expr>());
if (getLangOptions().CPlusPlus)
+ Diag(DIE->getLocStart(), diag::ext_designated_init_cxx)
+ << DIE->getSourceRange();
+ else if (!getLangOptions().C99)
Diag(DIE->getLocStart(), diag::ext_designated_init)
<< DIE->getSourceRange();
@@ -1998,6 +2045,7 @@ DeclarationName InitializedEntity::getName() const {
case EK_New:
case EK_Temporary:
case EK_Base:
+ case EK_Delegating:
case EK_ArrayElement:
case EK_VectorElement:
case EK_BlockElement:
@@ -2020,6 +2068,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const {
case EK_New:
case EK_Temporary:
case EK_Base:
+ case EK_Delegating:
case EK_ArrayElement:
case EK_VectorElement:
case EK_BlockElement:
@@ -2042,6 +2091,7 @@ bool InitializedEntity::allowsNRVO() const {
case EK_New:
case EK_Temporary:
case EK_Base:
+ case EK_Delegating:
case EK_ArrayElement:
case EK_VectorElement:
case EK_BlockElement:
@@ -2101,6 +2151,7 @@ bool InitializationSequence::isAmbiguous() const {
case FK_ReferenceInitDropsQualifiers:
case FK_ReferenceInitFailed:
case FK_ConversionFailed:
+ case FK_ConversionFromPropertyFailed:
case FK_TooManyInitsForScalar:
case FK_ReferenceBindingToInitList:
case FK_InitListBadDestinationType:
@@ -3126,8 +3177,14 @@ InitializationSequence::InitializationSequence(Sema &S,
}
for (unsigned I = 0; I != NumArgs; ++I)
- if (Args[I]->getObjectKind() == OK_ObjCProperty)
- S.ConvertPropertyForRValue(Args[I]);
+ if (Args[I]->getObjectKind() == OK_ObjCProperty) {
+ ExprResult Result = S.ConvertPropertyForRValue(Args[I]);
+ if (Result.isInvalid()) {
+ SetFailed(FK_ConversionFromPropertyFailed);
+ return;
+ }
+ Args[I] = Result.take();
+ }
QualType SourceType;
Expr *Initializer = 0;
@@ -3289,6 +3346,7 @@ getAssignmentAction(const InitializedEntity &Entity) {
case InitializedEntity::EK_New:
case InitializedEntity::EK_Exception:
case InitializedEntity::EK_Base:
+ case InitializedEntity::EK_Delegating:
return Sema::AA_Initializing;
case InitializedEntity::EK_Parameter:
@@ -3325,6 +3383,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_New:
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Base:
+ case InitializedEntity::EK_Delegating:
case InitializedEntity::EK_VectorElement:
case InitializedEntity::EK_Exception:
case InitializedEntity::EK_BlockElement:
@@ -3346,6 +3405,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_Result:
case InitializedEntity::EK_New:
case InitializedEntity::EK_Base:
+ case InitializedEntity::EK_Delegating:
case InitializedEntity::EK_VectorElement:
case InitializedEntity::EK_BlockElement:
return false;
@@ -3430,6 +3490,7 @@ static ExprResult CopyObject(Sema &S,
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_New:
case InitializedEntity::EK_Base:
+ case InitializedEntity::EK_Delegating:
case InitializedEntity::EK_VectorElement:
case InitializedEntity::EK_BlockElement:
Loc = CurInitExpr->getLocStart();
@@ -3686,14 +3747,15 @@ InitializationSequence::Perform(Sema &S,
case SK_ObjCObjectConversion:
case SK_ArrayInit: {
assert(Args.size() == 1);
- Expr *CurInitExpr = Args.get()[0];
- if (!CurInitExpr) return ExprError();
+ CurInit = Args.get()[0];
+ if (!CurInit.get()) return ExprError();
// Read from a property when initializing something with it.
- if (CurInitExpr->getObjectKind() == OK_ObjCProperty)
- S.ConvertPropertyForRValue(CurInitExpr);
-
- CurInit = ExprResult(CurInitExpr);
+ if (CurInit.get()->getObjectKind() == OK_ObjCProperty) {
+ CurInit = S.ConvertPropertyForRValue(CurInit.take());
+ if (CurInit.isInvalid())
+ return ExprError();
+ }
break;
}
@@ -3710,14 +3772,13 @@ InitializationSequence::Perform(Sema &S,
if (CurInit.isInvalid())
return ExprError();
- Expr *CurInitExpr = CurInit.get();
- QualType SourceType = CurInitExpr? CurInitExpr->getType() : QualType();
+ QualType SourceType = CurInit.get() ? CurInit.get()->getType() : QualType();
switch (Step->Kind) {
case SK_ResolveAddressOfOverloadedFunction:
// Overload resolution determined which function invoke; update the
// initializer to reflect that choice.
- S.CheckAddressOfMemberAccess(CurInitExpr, Step->Function.FoundDecl);
+ S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl);
S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation());
CurInit = S.FixOverloadedFunctionReference(move(CurInit),
Step->Function.FoundDecl,
@@ -3735,8 +3796,8 @@ InitializationSequence::Perform(Sema &S,
// Casts to inaccessible base classes are allowed with C-style casts.
bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
if (S.CheckDerivedToBaseConversion(SourceType, Step->Type,
- CurInitExpr->getLocStart(),
- CurInitExpr->getSourceRange(),
+ CurInit.get()->getLocStart(),
+ CurInit.get()->getSourceRange(),
&BasePath, IgnoreBaseAccess))
return ExprError();
@@ -3745,7 +3806,7 @@ InitializationSequence::Perform(Sema &S,
if (const PointerType *Pointer = T->getAs<PointerType>())
T = Pointer->getPointeeType();
if (const RecordType *RecordTy = T->getAs<RecordType>())
- S.MarkVTableUsed(CurInitExpr->getLocStart(),
+ S.MarkVTableUsed(CurInit.get()->getLocStart(),
cast<CXXRecordDecl>(RecordTy->getDecl()));
}
@@ -3764,21 +3825,21 @@ InitializationSequence::Perform(Sema &S,
}
case SK_BindReference:
- if (FieldDecl *BitField = CurInitExpr->getBitField()) {
+ if (FieldDecl *BitField = CurInit.get()->getBitField()) {
// References cannot bind to bit fields (C++ [dcl.init.ref]p5).
S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
<< Entity.getType().isVolatileQualified()
<< BitField->getDeclName()
- << CurInitExpr->getSourceRange();
+ << CurInit.get()->getSourceRange();
S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
return ExprError();
}
- if (CurInitExpr->refersToVectorElement()) {
+ if (CurInit.get()->refersToVectorElement()) {
// References cannot bind to vector elements.
S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element)
<< Entity.getType().isVolatileQualified()
- << CurInitExpr->getSourceRange();
+ << CurInit.get()->getSourceRange();
PrintInitLocationNote(S, Entity);
return ExprError();
}
@@ -3786,7 +3847,7 @@ InitializationSequence::Perform(Sema &S,
// Reference binding does not have any corresponding ASTs.
// Check exception specifications
- if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType))
+ if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
return ExprError();
break;
@@ -3795,7 +3856,7 @@ InitializationSequence::Perform(Sema &S,
// Reference binding does not have any corresponding ASTs.
// Check exception specifications
- if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType))
+ if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
return ExprError();
break;
@@ -3817,13 +3878,14 @@ InitializationSequence::Perform(Sema &S,
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) {
// Build a call to the selected constructor.
ASTOwningVector<Expr*> ConstructorArgs(S);
- SourceLocation Loc = CurInitExpr->getLocStart();
+ SourceLocation Loc = CurInit.get()->getLocStart();
CurInit.release(); // Ownership transferred into MultiExprArg, below.
// Determine the arguments required to actually perform the constructor
// call.
+ Expr *Arg = CurInit.get();
if (S.CompleteConstructorCall(Constructor,
- MultiExprArg(&CurInitExpr, 1),
+ MultiExprArg(&Arg, 1),
Loc, ConstructorArgs))
return ExprError();
@@ -3851,23 +3913,22 @@ InitializationSequence::Perform(Sema &S,
// Build a call to the conversion function.
CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
IsLvalue = Conversion->getResultType()->isLValueReferenceType();
- S.CheckMemberOperatorAccess(Kind.getLocation(), CurInitExpr, 0,
+ S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), 0,
FoundFn);
S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation());
// FIXME: Should we move this initialization into a separate
// derived-to-base conversion? I believe the answer is "no", because
// we don't want to turn off access control here for c-style casts.
- if (S.PerformObjectArgumentInitialization(CurInitExpr, /*Qualifier=*/0,
- FoundFn, Conversion))
+ ExprResult CurInitExprRes =
+ S.PerformObjectArgumentInitialization(CurInit.take(), /*Qualifier=*/0,
+ FoundFn, Conversion);
+ if(CurInitExprRes.isInvalid())
return ExprError();
-
- // Do a little dance to make sure that CurInit has the proper
- // pointer.
- CurInit.release();
+ CurInit = move(CurInitExprRes);
// Build the actual call to the conversion function.
- CurInit = S.BuildCXXMemberCallExpr(CurInitExpr, FoundFn, Conversion);
+ CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion);
if (CurInit.isInvalid() || !CurInit.get())
return ExprError();
@@ -3881,23 +3942,21 @@ InitializationSequence::Perform(Sema &S,
if (RequiresCopy || shouldBindAsTemporary(Entity))
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
else if (CreatedObject && shouldDestroyTemporary(Entity)) {
- CurInitExpr = static_cast<Expr *>(CurInit.get());
- QualType T = CurInitExpr->getType();
+ QualType T = CurInit.get()->getType();
if (const RecordType *Record = T->getAs<RecordType>()) {
CXXDestructorDecl *Destructor
= S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl()));
- S.CheckDestructorAccess(CurInitExpr->getLocStart(), Destructor,
+ S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor,
S.PDiag(diag::err_access_dtor_temp) << T);
- S.MarkDeclarationReferenced(CurInitExpr->getLocStart(), Destructor);
- S.DiagnoseUseOfDecl(Destructor, CurInitExpr->getLocStart());
+ S.MarkDeclarationReferenced(CurInit.get()->getLocStart(), Destructor);
+ S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart());
}
}
- CurInitExpr = CurInit.takeAs<Expr>();
// FIXME: xvalues
CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
- CurInitExpr->getType(),
- CastKind, CurInitExpr, 0,
+ CurInit.get()->getType(),
+ CastKind, CurInit.get(), 0,
IsLvalue ? VK_LValue : VK_RValue));
if (RequiresCopy)
@@ -3917,25 +3976,23 @@ InitializationSequence::Perform(Sema &S,
(Step->Kind == SK_QualificationConversionXValue ?
VK_XValue :
VK_RValue);
- S.ImpCastExprToType(CurInitExpr, Step->Type, CK_NoOp, VK);
- CurInit.release();
- CurInit = S.Owned(CurInitExpr);
+ CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type, CK_NoOp, VK);
break;
}
case SK_ConversionSequence: {
- if (S.PerformImplicitConversion(CurInitExpr, Step->Type, *Step->ICS,
- getAssignmentAction(Entity),
- Kind.isCStyleOrFunctionalCast()))
+ ExprResult CurInitExprRes =
+ S.PerformImplicitConversion(CurInit.get(), Step->Type, *Step->ICS,
+ getAssignmentAction(Entity),
+ Kind.isCStyleOrFunctionalCast());
+ if (CurInitExprRes.isInvalid())
return ExprError();
-
- CurInit.release();
- CurInit = S.Owned(CurInitExpr);
+ CurInit = move(CurInitExprRes);
break;
}
case SK_ListInitialization: {
- InitListExpr *InitList = cast<InitListExpr>(CurInitExpr);
+ InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
QualType Ty = Step->Type;
if (S.CheckInitList(Entity, InitList, ResultType? *ResultType : Ty))
return ExprError();
@@ -4004,6 +4061,9 @@ InitializationSequence::Perform(Sema &S,
CXXConstructExpr::CK_VirtualBase :
CXXConstructExpr::CK_NonVirtualBase;
}
+ if (Entity.getKind() == InitializedEntity::EK_Delegating) {
+ ConstructKind = CXXConstructExpr::CK_Delegating;
+ }
// Only get the parenthesis range if it is a direct construction.
SourceRange parenRange =
@@ -4068,54 +4128,57 @@ InitializationSequence::Perform(Sema &S,
}
case SK_CAssignment: {
- QualType SourceType = CurInitExpr->getType();
+ QualType SourceType = CurInit.get()->getType();
+ ExprResult Result = move(CurInit);
Sema::AssignConvertType ConvTy =
- S.CheckSingleAssignmentConstraints(Step->Type, CurInitExpr);
+ S.CheckSingleAssignmentConstraints(Step->Type, Result);
+ if (Result.isInvalid())
+ return ExprError();
+ CurInit = move(Result);
// If this is a call, allow conversion to a transparent union.
+ ExprResult CurInitExprRes = move(CurInit);
if (ConvTy != Sema::Compatible &&
Entity.getKind() == InitializedEntity::EK_Parameter &&
- S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExpr)
+ S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExprRes)
== Sema::Compatible)
ConvTy = Sema::Compatible;
+ if (CurInitExprRes.isInvalid())
+ return ExprError();
+ CurInit = move(CurInitExprRes);
bool Complained;
if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(),
Step->Type, SourceType,
- CurInitExpr,
+ CurInit.get(),
getAssignmentAction(Entity),
&Complained)) {
PrintInitLocationNote(S, Entity);
return ExprError();
} else if (Complained)
PrintInitLocationNote(S, Entity);
-
- CurInit.release();
- CurInit = S.Owned(CurInitExpr);
break;
}
case SK_StringInit: {
QualType Ty = Step->Type;
- CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty,
+ CheckStringInit(CurInit.get(), ResultType ? *ResultType : Ty,
S.Context.getAsArrayType(Ty), S);
break;
}
case SK_ObjCObjectConversion:
- S.ImpCastExprToType(CurInitExpr, Step->Type,
+ CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type,
CK_ObjCObjectLValueCast,
- S.CastCategory(CurInitExpr));
- CurInit.release();
- CurInit = S.Owned(CurInitExpr);
+ S.CastCategory(CurInit.get()));
break;
case SK_ArrayInit:
// Okay: we checked everything before creating this step. Note that
// this is a GNU extension.
S.Diag(Kind.getLocation(), diag::ext_array_init_copy)
- << Step->Type << CurInitExpr->getType()
- << CurInitExpr->getSourceRange();
+ << Step->Type << CurInit.get()->getType()
+ << CurInit.get()->getSourceRange();
// If the destination type is an incomplete array type, update the
// type accordingly.
@@ -4123,7 +4186,7 @@ InitializationSequence::Perform(Sema &S,
if (const IncompleteArrayType *IncompleteDest
= S.Context.getAsIncompleteArrayType(Step->Type)) {
if (const ConstantArrayType *ConstantSource
- = S.Context.getAsConstantArrayType(CurInitExpr->getType())) {
+ = S.Context.getAsConstantArrayType(CurInit.get()->getType())) {
*ResultType = S.Context.getConstantArrayType(
IncompleteDest->getElementType(),
ConstantSource->getSize(),
@@ -4283,6 +4346,11 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Args[0]->getSourceRange();
break;
}
+
+ case FK_ConversionFromPropertyFailed:
+ // No-op. This error has already been reported.
+ break;
+
case FK_TooManyInitsForScalar: {
SourceRange R;
@@ -4482,6 +4550,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
OS << "conversion failed";
break;
+ case FK_ConversionFromPropertyFailed:
+ OS << "conversion from property failed";
+ break;
+
case FK_TooManyInitsForScalar:
OS << "too many initializers for scalar";
break;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
index 3deb403..309c771 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
@@ -686,8 +686,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
// FIXME: Calling convention!
FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo();
EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_Default);
- EPI.HasExceptionSpec = false;
- EPI.HasAnyExceptionSpec = false;
+ EPI.ExceptionSpecType = EST_None;
EPI.NumExceptions = 0;
QualType ExpectedType
= R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(),
@@ -1130,8 +1129,8 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
// If we didn't find a use of this identifier, and if the identifier
// corresponds to a compiler builtin, create the decl object for the builtin
// now, injecting it into translation unit scope, and return it.
- if (AllowBuiltinCreation)
- return LookupBuiltin(*this, R);
+ if (AllowBuiltinCreation && LookupBuiltin(*this, R))
+ return true;
// If we didn't find a use of this identifier, the ExternalSource
// may be able to handle the situation.
@@ -1964,10 +1963,13 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
case Type::Complex:
break;
- // These are ignored by ADL.
+ // If T is an Objective-C object or interface type, or a pointer to an
+ // object or interface type, the associated namespace is the global
+ // namespace.
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
+ Result.Namespaces.insert(Result.S.Context.getTranslationUnitDecl());
break;
}
@@ -2203,7 +2205,8 @@ void ADLResult::insert(NamedDecl *New) {
void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
Expr **Args, unsigned NumArgs,
- ADLResult &Result) {
+ ADLResult &Result,
+ bool StdNamespaceIsAssociated) {
// Find all of the associated namespaces and classes based on the
// arguments we have.
AssociatedNamespaceSet AssociatedNamespaces;
@@ -2211,6 +2214,8 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
FindAssociatedClassesAndNamespaces(Args, NumArgs,
AssociatedNamespaces,
AssociatedClasses);
+ if (StdNamespaceIsAssociated && StdNamespace)
+ AssociatedNamespaces.insert(getStdNamespace());
QualType T1, T2;
if (Operator) {
@@ -2766,30 +2771,35 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
}
/// LookupOrCreateLabel - Do a name lookup of a label with the specified name.
-/// If isLocalLabel is true, then this is a definition of an __label__ label
-/// name, otherwise it is a normal label definition or use.
+/// If GnuLabelLoc is a valid source location, then this is a definition
+/// of an __label__ label name, otherwise it is a normal label definition
+/// or use.
LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- bool isLocalLabel) {
+ SourceLocation GnuLabelLoc) {
// Do a lookup to see if we have a label with this name already.
NamedDecl *Res = 0;
-
- // Local label definitions always shadow existing labels.
- if (!isLocalLabel)
- Res = LookupSingleName(CurScope, II, Loc, LookupLabel, NotForRedeclaration);
-
- // If we found a label, check to see if it is in the same context as us. When
- // in a Block, we don't want to reuse a label in an enclosing function.
+
+ if (GnuLabelLoc.isValid()) {
+ // Local label definitions always shadow existing labels.
+ Res = LabelDecl::Create(Context, CurContext, Loc, II, GnuLabelLoc);
+ Scope *S = CurScope;
+ PushOnScopeChains(Res, S, true);
+ return cast<LabelDecl>(Res);
+ }
+
+ // Not a GNU local label.
+ Res = LookupSingleName(CurScope, II, Loc, LookupLabel, NotForRedeclaration);
+ // If we found a label, check to see if it is in the same context as us.
+ // When in a Block, we don't want to reuse a label in an enclosing function.
if (Res && Res->getDeclContext() != CurContext)
Res = 0;
-
if (Res == 0) {
// If not forward referenced or defined already, create the backing decl.
Res = LabelDecl::Create(Context, CurContext, Loc, II);
- Scope *S = isLocalLabel ? CurScope : CurScope->getFnParent();
+ Scope *S = CurScope->getFnParent();
assert(S && "Not in a function?");
PushOnScopeChains(Res, S, true);
}
-
return cast<LabelDecl>(Res);
}
@@ -2853,8 +2863,6 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
}
void TypoCorrectionConsumer::FoundName(llvm::StringRef Name) {
- using namespace std;
-
// Use a simple length-based heuristic to determine the minimum possible
// edit distance. If the minimum isn't good enough, bail out early.
unsigned MinED = abs((int)Name.size() - (int)Typo.size());
@@ -2863,7 +2871,8 @@ void TypoCorrectionConsumer::FoundName(llvm::StringRef Name) {
// Compute an upper bound on the allowable edit distance, so that the
// edit-distance algorithm can short-circuit.
- unsigned UpperBound = min(unsigned((Typo.size() + 2) / 3), BestEditDistance);
+ unsigned UpperBound =
+ std::min(unsigned((Typo.size() + 2) / 3), BestEditDistance);
// Compute the edit distance between the typo and the name of this
// entity. If this edit distance is not worse than the best edit
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
index b086ca7..6c4469c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
@@ -45,11 +45,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
!(Attributes & ObjCDeclSpec::DQ_PR_copy)));
TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
- QualType T = TSI->getType();
- if (T->isReferenceType()) {
- Diag(AtLoc, diag::error_reference_property);
- return 0;
- }
+
// Proceed with constructing the ObjCPropertDecls.
ObjCContainerDecl *ClassDecl =
cast<ObjCContainerDecl>(ClassCategory);
@@ -404,12 +400,16 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
if (!PropertyIvar)
PropertyIvar = PropertyId;
QualType PropType = Context.getCanonicalType(property->getType());
+ QualType PropertyIvarType = PropType;
+ if (PropType->isReferenceType())
+ PropertyIvarType = cast<ReferenceType>(PropType)->getPointeeType();
// Check that this is a previously declared 'ivar' in 'IDecl' interface
ObjCInterfaceDecl *ClassDeclared;
Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
if (!Ivar) {
- Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, PropertyLoc,
- PropertyIvar, PropType, /*Dinfo=*/0,
+ Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
+ PropertyLoc, PropertyLoc, PropertyIvar,
+ PropertyIvarType, /*Dinfo=*/0,
ObjCIvarDecl::Private,
(Expr *)0, true);
ClassImpDecl->addDecl(Ivar);
@@ -432,19 +432,19 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
QualType IvarType = Context.getCanonicalType(Ivar->getType());
// Check that type of property and its ivar are type compatible.
- if (PropType != IvarType) {
+ if (PropertyIvarType != IvarType) {
bool compat = false;
- if (isa<ObjCObjectPointerType>(PropType)
+ if (isa<ObjCObjectPointerType>(PropertyIvarType)
&& isa<ObjCObjectPointerType>(IvarType))
compat =
Context.canAssignObjCInterfaces(
- PropType->getAs<ObjCObjectPointerType>(),
+ PropertyIvarType->getAs<ObjCObjectPointerType>(),
IvarType->getAs<ObjCObjectPointerType>());
else {
SourceLocation Loc = PropertyIvarLoc;
if (Loc.isInvalid())
Loc = PropertyLoc;
- compat = (CheckAssignmentConstraints(Loc, PropType, IvarType)
+ compat = (CheckAssignmentConstraints(Loc, PropertyIvarType, IvarType)
== Compatible);
}
if (!compat) {
@@ -459,7 +459,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// FIXME! Rules for properties are somewhat different that those
// for assignments. Use a new routine to consolidate all cases;
// specifically for property redeclarations as well as for ivars.
- QualType lhsType =Context.getCanonicalType(PropType).getUnqualifiedType();
+ QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
if (lhsType != rhsType &&
lhsType->isArithmeticType()) {
@@ -538,7 +538,10 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
SelfExpr, true, true);
ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
ParmVarDecl *Param = (*P);
- Expr *rhs = new (Context) DeclRefExpr(Param, Param->getType(),
+ QualType T = Param->getType();
+ if (T->isReferenceType())
+ T = T->getAs<ReferenceType>()->getPointeeType();
+ Expr *rhs = new (Context) DeclRefExpr(Param, T,
VK_LValue, SourceLocation());
ExprResult Res = BuildBinOp(S, lhs->getLocEnd(),
BO_Assign, lhs, rhs);
@@ -682,7 +685,7 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
/// ComparePropertiesInBaseAndSuper - This routine compares property
/// declarations in base and its super class, if any, and issues
-/// diagnostics in a variety of inconsistant situations.
+/// diagnostics in a variety of inconsistent situations.
///
void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) {
ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
@@ -1137,10 +1140,14 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
ObjCPropertyDecl *Property) {
// Should we just clone all attributes over?
- if (DeprecatedAttr *A = Property->getAttr<DeprecatedAttr>())
- PropertyMethod->addAttr(A->clone(S.Context));
- if (UnavailableAttr *A = Property->getAttr<UnavailableAttr>())
- PropertyMethod->addAttr(A->clone(S.Context));
+ for (Decl::attr_iterator A = Property->attr_begin(),
+ AEnd = Property->attr_end();
+ A != AEnd; ++A) {
+ if (isa<DeprecatedAttr>(*A) ||
+ isa<UnavailableAttr>(*A) ||
+ isa<AvailabilityAttr>(*A))
+ PropertyMethod->addAttr((*A)->clone(S.Context));
+ }
}
/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
@@ -1235,7 +1242,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
// Invent the arguments for the setter. We don't bother making a
// nice name for the argument.
- ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, Loc,
+ ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod,
+ Loc, Loc,
property->getIdentifier(),
property->getType(),
/*TInfo=*/0,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
index 8d03285..3f3ed0e 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
@@ -36,18 +36,26 @@ using namespace sema;
/// A convenience routine for creating a decayed reference to a
/// function.
-static Expr *
+static ExprResult
CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn,
SourceLocation Loc = SourceLocation()) {
- Expr *E = new (S.Context) DeclRefExpr(Fn, Fn->getType(), VK_LValue, Loc);
- S.DefaultFunctionArrayConversion(E);
- return E;
+ ExprResult E = S.Owned(new (S.Context) DeclRefExpr(Fn, Fn->getType(), VK_LValue, Loc));
+ E = S.DefaultFunctionArrayConversion(E.take());
+ if (E.isInvalid())
+ return ExprError();
+ return move(E);
}
static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
bool InOverloadResolution,
StandardConversionSequence &SCS,
bool CStyle);
+
+static bool IsTransparentUnionStandardConversion(Sema &S, Expr* From,
+ QualType &ToType,
+ bool InOverloadResolution,
+ StandardConversionSequence &SCS,
+ bool CStyle);
static OverloadingResult
IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
UserDefinedConversionSequence& User,
@@ -128,7 +136,9 @@ ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) {
ICR_Conversion,
ICR_Conversion,
ICR_Conversion,
- ICR_Complex_Real_Conversion
+ ICR_Complex_Real_Conversion,
+ ICR_Conversion,
+ ICR_Conversion
};
return Rank[(int)Kind];
}
@@ -157,7 +167,9 @@ const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
"Derived-to-base conversion",
"Vector conversion",
"Vector splat",
- "Complex-real conversion"
+ "Complex-real conversion",
+ "Block Pointer conversion",
+ "Transparent Union Conversion"
};
return Name[Kind];
}
@@ -228,7 +240,7 @@ isPointerConversionToVoidPointer(ASTContext& Context) const {
if (First == ICK_Array_To_Pointer)
FromType = Context.getArrayDecayedType(FromType);
- if (Second == ICK_Pointer_Conversion && FromType->isPointerType())
+ if (Second == ICK_Pointer_Conversion && FromType->isAnyPointerType())
if (const PointerType* ToPtrType = ToType->getAs<PointerType>())
return ToPtrType->getPointeeType()->isVoidType();
@@ -876,20 +888,19 @@ bool Sema::TryImplicitConversion(InitializationSequence &Sequence,
}
/// PerformImplicitConversion - Perform an implicit conversion of the
-/// expression From to the type ToType. Returns true if there was an
-/// error, false otherwise. The expression From is replaced with the
+/// expression From to the type ToType. Returns the
/// converted expression. Flavor is the kind of conversion we're
/// performing, used in the error message. If @p AllowExplicit,
/// explicit user-defined conversions are permitted.
-bool
-Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
+ExprResult
+Sema::PerformImplicitConversion(Expr *From, QualType ToType,
AssignmentAction Action, bool AllowExplicit) {
ImplicitConversionSequence ICS;
return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS);
}
-bool
-Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
+ExprResult
+Sema::PerformImplicitConversion(Expr *From, QualType ToType,
AssignmentAction Action, bool AllowExplicit,
ImplicitConversionSequence& ICS) {
ICS = clang::TryImplicitConversion(*this, From, ToType,
@@ -1048,27 +1059,33 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// otherwise, only a boolean conversion is standard
if (!ToType->isBooleanType())
return false;
-
- }
-
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
- if (!Method->isStatic()) {
- const Type *ClassType
- = S.Context.getTypeDeclType(Method->getParent()).getTypePtr();
- FromType = S.Context.getMemberPointerType(FromType, ClassType);
- }
}
- // If the "from" expression takes the address of the overloaded
- // function, update the type of the resulting expression accordingly.
- if (FromType->getAs<FunctionType>())
- if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(From->IgnoreParens()))
- if (UnOp->getOpcode() == UO_AddrOf)
- FromType = S.Context.getPointerType(FromType);
+ // Check if the "from" expression is taking the address of an overloaded
+ // function and recompute the FromType accordingly. Take advantage of the
+ // fact that non-static member functions *must* have such an address-of
+ // expression.
+ CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn);
+ if (Method && !Method->isStatic()) {
+ assert(isa<UnaryOperator>(From->IgnoreParens()) &&
+ "Non-unary operator on non-static member address");
+ assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode()
+ == UO_AddrOf &&
+ "Non-address-of operator on non-static member address");
+ const Type *ClassType
+ = S.Context.getTypeDeclType(Method->getParent()).getTypePtr();
+ FromType = S.Context.getMemberPointerType(FromType, ClassType);
+ } else if (isa<UnaryOperator>(From->IgnoreParens())) {
+ assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() ==
+ UO_AddrOf &&
+ "Non-address-of operator for overloaded function expression");
+ FromType = S.Context.getPointerType(FromType);
+ }
// Check that we've computed the proper type after overload resolution.
- assert(S.Context.hasSameType(FromType,
- S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType()));
+ assert(S.Context.hasSameType(
+ FromType,
+ S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType()));
} else {
return false;
}
@@ -1188,6 +1205,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// Pointer conversions (C++ 4.10).
SCS.Second = ICK_Pointer_Conversion;
SCS.IncompatibleObjC = IncompatibleObjC;
+ FromType = FromType.getUnqualifiedType();
} else if (S.IsMemberPointerConversion(From, FromType, ToType,
InOverloadResolution, FromType)) {
// Pointer to member conversions (4.11).
@@ -1203,6 +1221,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
} else if (IsNoReturnConversion(S.Context, FromType, ToType, FromType)) {
// Treat a conversion that strips "noreturn" as an identity conversion.
SCS.Second = ICK_NoReturn_Adjustment;
+ } else if (IsTransparentUnionStandardConversion(S, From, ToType,
+ InOverloadResolution,
+ SCS, CStyle)) {
+ SCS.Second = ICK_TransparentUnionConversion;
+ FromType = ToType;
} else {
// No second conversion required.
SCS.Second = ICK_Identity;
@@ -1244,6 +1267,30 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
return true;
}
+
+static bool
+IsTransparentUnionStandardConversion(Sema &S, Expr* From,
+ QualType &ToType,
+ bool InOverloadResolution,
+ StandardConversionSequence &SCS,
+ bool CStyle) {
+
+ const RecordType *UT = ToType->getAsUnionType();
+ if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ return false;
+ // The field to initialize within the transparent union.
+ RecordDecl *UD = UT->getDecl();
+ // It's compatible if the expression matches any of the fields.
+ for (RecordDecl::field_iterator it = UD->field_begin(),
+ itend = UD->field_end();
+ it != itend; ++it) {
+ if (IsStandardConversion(S, From, it->getType(), InOverloadResolution, SCS, CStyle)) {
+ ToType = it->getType();
+ return true;
+ }
+ }
+ return false;
+}
/// IsIntegralPromotion - Determines whether the conversion from the
/// expression From (whose potentially-adjusted type is FromType) to
@@ -1615,8 +1662,30 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
return true;
}
+ if (FromPointeeType->isVectorType() && ToPointeeType->isVectorType() &&
+ Context.areCompatibleVectorTypes(FromPointeeType, ToPointeeType)) {
+ ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
+ ToPointeeType,
+ ToType, Context);
+ return true;
+ }
+
return false;
}
+
+/// \brief Adopt the given qualifiers for the given type.
+static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){
+ Qualifiers TQs = T.getQualifiers();
+
+ // Check whether qualifiers already match.
+ if (TQs == Qs)
+ return T;
+
+ if (Qs.compatiblyIncludes(TQs))
+ return Context.getQualifiedType(T, Qs);
+
+ return Context.getQualifiedType(T.getUnqualifiedType(), Qs);
+}
/// isObjCPointerConversion - Determines whether this is an
/// Objective-C pointer conversion. Subroutine of IsPointerConversion,
@@ -1627,6 +1696,9 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
if (!getLangOptions().ObjC1)
return false;
+ // The set of qualifiers on the type we're converting from.
+ Qualifiers FromQualifiers = FromType.getQualifiers();
+
// First, we handle all conversions on ObjC object pointer types.
const ObjCObjectPointerType* ToObjCPtr =
ToType->getAs<ObjCObjectPointerType>();
@@ -1640,10 +1712,11 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
FromObjCPtr->getPointeeType()))
return false;
+ // Check for compatible
// Objective C++: We're able to convert between "id" or "Class" and a
// pointer to any interface (in both directions).
if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) {
- ConvertedType = ToType;
+ ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
return true;
}
// Conversions with Objective-C's id<...>.
@@ -1651,7 +1724,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
ToObjCPtr->isObjCQualifiedIdType()) &&
Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType,
/*compare=*/false)) {
- ConvertedType = ToType;
+ ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
return true;
}
// Objective C++: We're able to convert from a pointer to an
@@ -1666,6 +1739,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr,
ToObjCPtr->getPointeeType(),
ToType, Context);
+ ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
return true;
}
@@ -1677,6 +1751,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr,
ToObjCPtr->getPointeeType(),
ToType, Context);
+ ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
return true;
}
}
@@ -1689,7 +1764,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
// Objective C++: We're able to convert from a pointer to any object
// to a block pointer type.
if (FromObjCPtr && FromObjCPtr->isObjCBuiltinType()) {
- ConvertedType = ToType;
+ ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
return true;
}
ToPointeeType = ToBlockPtr->getPointeeType();
@@ -1698,7 +1773,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) {
// Objective C++: We're able to convert from a block pointer type to a
// pointer to any object.
- ConvertedType = ToType;
+ ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
return true;
}
else
@@ -1721,6 +1796,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
// We always complain about this conversion.
IncompatibleObjC = true;
ConvertedType = Context.getPointerType(ConvertedType);
+ ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
return true;
}
// Allow conversion of pointee being objective-c pointer to another one;
@@ -1730,6 +1806,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType,
IncompatibleObjC)) {
ConvertedType = Context.getPointerType(ConvertedType);
+ ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
return true;
}
@@ -1790,7 +1867,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
if (HasObjCConversion) {
// We had an Objective-C conversion. Allow this pointer
// conversion, but complain about it.
- ConvertedType = ToType;
+ ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
IncompatibleObjC = true;
return true;
}
@@ -1936,11 +2013,12 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
Kind = CK_BitCast;
- if (CXXBoolLiteralExpr* LitBool
- = dyn_cast<CXXBoolLiteralExpr>(From->IgnoreParens()))
- if (!IsCStyleOrFunctionalCast && LitBool->getValue() == false)
- Diag(LitBool->getExprLoc(), diag::warn_init_pointer_from_false)
- << ToType;
+ if (!IsCStyleOrFunctionalCast &&
+ Context.hasSameUnqualifiedType(From->getType(), Context.BoolTy) &&
+ From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
+ DiagRuntimeBehavior(From->getExprLoc(), From,
+ PDiag(diag::warn_impcast_bool_to_null_pointer)
+ << ToType << From->getSourceRange());
if (const PointerType *FromPtrType = FromType->getAs<PointerType>())
if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) {
@@ -2116,21 +2194,24 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
// unwrap.
UnwrappedAnyPointer = true;
+ Qualifiers FromQuals = FromType.getQualifiers();
+ Qualifiers ToQuals = ToType.getQualifiers();
+
// -- for every j > 0, if const is in cv 1,j then const is in cv
// 2,j, and similarly for volatile.
- if (!CStyle && !ToType.isAtLeastAsQualifiedAs(FromType))
+ if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals))
return false;
// -- if the cv 1,j and cv 2,j are different, then const is in
// every cv for 0 < k < j.
- if (!CStyle && FromType.getCVRQualifiers() != ToType.getCVRQualifiers()
+ if (!CStyle && FromQuals.getCVRQualifiers() != ToQuals.getCVRQualifiers()
&& !PreviousToQualsIncludeConst)
return false;
// Keep track of whether all prior cv-qualifiers in the "to" type
// include const.
PreviousToQualsIncludeConst
- = PreviousToQualsIncludeConst && ToType.isConstQualified();
+ = PreviousToQualsIncludeConst && ToQuals.hasConst();
}
// We are left with FromType and ToType being the pointee types
@@ -2175,7 +2256,11 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
S.IsDerivedFrom(From->getType(), ToType)))
ConstructorsOnly = true;
- if (S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag())) {
+ S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag());
+ // RequireCompleteType may have returned true due to some invalid decl
+ // during template instantiation, but ToType may be complete enough now
+ // to try to recover.
+ if (ToType->isIncompleteType()) {
// We're not going to find any constructors.
} else if (CXXRecordDecl *ToRecordDecl
= dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
@@ -2546,7 +2631,8 @@ CompareStandardConversionSequences(Sema &S,
if (ImplicitConversionSequence::CompareKind DerivedCK
= CompareDerivedToBaseConversions(S, SCS1, SCS2))
return DerivedCK;
- } else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid) {
+ } else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid &&
+ !S.Context.hasSameType(SCS1.getFromType(), SCS2.getFromType())) {
// Both conversion sequences are conversions to void
// pointers. Compare the source types to determine if there's an
// inheritance relationship in their sources.
@@ -2560,10 +2646,8 @@ CompareStandardConversionSequences(Sema &S,
if (SCS2.First == ICK_Array_To_Pointer)
FromType2 = S.Context.getArrayDecayedType(FromType2);
- QualType FromPointee1
- = FromType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
- QualType FromPointee2
- = FromType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+ QualType FromPointee1 = FromType1->getPointeeType().getUnqualifiedType();
+ QualType FromPointee2 = FromType2->getPointeeType().getUnqualifiedType();
if (S.IsDerivedFrom(FromPointee2, FromPointee1))
return ImplicitConversionSequence::Better;
@@ -2572,13 +2656,19 @@ CompareStandardConversionSequences(Sema &S,
// Objective-C++: If one interface is more specific than the
// other, it is the better one.
- const ObjCObjectType* FromIface1 = FromPointee1->getAs<ObjCObjectType>();
- const ObjCObjectType* FromIface2 = FromPointee2->getAs<ObjCObjectType>();
- if (FromIface1 && FromIface1) {
- if (S.Context.canAssignObjCInterfaces(FromIface2, FromIface1))
- return ImplicitConversionSequence::Better;
- else if (S.Context.canAssignObjCInterfaces(FromIface1, FromIface2))
- return ImplicitConversionSequence::Worse;
+ const ObjCObjectPointerType* FromObjCPtr1
+ = FromType1->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType* FromObjCPtr2
+ = FromType2->getAs<ObjCObjectPointerType>();
+ if (FromObjCPtr1 && FromObjCPtr2) {
+ bool AssignLeft = S.Context.canAssignObjCInterfaces(FromObjCPtr1,
+ FromObjCPtr2);
+ bool AssignRight = S.Context.canAssignObjCInterfaces(FromObjCPtr2,
+ FromObjCPtr1);
+ if (AssignLeft != AssignRight) {
+ return AssignLeft? ImplicitConversionSequence::Better
+ : ImplicitConversionSequence::Worse;
+ }
}
}
@@ -2981,7 +3071,12 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
// overload resolution, cases for which cv1 is greater
// cv-qualification than cv2 are identified as
// reference-compatible with added qualification (see 13.3.3.2).
- if (T1Quals.getCVRQualifiers() == T2Quals.getCVRQualifiers())
+ //
+ // Note that we also require equivalence of Objective-C GC and address-space
+ // qualifiers when performing these computations, so that e.g., an int in
+ // address space 1 is not reference-compatible with an int in address
+ // space 2.
+ if (T1Quals == T2Quals)
return Ref_Compatible;
else if (T1.isMoreQualifiedThan(T2))
return Ref_Compatible_With_Added_Qualification;
@@ -3480,8 +3575,8 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType,
/// PerformObjectArgumentInitialization - Perform initialization of
/// the implicit object parameter for the given Method with the given
/// expression.
-bool
-Sema::PerformObjectArgumentInitialization(Expr *&From,
+ExprResult
+Sema::PerformObjectArgumentInitialization(Expr *From,
NestedNameSpecifier *Qualifier,
NamedDecl *FoundDecl,
CXXMethodDecl *Method) {
@@ -3517,7 +3612,7 @@ Sema::PerformObjectArgumentInitialization(Expr *&From,
<< From->getSourceRange();
Diag(Method->getLocation(), diag::note_previous_decl)
<< Method->getDeclName();
- return true;
+ return ExprError();
}
}
@@ -3526,13 +3621,18 @@ Sema::PerformObjectArgumentInitialization(Expr *&From,
<< ImplicitParamRecordType << FromRecordType << From->getSourceRange();
}
- if (ICS.Standard.Second == ICK_Derived_To_Base)
- return PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method);
+ if (ICS.Standard.Second == ICK_Derived_To_Base) {
+ ExprResult FromRes =
+ PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method);
+ if (FromRes.isInvalid())
+ return ExprError();
+ From = FromRes.take();
+ }
if (!Context.hasSameType(From->getType(), DestType))
- ImpCastExprToType(From, DestType, CK_NoOp,
- From->getType()->isPointerType() ? VK_RValue : VK_LValue);
- return false;
+ From = ImpCastExprToType(From, DestType, CK_NoOp,
+ From->getType()->isPointerType() ? VK_RValue : VK_LValue).take();
+ return Owned(From);
}
/// TryContextuallyConvertToBool - Attempt to contextually convert the
@@ -3550,16 +3650,16 @@ TryContextuallyConvertToBool(Sema &S, Expr *From) {
/// PerformContextuallyConvertToBool - Perform a contextual conversion
/// of the expression From to bool (C++0x [conv]p3).
-bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
+ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) {
ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From);
if (!ICS.isBad())
return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
- return Diag(From->getSourceRange().getBegin(),
- diag::err_typecheck_bool_condition)
+ return Diag(From->getSourceRange().getBegin(),
+ diag::err_typecheck_bool_condition)
<< From->getType() << From->getSourceRange();
- return true;
+ return ExprError();
}
/// TryContextuallyConvertToObjCId - Attempt to contextually convert the
@@ -3577,12 +3677,12 @@ TryContextuallyConvertToObjCId(Sema &S, Expr *From) {
/// PerformContextuallyConvertToObjCId - Perform a contextual conversion
/// of the expression From to 'id'.
-bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) {
+ExprResult Sema::PerformContextuallyConvertToObjCId(Expr *From) {
QualType Ty = Context.getObjCIdType();
ImplicitConversionSequence ICS = TryContextuallyConvertToObjCId(*this, From);
if (!ICS.isBad())
return PerformImplicitConversion(From, Ty, ICS, AA_Converting);
- return true;
+ return ExprError();
}
/// \brief Attempt to convert the given expression to an integral or
@@ -4061,7 +4161,7 @@ void
Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ObjectType,
Expr::Classification ObjectClassification,
Expr **Args, unsigned NumArgs,
@@ -4114,7 +4214,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
void
Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
DeclAccessPair FoundDecl,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
@@ -6090,9 +6190,10 @@ void
Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
bool Operator,
Expr **Args, unsigned NumArgs,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
- bool PartialOverloading) {
+ bool PartialOverloading,
+ bool StdNamespaceIsAssociated) {
ADLResult Fns;
// FIXME: This approach for uniquing ADL results (and removing
@@ -6103,7 +6204,8 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
// we supposed to consider on ADL candidates, anyway?
// FIXME: Pass in the explicit template arguments?
- ArgumentDependentLookup(Name, Operator, Args, NumArgs, Fns);
+ ArgumentDependentLookup(Name, Operator, Args, NumArgs, Fns,
+ StdNamespaceIsAssociated);
// Erase all of the candidates we already knew about.
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
@@ -6282,8 +6384,7 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
// Best is the best viable function.
if (Best->Function &&
- (Best->Function->isDeleted() ||
- Best->Function->getAttr<UnavailableAttr>()))
+ (Best->Function->isDeleted() || Best->Function->isUnavailable()))
return OR_Deleted;
return OR_Success;
@@ -6473,6 +6574,17 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
return;
}
+ if (FromQs.getObjCGCAttr() != ToQs.getObjCGCAttr()) {
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_gc)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy
+ << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr()
+ << (unsigned) isObjectArgument << I+1;
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+ }
+
unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
assert(CVR && "unexpected qualifiers mismatch");
@@ -6735,7 +6847,7 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
FunctionDecl *Fn = Cand->Function;
// Note deleted candidates, but only if they're viable.
- if (Cand->Viable && (Fn->isDeleted() || Fn->hasAttr<UnavailableAttr>())) {
+ if (Cand->Viable && (Fn->isDeleted() || Fn->isUnavailable())) {
std::string FnDesc;
OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
@@ -7134,8 +7246,23 @@ public:
if (!TargetFunctionType->isFunctionType()) {
if (OvlExpr->hasExplicitTemplateArgs()) {
DeclAccessPair dap;
- if( FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization(
+ if (FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization(
OvlExpr, false, &dap) ) {
+
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
+ if (!Method->isStatic()) {
+ // If the target type is a non-function type and the function
+ // found is a non-static member function, pretend as if that was
+ // the target, it's the only possible type to end up with.
+ TargetTypeIsNonStaticMemberFunction = true;
+
+ // And skip adding the function if its not in the proper form.
+ // We'll diagnose this due to an empty set of functions.
+ if (!OvlExprInfo.HasFormOfMemberPointer)
+ return;
+ }
+ }
+
Matches.push_back(std::make_pair(dap,Fn));
}
}
@@ -7419,32 +7546,29 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetTyp
/// template, where that template-id refers to a single template whose template
/// arguments are either provided by the template-id or have defaults,
/// as described in C++0x [temp.arg.explicit]p3.
-FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From,
- bool Complain,
- DeclAccessPair* FoundResult) {
+FunctionDecl *
+Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
+ bool Complain,
+ DeclAccessPair *FoundResult) {
// C++ [over.over]p1:
// [...] [Note: any redundant set of parentheses surrounding the
// overloaded function name is ignored (5.1). ]
// C++ [over.over]p1:
// [...] The overloaded function name can be preceded by the &
// operator.
- if (From->getType() != Context.OverloadTy)
- return 0;
-
- OverloadExpr *OvlExpr = OverloadExpr::find(From).Expression;
// If we didn't actually find any template-ids, we're done.
- if (!OvlExpr->hasExplicitTemplateArgs())
+ if (!ovl->hasExplicitTemplateArgs())
return 0;
TemplateArgumentListInfo ExplicitTemplateArgs;
- OvlExpr->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+ ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
FunctionDecl *Matched = 0;
- for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
- E = OvlExpr->decls_end(); I != E; ++I) {
+ for (UnresolvedSetIterator I = ovl->decls_begin(),
+ E = ovl->decls_end(); I != E; ++I) {
// C++0x [temp.arg.explicit]p3:
// [...] In contexts where deduction is done and fails, or in contexts
// where deduction is not done, if a template argument list is
@@ -7461,7 +7585,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From,
// function template specialization, which is added to the set of
// overloaded functions considered.
FunctionDecl *Specialization = 0;
- TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
+ TemplateDeductionInfo Info(Context, ovl->getNameLoc());
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
Specialization, Info)) {
@@ -7470,30 +7594,98 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From,
continue;
}
+ assert(Specialization && "no specialization and no error?");
+
// Multiple matches; we can't resolve to a single declaration.
if (Matched) {
- if (FoundResult)
- *FoundResult = DeclAccessPair();
-
if (Complain) {
- Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
- << OvlExpr->getName();
- NoteAllOverloadCandidates(OvlExpr);
+ Diag(ovl->getExprLoc(), diag::err_addr_ovl_ambiguous)
+ << ovl->getName();
+ NoteAllOverloadCandidates(ovl);
}
return 0;
- }
+ }
- if ((Matched = Specialization) && FoundResult)
- *FoundResult = I.getPair();
+ Matched = Specialization;
+ if (FoundResult) *FoundResult = I.getPair();
}
return Matched;
}
+
+
+
+// Resolve and fix an overloaded expression that
+// can be resolved because it identifies a single function
+// template specialization
+// Last three arguments should only be supplied if Complain = true
+ExprResult Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
+ Expr *SrcExpr, bool doFunctionPointerConverion, bool complain,
+ const SourceRange& OpRangeForComplaining,
+ QualType DestTypeForComplaining,
+ unsigned DiagIDForComplaining) {
+ assert(SrcExpr->getType() == Context.OverloadTy);
+
+ OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr);
+
+ DeclAccessPair found;
+ ExprResult SingleFunctionExpression;
+ if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization(
+ ovl.Expression, /*complain*/ false, &found)) {
+ if (DiagnoseUseOfDecl(fn, SrcExpr->getSourceRange().getBegin()))
+ return ExprError();
+
+ // It is only correct to resolve to an instance method if we're
+ // resolving a form that's permitted to be a pointer to member.
+ // Otherwise we'll end up making a bound member expression, which
+ // is illegal in all the contexts we resolve like this.
+ if (!ovl.HasFormOfMemberPointer &&
+ isa<CXXMethodDecl>(fn) &&
+ cast<CXXMethodDecl>(fn)->isInstance()) {
+ if (complain) {
+ Diag(ovl.Expression->getExprLoc(),
+ diag::err_invalid_use_of_bound_member_func)
+ << ovl.Expression->getSourceRange();
+ // TODO: I believe we only end up here if there's a mix of
+ // static and non-static candidates (otherwise the expression
+ // would have 'bound member' type, not 'overload' type).
+ // Ideally we would note which candidate was chosen and why
+ // the static candidates were rejected.
+ }
+
+ return ExprError();
+ }
+
+ // Fix the expresion to refer to 'fn'.
+ SingleFunctionExpression =
+ Owned(FixOverloadedFunctionReference(SrcExpr, found, fn));
+
+ // If desired, do function-to-pointer decay.
+ if (doFunctionPointerConverion)
+ SingleFunctionExpression =
+ DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take());
+ }
+
+ if (!SingleFunctionExpression.isUsable()) {
+ if (complain) {
+ Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
+ << ovl.Expression->getName()
+ << DestTypeForComplaining
+ << OpRangeForComplaining
+ << ovl.Expression->getQualifierLoc().getSourceRange();
+ NoteAllOverloadCandidates(SrcExpr);
+ }
+ return ExprError();
+ }
+
+ return SingleFunctionExpression;
+}
+
/// \brief Add a single candidate to the overload set.
static void AddOverloadedCallCandidate(Sema &S,
DeclAccessPair FoundDecl,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
bool PartialOverloading) {
@@ -7559,7 +7751,7 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
// It would be nice to avoid this copy.
TemplateArgumentListInfo TABuffer;
- const TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
+ TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
if (ULE->hasExplicitTemplateArgs()) {
ULE->copyTemplateArgumentsInto(TABuffer);
ExplicitTemplateArgs = &TABuffer;
@@ -7576,7 +7768,8 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
Args, NumArgs,
ExplicitTemplateArgs,
CandidateSet,
- PartialOverloading);
+ PartialOverloading,
+ ULE->isStdAssociatedNamespace());
}
/// Attempts to recover from a call where no functions were found.
@@ -7590,9 +7783,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
SourceLocation RParenLoc) {
CXXScopeSpec SS;
- if (ULE->getQualifier())
- SS.MakeTrivial(SemaRef.Context,
- ULE->getQualifier(), ULE->getQualifierRange());
+ SS.Adopt(ULE->getQualifierLoc());
TemplateArgumentListInfo TABuffer;
const TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
@@ -7657,7 +7848,9 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
// We don't perform ADL in C.
assert(getLangOptions().CPlusPlus && "ADL enabled in C");
- }
+ } else
+ assert(!ULE->isStdAssociatedNamespace() &&
+ "std is associated namespace but not doing ADL");
#endif
OverloadCandidateSet CandidateSet(Fn->getExprLoc());
@@ -7704,8 +7897,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call)
<< Best->Function->isDeleted()
<< ULE->getName()
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< Fn->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
}
@@ -7749,8 +7941,12 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
// TODO: provide better source location info.
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
- if (Input->getObjectKind() == OK_ObjCProperty)
- ConvertPropertyForRValue(Input);
+ if (Input->getObjectKind() == OK_ObjCProperty) {
+ ExprResult Result = ConvertPropertyForRValue(Input);
+ if (Result.isInvalid())
+ return ExprError();
+ Input = Result.take();
+ }
Expr *Args[2] = { Input, 0 };
unsigned NumArgs = 1;
@@ -7776,11 +7972,11 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, NamingClass,
- 0, SourceRange(), OpNameInfo,
+ NestedNameSpecifierLoc(), OpNameInfo,
/*ADL*/ true, IsOverloaded(Fns),
Fns.begin(), Fns.end());
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
- &Args[0], NumArgs,
+ &Args[0], NumArgs,
Context.DependentTy,
VK_RValue,
OpLoc));
@@ -7821,9 +8017,12 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl);
- if (PerformObjectArgumentInitialization(Input, /*Qualifier=*/0,
- Best->FoundDecl, Method))
+ ExprResult InputRes =
+ PerformObjectArgumentInitialization(Input, /*Qualifier=*/0,
+ Best->FoundDecl, Method);
+ if (InputRes.isInvalid())
return ExprError();
+ Input = InputRes.take();
} else {
// Convert the arguments.
ExprResult InputInit
@@ -7845,11 +8044,13 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
ResultTy = ResultTy.getNonLValueExprType(Context);
// Build the actual expression node.
- Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl);
+ ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl);
+ if (FnExpr.isInvalid())
+ return ExprError();
Args[0] = Input;
CallExpr *TheCall =
- new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
+ new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),
Args, NumArgs, ResultTy, VK, OpLoc);
if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
@@ -7861,39 +8062,40 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
// We matched a built-in operator. Convert the arguments, then
// break out so that we will build the appropriate built-in
// operator node.
- if (PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0],
- Best->Conversions[0], AA_Passing))
- return ExprError();
-
- break;
- }
- }
-
- case OR_No_Viable_Function:
- // No viable function; fall through to handling this as a
- // built-in operator, which will produce an error message for us.
+ ExprResult InputRes =
+ PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0],
+ Best->Conversions[0], AA_Passing);
+ if (InputRes.isInvalid())
+ return ExprError();
+ Input = InputRes.take();
break;
+ }
+ }
- case OR_Ambiguous:
- Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary)
- << UnaryOperator::getOpcodeStr(Opc)
- << Input->getType()
- << Input->getSourceRange();
- CandidateSet.NoteCandidates(*this, OCD_ViableCandidates,
- Args, NumArgs,
- UnaryOperator::getOpcodeStr(Opc), OpLoc);
- return ExprError();
+ case OR_No_Viable_Function:
+ // No viable function; fall through to handling this as a
+ // built-in operator, which will produce an error message for us.
+ break;
- case OR_Deleted:
- Diag(OpLoc, diag::err_ovl_deleted_oper)
- << Best->Function->isDeleted()
+ case OR_Ambiguous:
+ Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary)
<< UnaryOperator::getOpcodeStr(Opc)
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << Input->getType()
<< Input->getSourceRange();
- CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
- return ExprError();
- }
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates,
+ Args, NumArgs,
+ UnaryOperator::getOpcodeStr(Opc), OpLoc);
+ return ExprError();
+
+ case OR_Deleted:
+ Diag(OpLoc, diag::err_ovl_deleted_oper)
+ << Best->Function->isDeleted()
+ << UnaryOperator::getOpcodeStr(Opc)
+ << getDeletedOrUnavailableSuffix(Best->Function)
+ << Input->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ return ExprError();
+ }
// Either we found no viable overloaded operator or we matched a
// built-in operator. In either case, fall through to trying to
@@ -7956,8 +8158,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// TODO: provide better source location info in DNLoc component.
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
UnresolvedLookupExpr *Fn
- = UnresolvedLookupExpr::Create(Context, NamingClass, 0, SourceRange(),
- OpNameInfo, /*ADL*/ true, IsOverloaded(Fns),
+ = UnresolvedLookupExpr::Create(Context, NamingClass,
+ NestedNameSpecifierLoc(), OpNameInfo,
+ /*ADL*/ true, IsOverloaded(Fns),
Fns.begin(), Fns.end());
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
Args, 2,
@@ -7967,8 +8170,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
}
// Always do property rvalue conversions on the RHS.
- if (Args[1]->getObjectKind() == OK_ObjCProperty)
- ConvertPropertyForRValue(Args[1]);
+ if (Args[1]->getObjectKind() == OK_ObjCProperty) {
+ ExprResult Result = ConvertPropertyForRValue(Args[1]);
+ if (Result.isInvalid())
+ return ExprError();
+ Args[1] = Result.take();
+ }
// The LHS is more complicated.
if (Args[0]->getObjectKind() == OK_ObjCProperty) {
@@ -7996,7 +8203,10 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
}
- ConvertPropertyForRValue(Args[0]);
+ ExprResult Result = ConvertPropertyForRValue(Args[0]);
+ if (Result.isInvalid())
+ return ExprError();
+ Args[0] = Result.take();
}
// If this is the assignment operator, we only perform overload resolution
@@ -8057,10 +8267,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Arg1.isInvalid())
return ExprError();
- if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
- Best->FoundDecl, Method))
+ ExprResult Arg0 =
+ PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+ Best->FoundDecl, Method);
+ if (Arg0.isInvalid())
return ExprError();
-
+ Args[0] = Arg0.takeAs<Expr>();
Args[1] = RHS = Arg1.takeAs<Expr>();
} else {
// Convert the arguments.
@@ -8090,10 +8302,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
ResultTy = ResultTy.getNonLValueExprType(Context);
// Build the actual expression node.
- Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, OpLoc);
+ ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, OpLoc);
+ if (FnExpr.isInvalid())
+ return ExprError();
CXXOperatorCallExpr *TheCall =
- new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
+ new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),
Args, 2, ResultTy, VK, OpLoc);
if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
@@ -8105,12 +8319,19 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// We matched a built-in operator. Convert the arguments, then
// break out so that we will build the appropriate built-in
// operator node.
- if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
- Best->Conversions[0], AA_Passing) ||
- PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
- Best->Conversions[1], AA_Passing))
+ ExprResult ArgsRes0 =
+ PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
+ Best->Conversions[0], AA_Passing);
+ if (ArgsRes0.isInvalid())
return ExprError();
+ Args[0] = ArgsRes0.take();
+ ExprResult ArgsRes1 =
+ PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
+ Best->Conversions[1], AA_Passing);
+ if (ArgsRes1.isInvalid())
+ return ExprError();
+ Args[1] = ArgsRes1.take();
break;
}
}
@@ -8158,8 +8379,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< BinaryOperator::getOpcodeStr(Opc)
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2);
return ExprError();
@@ -8187,7 +8407,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, NamingClass,
- 0, SourceRange(), OpNameInfo,
+ NestedNameSpecifierLoc(), OpNameInfo,
/*ADL*/ true, /*Overloaded*/ false,
UnresolvedSetIterator(),
UnresolvedSetIterator());
@@ -8200,10 +8420,18 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
RLoc));
}
- if (Args[0]->getObjectKind() == OK_ObjCProperty)
- ConvertPropertyForRValue(Args[0]);
- if (Args[1]->getObjectKind() == OK_ObjCProperty)
- ConvertPropertyForRValue(Args[1]);
+ if (Args[0]->getObjectKind() == OK_ObjCProperty) {
+ ExprResult Result = ConvertPropertyForRValue(Args[0]);
+ if (Result.isInvalid())
+ return ExprError();
+ Args[0] = Result.take();
+ }
+ if (Args[1]->getObjectKind() == OK_ObjCProperty) {
+ ExprResult Result = ConvertPropertyForRValue(Args[1]);
+ if (Result.isInvalid())
+ return ExprError();
+ Args[1] = Result.take();
+ }
// Build an empty overload set.
OverloadCandidateSet CandidateSet(LLoc);
@@ -8234,9 +8462,12 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// Convert the arguments.
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
- if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
- Best->FoundDecl, Method))
+ ExprResult Arg0 =
+ PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+ Best->FoundDecl, Method);
+ if (Arg0.isInvalid())
return ExprError();
+ Args[0] = Arg0.take();
// Convert the arguments.
ExprResult InputInit
@@ -8256,11 +8487,13 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
ResultTy = ResultTy.getNonLValueExprType(Context);
// Build the actual expression node.
- Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, LLoc);
+ ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, LLoc);
+ if (FnExpr.isInvalid())
+ return ExprError();
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
- FnExpr, Args, 2,
+ FnExpr.take(), Args, 2,
ResultTy, VK, RLoc);
if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall,
@@ -8272,11 +8505,19 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// We matched a built-in operator. Convert the arguments, then
// break out so that we will build the appropriate built-in
// operator node.
- if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
- Best->Conversions[0], AA_Passing) ||
- PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
- Best->Conversions[1], AA_Passing))
+ ExprResult ArgsRes0 =
+ PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
+ Best->Conversions[0], AA_Passing);
+ if (ArgsRes0.isInvalid())
return ExprError();
+ Args[0] = ArgsRes0.take();
+
+ ExprResult ArgsRes1 =
+ PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
+ Best->Conversions[1], AA_Passing);
+ if (ArgsRes1.isInvalid())
+ return ExprError();
+ Args[1] = ArgsRes1.take();
break;
}
@@ -8308,8 +8549,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
case OR_Deleted:
Diag(LLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted() << "[]"
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2,
"[]", LLoc);
@@ -8325,16 +8565,66 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
/// function (and includes the object parameter), Args/NumArgs are the
/// arguments to the function call (not including the object
/// parameter). The caller needs to validate that the member
-/// expression refers to a member function or an overloaded member
-/// function.
+/// expression refers to a non-static member function or an overloaded
+/// member function.
ExprResult
Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
SourceLocation LParenLoc, Expr **Args,
unsigned NumArgs, SourceLocation RParenLoc) {
+ assert(MemExprE->getType() == Context.BoundMemberTy ||
+ MemExprE->getType() == Context.OverloadTy);
+
// Dig out the member expression. This holds both the object
// argument and the member function we're referring to.
Expr *NakedMemExpr = MemExprE->IgnoreParens();
+ // Determine whether this is a call to a pointer-to-member function.
+ if (BinaryOperator *op = dyn_cast<BinaryOperator>(NakedMemExpr)) {
+ assert(op->getType() == Context.BoundMemberTy);
+ assert(op->getOpcode() == BO_PtrMemD || op->getOpcode() == BO_PtrMemI);
+
+ QualType fnType =
+ op->getRHS()->getType()->castAs<MemberPointerType>()->getPointeeType();
+
+ const FunctionProtoType *proto = fnType->castAs<FunctionProtoType>();
+ QualType resultType = proto->getCallResultType(Context);
+ ExprValueKind valueKind = Expr::getValueKindForType(proto->getResultType());
+
+ // Check that the object type isn't more qualified than the
+ // member function we're calling.
+ Qualifiers funcQuals = Qualifiers::fromCVRMask(proto->getTypeQuals());
+
+ QualType objectType = op->getLHS()->getType();
+ if (op->getOpcode() == BO_PtrMemI)
+ objectType = objectType->castAs<PointerType>()->getPointeeType();
+ Qualifiers objectQuals = objectType.getQualifiers();
+
+ Qualifiers difference = objectQuals - funcQuals;
+ difference.removeObjCGCAttr();
+ difference.removeAddressSpace();
+ if (difference) {
+ std::string qualsString = difference.getAsString();
+ Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals)
+ << fnType.getUnqualifiedType()
+ << qualsString
+ << (qualsString.find(' ') == std::string::npos ? 1 : 2);
+ }
+
+ CXXMemberCallExpr *call
+ = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs,
+ resultType, valueKind, RParenLoc);
+
+ if (CheckCallReturnType(proto->getResultType(),
+ op->getRHS()->getSourceRange().getBegin(),
+ call, 0))
+ return ExprError();
+
+ if (ConvertArgumentsForCall(call, op, 0, proto, Args, NumArgs, RParenLoc))
+ return ExprError();
+
+ return MaybeBindToTemporary(call);
+ }
+
MemberExpr *MemExpr;
CXXMethodDecl *Method = 0;
DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public);
@@ -8427,8 +8717,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
<< Best->Function->isDeleted()
<< DeclName
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< MemExprE->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
// FIXME: Leaking incoming expressions!
@@ -8464,12 +8753,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
// Convert the object argument (for a non-static member function call).
// We only need to do this if there was actually an overload; otherwise
// it was done at lookup.
- Expr *ObjectArg = MemExpr->getBase();
- if (!Method->isStatic() &&
- PerformObjectArgumentInitialization(ObjectArg, Qualifier,
- FoundDecl, Method))
- return ExprError();
- MemExpr->setBase(ObjectArg);
+ if (!Method->isStatic()) {
+ ExprResult ObjectArg =
+ PerformObjectArgumentInitialization(MemExpr->getBase(), Qualifier,
+ FoundDecl, Method);
+ if (ObjectArg.isInvalid())
+ return ExprError();
+ MemExpr->setBase(ObjectArg.take());
+ }
// Convert the rest of the arguments
const FunctionProtoType *Proto =
@@ -8489,15 +8780,19 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
/// overloaded function call operator (@c operator()) or performing a
/// user-defined conversion on the object argument.
ExprResult
-Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
+Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc) {
- if (Object->getObjectKind() == OK_ObjCProperty)
- ConvertPropertyForRValue(Object);
+ ExprResult Object = Owned(Obj);
+ if (Object.get()->getObjectKind() == OK_ObjCProperty) {
+ Object = ConvertPropertyForRValue(Object.take());
+ if (Object.isInvalid())
+ return ExprError();
+ }
- assert(Object->getType()->isRecordType() && "Requires object type argument");
- const RecordType *Record = Object->getType()->getAs<RecordType>();
+ assert(Object.get()->getType()->isRecordType() && "Requires object type argument");
+ const RecordType *Record = Object.get()->getType()->getAs<RecordType>();
// C++ [over.call.object]p1:
// If the primary-expression E in the function call syntax
@@ -8509,9 +8804,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
OverloadCandidateSet CandidateSet(LParenLoc);
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
- if (RequireCompleteType(LParenLoc, Object->getType(),
+ if (RequireCompleteType(LParenLoc, Object.get()->getType(),
PDiag(diag::err_incomplete_object_call)
- << Object->getSourceRange()))
+ << Object.get()->getSourceRange()))
return true;
LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName);
@@ -8520,8 +8815,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
- AddMethodCandidate(Oper.getPair(), Object->getType(),
- Object->Classify(Context), Args, NumArgs, CandidateSet,
+ AddMethodCandidate(Oper.getPair(), Object.get()->getType(),
+ Object.get()->Classify(Context), Args, NumArgs, CandidateSet,
/*SuppressUserConversions=*/ false);
}
@@ -8566,12 +8861,12 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto,
- Object, Args, NumArgs, CandidateSet);
+ Object.get(), Args, NumArgs, CandidateSet);
}
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (CandidateSet.BestViableFunction(*this, Object->getLocStart(),
+ switch (CandidateSet.BestViableFunction(*this, Object.get()->getLocStart(),
Best)) {
case OR_Success:
// Overload resolution succeeded; we'll build the appropriate call
@@ -8580,31 +8875,30 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
case OR_No_Viable_Function:
if (CandidateSet.empty())
- Diag(Object->getSourceRange().getBegin(), diag::err_ovl_no_oper)
- << Object->getType() << /*call*/ 1
- << Object->getSourceRange();
+ Diag(Object.get()->getSourceRange().getBegin(), diag::err_ovl_no_oper)
+ << Object.get()->getType() << /*call*/ 1
+ << Object.get()->getSourceRange();
else
- Diag(Object->getSourceRange().getBegin(),
+ Diag(Object.get()->getSourceRange().getBegin(),
diag::err_ovl_no_viable_object_call)
- << Object->getType() << Object->getSourceRange();
+ << Object.get()->getType() << Object.get()->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
break;
case OR_Ambiguous:
- Diag(Object->getSourceRange().getBegin(),
+ Diag(Object.get()->getSourceRange().getBegin(),
diag::err_ovl_ambiguous_object_call)
- << Object->getType() << Object->getSourceRange();
+ << Object.get()->getType() << Object.get()->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs);
break;
case OR_Deleted:
- Diag(Object->getSourceRange().getBegin(),
+ Diag(Object.get()->getSourceRange().getBegin(),
diag::err_ovl_deleted_object_call)
<< Best->Function->isDeleted()
- << Object->getType()
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
- << Object->getSourceRange();
+ << Object.get()->getType()
+ << getDeletedOrUnavailableSuffix(Best->Function)
+ << Object.get()->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
break;
}
@@ -8619,7 +8913,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
= cast<CXXConversionDecl>(
Best->Conversions[0].UserDefined.ConversionFunction);
- CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl);
+ CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc);
// We selected one of the surrogate functions that converts the
@@ -8628,7 +8922,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// Create an implicit member expr to refer to the conversion operator.
// and then call it.
- ExprResult Call = BuildCXXMemberCallExpr(Object, Best->FoundDecl, Conv);
+ ExprResult Call = BuildCXXMemberCallExpr(Object.get(), Best->FoundDecl, Conv);
if (Call.isInvalid())
return ExprError();
@@ -8637,7 +8931,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
}
MarkDeclarationReferenced(LParenLoc, Best->Function);
- CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl);
+ CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc);
// We found an overloaded operator(). Build a CXXOperatorCallExpr
@@ -8660,11 +8954,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
} else {
MethodArgs = new Expr*[NumArgs + 1];
}
- MethodArgs[0] = Object;
+ MethodArgs[0] = Object.get();
for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
MethodArgs[ArgIdx + 1] = Args[ArgIdx];
- Expr *NewFn = CreateFunctionRefExpr(*this, Method);
+ ExprResult NewFn = CreateFunctionRefExpr(*this, Method);
+ if (NewFn.isInvalid())
+ return true;
// Once we've built TheCall, all of the expressions are properly
// owned.
@@ -8673,7 +8969,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall =
- new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn,
+ new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.take(),
MethodArgs, NumArgs + 1,
ResultTy, VK, RParenLoc);
delete [] MethodArgs;
@@ -8692,10 +8988,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
bool IsError = false;
// Initialize the implicit object parameter.
- IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0,
- Best->FoundDecl, Method);
- TheCall->setArg(0, Object);
-
+ ExprResult ObjRes =
+ PerformObjectArgumentInitialization(Object.get(), /*Qualifier=*/0,
+ Best->FoundDecl, Method);
+ if (ObjRes.isInvalid())
+ IsError = true;
+ else
+ Object = move(ObjRes);
+ TheCall->setArg(0, Object.take());
// Check the argument types.
for (unsigned i = 0; i != NumArgsToCheck; i++) {
@@ -8731,9 +9031,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
if (Proto->isVariadic()) {
// Promote the arguments (C99 6.5.2.2p7).
for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
- Expr *Arg = Args[i];
- IsError |= DefaultVariadicArgumentPromotion(Arg, VariadicMethod, 0);
- TheCall->setArg(i + 1, Arg);
+ ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0);
+ IsError |= Arg.isInvalid();
+ TheCall->setArg(i + 1, Arg.take());
}
}
@@ -8753,8 +9053,12 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
assert(Base->getType()->isRecordType() &&
"left-hand side must have class type");
- if (Base->getObjectKind() == OK_ObjCProperty)
- ConvertPropertyForRValue(Base);
+ if (Base->getObjectKind() == OK_ObjCProperty) {
+ ExprResult Result = ConvertPropertyForRValue(Base);
+ if (Result.isInvalid())
+ return ExprError();
+ Base = Result.take();
+ }
SourceLocation Loc = Base->getExprLoc();
@@ -8811,8 +9115,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< "->"
- << Best->Function->getMessageUnavailableAttr(
- !Best->Function->isDeleted())
+ << getDeletedOrUnavailableSuffix(Best->Function)
<< Base->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1);
return ExprError();
@@ -8824,24 +9127,30 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
// Convert the object parameter.
CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
- if (PerformObjectArgumentInitialization(Base, /*Qualifier=*/0,
- Best->FoundDecl, Method))
+ ExprResult BaseResult =
+ PerformObjectArgumentInitialization(Base, /*Qualifier=*/0,
+ Best->FoundDecl, Method);
+ if (BaseResult.isInvalid())
return ExprError();
+ Base = BaseResult.take();
// Build the operator call.
- Expr *FnExpr = CreateFunctionRefExpr(*this, Method);
+ ExprResult FnExpr = CreateFunctionRefExpr(*this, Method);
+ if (FnExpr.isInvalid())
+ return ExprError();
QualType ResultTy = Method->getResultType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall =
- new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr,
+ new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(),
&Base, 1, ResultTy, VK, OpLoc);
if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall,
Method))
return ExprError();
- return Owned(TheCall);
+
+ return MaybeBindToTemporary(TheCall);
}
/// FixOverloadedFunctionReference - E is an expression that refers to
@@ -8930,12 +9239,12 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
}
return DeclRefExpr::Create(Context,
- ULE->getQualifier(),
- ULE->getQualifierRange(),
+ ULE->getQualifierLoc(),
Fn,
ULE->getNameLoc(),
Fn->getType(),
VK_LValue,
+ Found.getDecl(),
TemplateArgs);
}
@@ -8954,17 +9263,17 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
if (MemExpr->isImplicitAccess()) {
if (cast<CXXMethodDecl>(Fn)->isStatic()) {
return DeclRefExpr::Create(Context,
- MemExpr->getQualifier(),
- MemExpr->getQualifierRange(),
+ MemExpr->getQualifierLoc(),
Fn,
MemExpr->getMemberLoc(),
Fn->getType(),
VK_LValue,
+ Found.getDecl(),
TemplateArgs);
} else {
SourceLocation Loc = MemExpr->getMemberLoc();
if (MemExpr->getQualifier())
- Loc = MemExpr->getQualifierRange().getBegin();
+ Loc = MemExpr->getQualifierLoc().getBeginLoc();
Base = new (Context) CXXThisExpr(Loc,
MemExpr->getBaseType(),
/*isImplicit=*/true);
@@ -8972,18 +9281,24 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
} else
Base = MemExpr->getBase();
+ ExprValueKind valueKind;
+ QualType type;
+ if (cast<CXXMethodDecl>(Fn)->isStatic()) {
+ valueKind = VK_LValue;
+ type = Fn->getType();
+ } else {
+ valueKind = VK_RValue;
+ type = Context.BoundMemberTy;
+ }
+
return MemberExpr::Create(Context, Base,
MemExpr->isArrow(),
- MemExpr->getQualifier(),
- MemExpr->getQualifierRange(),
+ MemExpr->getQualifierLoc(),
Fn,
Found,
MemExpr->getMemberNameInfo(),
TemplateArgs,
- Fn->getType(),
- cast<CXXMethodDecl>(Fn)->isStatic()
- ? VK_LValue : VK_RValue,
- OK_Ordinary);
+ type, valueKind, OK_Ordinary);
}
llvm_unreachable("Invalid reference to overloaded function");
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
index 89957e6..65cea7a 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
@@ -15,6 +15,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
@@ -45,8 +46,9 @@ StmtResult Sema::ActOnExprStmt(FullExprArg expr) {
}
-StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc, bool LeadingEmptyMacro) {
- return Owned(new (Context) NullStmt(SemiLoc, LeadingEmptyMacro));
+StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc,
+ SourceLocation LeadingEmptyMacroLoc) {
+ return Owned(new (Context) NullStmt(SemiLoc, LeadingEmptyMacroLoc));
}
StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc,
@@ -76,12 +78,6 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
if (!E)
return;
- if (E->isBoundMemberFunction(Context)) {
- Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
- << E->getSourceRange();
- return;
- }
-
SourceLocation Loc;
SourceRange R1, R2;
if (!E->isUnusedResultAWarning(Loc, R1, R2, Context))
@@ -245,11 +241,10 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
}
// Otherwise, things are good. Fill in the declaration and return it.
- TheDecl->setLocation(IdentLoc);
-
LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt);
TheDecl->setStmt(LS);
- TheDecl->setLocation(IdentLoc);
+ if (!TheDecl->isGnuLocal())
+ TheDecl->setLocation(IdentLoc);
return Owned(LS);
}
@@ -470,7 +465,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
GetTypeBeforeIntegralPromotion(CondExpr);
// C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr.
- UsualUnaryConversions(CondExpr);
+ ExprResult CondResult = UsualUnaryConversions(CondExpr);
+ if (CondResult.isInvalid())
+ return StmtError();
+ CondExpr = CondResult.take();
QualType CondType = CondExpr->getType();
SS->setCond(CondExpr);
@@ -556,7 +554,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// If the LHS is not the same type as the condition, insert an implicit
// cast.
- ImpCastExprToType(Lo, CondType, CK_IntegralCast);
+ Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).take();
CS->setLHS(Lo);
// If this is a case range, remember it in CaseRanges, otherwise CaseVals.
@@ -635,7 +633,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// If the LHS is not the same type as the condition, insert an implicit
// cast.
- ImpCastExprToType(Hi, CondType, CK_IntegralCast);
+ Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).take();
CR->setRHS(Hi);
// If the low value is bigger than the high value, the case is empty.
@@ -869,11 +867,13 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
Expr *Cond, SourceLocation CondRParen) {
assert(Cond && "ActOnDoStmt(): missing expression");
- if (CheckBooleanCondition(Cond, DoLoc))
+ ExprResult CondResult = CheckBooleanCondition(Cond, DoLoc);
+ if (CondResult.isInvalid() || CondResult.isInvalid())
return StmtError();
+ Cond = CondResult.take();
CheckImplicitConversions(Cond, DoLoc);
- ExprResult CondResult = MaybeCreateExprWithCleanups(Cond);
+ CondResult = MaybeCreateExprWithCleanups(Cond);
if (CondResult.isInvalid())
return StmtError();
Cond = CondResult.take();
@@ -974,7 +974,10 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
<< FirstType << First->getSourceRange();
}
if (Second && !Second->isTypeDependent()) {
- DefaultFunctionArrayLvalueConversion(Second);
+ ExprResult Result = DefaultFunctionArrayLvalueConversion(Second);
+ if (Result.isInvalid())
+ return StmtError();
+ Second = Result.take();
QualType SecondType = Second->getType();
if (!SecondType->isObjCObjectPointerType())
Diag(ForLoc, diag::err_collection_expr_type)
@@ -992,7 +995,8 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
Selector CSelector = Context.Selectors.getSelector(3, &KeyIdents[0]);
if (ObjCInterfaceDecl *IDecl = OPT->getInterfaceDecl()) {
if (!IDecl->isForwardDecl() &&
- !IDecl->lookupInstanceMethod(CSelector)) {
+ !IDecl->lookupInstanceMethod(CSelector) &&
+ !LookupMethodInQualifiedType(CSelector, OPT, true)) {
// Must further look into private implementation methods.
if (!LookupPrivateInstanceMethod(CSelector, IDecl))
Diag(ForLoc, diag::warn_collection_expr_type)
@@ -1005,6 +1009,389 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
ForLoc, RParenLoc));
}
+namespace {
+
+enum BeginEndFunction {
+ BEF_begin,
+ BEF_end
+};
+
+/// Build a variable declaration for a for-range statement.
+static VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc,
+ QualType Type, const char *Name) {
+ DeclContext *DC = SemaRef.CurContext;
+ IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
+ TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
+ VarDecl *Decl = VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type,
+ TInfo, SC_Auto, SC_None);
+ Decl->setImplicit();
+ return Decl;
+}
+
+/// Finish building a variable declaration for a for-range statement.
+/// \return true if an error occurs.
+static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init,
+ SourceLocation Loc, int diag) {
+ // Deduce the type for the iterator variable now rather than leaving it to
+ // AddInitializerToDecl, so we can produce a more suitable diagnostic.
+ TypeSourceInfo *InitTSI = 0;
+ if (Init->getType()->isVoidType() ||
+ !SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitTSI))
+ SemaRef.Diag(Loc, diag) << Init->getType();
+ if (!InitTSI) {
+ Decl->setInvalidDecl();
+ return true;
+ }
+ Decl->setTypeSourceInfo(InitTSI);
+ Decl->setType(InitTSI->getType());
+
+ SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false,
+ /*TypeMayContainAuto=*/false);
+ SemaRef.FinalizeDeclaration(Decl);
+ SemaRef.CurContext->addHiddenDecl(Decl);
+ return false;
+}
+
+/// Produce a note indicating which begin/end function was implicitly called
+/// by a C++0x for-range statement. This is often not obvious from the code,
+/// nor from the diagnostics produced when analysing the implicit expressions
+/// required in a for-range statement.
+void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E,
+ BeginEndFunction BEF) {
+ CallExpr *CE = dyn_cast<CallExpr>(E);
+ if (!CE)
+ return;
+ FunctionDecl *D = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
+ if (!D)
+ return;
+ SourceLocation Loc = D->getLocation();
+
+ std::string Description;
+ bool IsTemplate = false;
+ if (FunctionTemplateDecl *FunTmpl = D->getPrimaryTemplate()) {
+ Description = SemaRef.getTemplateArgumentBindingsText(
+ FunTmpl->getTemplateParameters(), *D->getTemplateSpecializationArgs());
+ IsTemplate = true;
+ }
+
+ SemaRef.Diag(Loc, diag::note_for_range_begin_end)
+ << BEF << IsTemplate << Description << E->getType();
+}
+
+/// Build a call to 'begin' or 'end' for a C++0x for-range statement. If the
+/// given LookupResult is non-empty, it is assumed to describe a member which
+/// will be invoked. Otherwise, the function will be found via argument
+/// dependent lookup.
+static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S,
+ SourceLocation Loc,
+ VarDecl *Decl,
+ BeginEndFunction BEF,
+ const DeclarationNameInfo &NameInfo,
+ LookupResult &MemberLookup,
+ Expr *Range) {
+ ExprResult CallExpr;
+ if (!MemberLookup.empty()) {
+ ExprResult MemberRef =
+ SemaRef.BuildMemberReferenceExpr(Range, Range->getType(), Loc,
+ /*IsPtr=*/false, CXXScopeSpec(),
+ /*Qualifier=*/0, MemberLookup,
+ /*TemplateArgs=*/0);
+ if (MemberRef.isInvalid())
+ return ExprError();
+ CallExpr = SemaRef.ActOnCallExpr(S, MemberRef.get(), Loc, MultiExprArg(),
+ Loc, 0);
+ if (CallExpr.isInvalid())
+ return ExprError();
+ } else {
+ UnresolvedSet<0> FoundNames;
+ // C++0x [stmt.ranged]p1: For the purposes of this name lookup, namespace
+ // std is an associated namespace.
+ UnresolvedLookupExpr *Fn =
+ UnresolvedLookupExpr::Create(SemaRef.Context, /*NamingClass=*/0,
+ NestedNameSpecifierLoc(), NameInfo,
+ /*NeedsADL=*/true, /*Overloaded=*/false,
+ FoundNames.begin(), FoundNames.end(),
+ /*LookInStdNamespace=*/true);
+ CallExpr = SemaRef.BuildOverloadedCallExpr(S, Fn, Fn, Loc, &Range, 1, Loc,
+ 0);
+ if (CallExpr.isInvalid()) {
+ SemaRef.Diag(Range->getLocStart(), diag::note_for_range_type)
+ << Range->getType();
+ return ExprError();
+ }
+ }
+ if (FinishForRangeVarDecl(SemaRef, Decl, CallExpr.get(), Loc,
+ diag::err_for_range_iter_deduction_failure)) {
+ NoteForRangeBeginEndFunction(SemaRef, CallExpr.get(), BEF);
+ return ExprError();
+ }
+ return CallExpr;
+}
+
+}
+
+/// ActOnCXXForRangeStmt - Check and build a C++0x for-range statement.
+///
+/// C++0x [stmt.ranged]:
+/// A range-based for statement is equivalent to
+///
+/// {
+/// auto && __range = range-init;
+/// for ( auto __begin = begin-expr,
+/// __end = end-expr;
+/// __begin != __end;
+/// ++__begin ) {
+/// for-range-declaration = *__begin;
+/// statement
+/// }
+/// }
+///
+/// The body of the loop is not available yet, since it cannot be analysed until
+/// we have determined the type of the for-range-declaration.
+StmtResult
+Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+ Stmt *First, SourceLocation ColonLoc, Expr *Range,
+ SourceLocation RParenLoc) {
+ if (!First || !Range)
+ return StmtError();
+
+ DeclStmt *DS = dyn_cast<DeclStmt>(First);
+ assert(DS && "first part of for range not a decl stmt");
+
+ if (!DS->isSingleDecl()) {
+ Diag(DS->getStartLoc(), diag::err_type_defined_in_for_range);
+ return StmtError();
+ }
+ if (DS->getSingleDecl()->isInvalidDecl())
+ return StmtError();
+
+ if (DiagnoseUnexpandedParameterPack(Range, UPPC_Expression))
+ return StmtError();
+
+ // Build auto && __range = range-init
+ SourceLocation RangeLoc = Range->getLocStart();
+ VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc,
+ Context.getAutoRRefDeductType(),
+ "__range");
+ if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
+ diag::err_for_range_deduction_failure))
+ return StmtError();
+
+ // Claim the type doesn't contain auto: we've already done the checking.
+ DeclGroupPtrTy RangeGroup =
+ BuildDeclaratorGroup((Decl**)&RangeVar, 1, /*TypeMayContainAuto=*/false);
+ StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc);
+ if (RangeDecl.isInvalid())
+ return StmtError();
+
+ return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(),
+ /*BeginEndDecl=*/0, /*Cond=*/0, /*Inc=*/0, DS,
+ RParenLoc);
+}
+
+/// BuildCXXForRangeStmt - Build or instantiate a C++0x for-range statement.
+StmtResult
+Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
+ Stmt *RangeDecl, Stmt *BeginEnd, Expr *Cond,
+ Expr *Inc, Stmt *LoopVarDecl,
+ SourceLocation RParenLoc) {
+ Scope *S = getCurScope();
+
+ DeclStmt *RangeDS = cast<DeclStmt>(RangeDecl);
+ VarDecl *RangeVar = cast<VarDecl>(RangeDS->getSingleDecl());
+ QualType RangeVarType = RangeVar->getType();
+
+ DeclStmt *LoopVarDS = cast<DeclStmt>(LoopVarDecl);
+ VarDecl *LoopVar = cast<VarDecl>(LoopVarDS->getSingleDecl());
+
+ StmtResult BeginEndDecl = BeginEnd;
+ ExprResult NotEqExpr = Cond, IncrExpr = Inc;
+
+ if (!BeginEndDecl.get() && !RangeVarType->isDependentType()) {
+ SourceLocation RangeLoc = RangeVar->getLocation();
+
+ ExprResult RangeRef = BuildDeclRefExpr(RangeVar,
+ RangeVarType.getNonReferenceType(),
+ VK_LValue, ColonLoc);
+ if (RangeRef.isInvalid())
+ return StmtError();
+
+ QualType AutoType = Context.getAutoDeductType();
+ Expr *Range = RangeVar->getInit();
+ if (!Range)
+ return StmtError();
+ QualType RangeType = Range->getType();
+
+ if (RequireCompleteType(RangeLoc, RangeType,
+ PDiag(diag::err_for_range_incomplete_type)))
+ return StmtError();
+
+ // Build auto __begin = begin-expr, __end = end-expr.
+ VarDecl *BeginVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,
+ "__begin");
+ VarDecl *EndVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,
+ "__end");
+
+ // Build begin-expr and end-expr and attach to __begin and __end variables.
+ ExprResult BeginExpr, EndExpr;
+ if (const ArrayType *UnqAT = RangeType->getAsArrayTypeUnsafe()) {
+ // - if _RangeT is an array type, begin-expr and end-expr are __range and
+ // __range + __bound, respectively, where __bound is the array bound. If
+ // _RangeT is an array of unknown size or an array of incomplete type,
+ // the program is ill-formed;
+
+ // begin-expr is __range.
+ BeginExpr = RangeRef;
+ if (FinishForRangeVarDecl(*this, BeginVar, RangeRef.get(), ColonLoc,
+ diag::err_for_range_iter_deduction_failure)) {
+ NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
+ return StmtError();
+ }
+
+ // Find the array bound.
+ ExprResult BoundExpr;
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(UnqAT))
+ BoundExpr = Owned(IntegerLiteral::Create(Context, CAT->getSize(),
+ Context.IntTy, RangeLoc));
+ else if (const VariableArrayType *VAT =
+ dyn_cast<VariableArrayType>(UnqAT))
+ BoundExpr = VAT->getSizeExpr();
+ else {
+ // Can't be a DependentSizedArrayType or an IncompleteArrayType since
+ // UnqAT is not incomplete and Range is not type-dependent.
+ assert(0 && "Unexpected array type in for-range");
+ return StmtError();
+ }
+
+ // end-expr is __range + __bound.
+ EndExpr = ActOnBinOp(S, ColonLoc, tok::plus, RangeRef.get(),
+ BoundExpr.get());
+ if (EndExpr.isInvalid())
+ return StmtError();
+ if (FinishForRangeVarDecl(*this, EndVar, EndExpr.get(), ColonLoc,
+ diag::err_for_range_iter_deduction_failure)) {
+ NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end);
+ return StmtError();
+ }
+ } else {
+ DeclarationNameInfo BeginNameInfo(&PP.getIdentifierTable().get("begin"),
+ ColonLoc);
+ DeclarationNameInfo EndNameInfo(&PP.getIdentifierTable().get("end"),
+ ColonLoc);
+
+ LookupResult BeginMemberLookup(*this, BeginNameInfo, LookupMemberName);
+ LookupResult EndMemberLookup(*this, EndNameInfo, LookupMemberName);
+
+ if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) {
+ // - if _RangeT is a class type, the unqualified-ids begin and end are
+ // looked up in the scope of class _RangeT as if by class member access
+ // lookup (3.4.5), and if either (or both) finds at least one
+ // declaration, begin-expr and end-expr are __range.begin() and
+ // __range.end(), respectively;
+ LookupQualifiedName(BeginMemberLookup, D);
+ LookupQualifiedName(EndMemberLookup, D);
+
+ if (BeginMemberLookup.empty() != EndMemberLookup.empty()) {
+ Diag(ColonLoc, diag::err_for_range_member_begin_end_mismatch)
+ << RangeType << BeginMemberLookup.empty();
+ return StmtError();
+ }
+ } else {
+ // - otherwise, begin-expr and end-expr are begin(__range) and
+ // end(__range), respectively, where begin and end are looked up with
+ // argument-dependent lookup (3.4.2). For the purposes of this name
+ // lookup, namespace std is an associated namespace.
+ }
+
+ BeginExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, BeginVar,
+ BEF_begin, BeginNameInfo,
+ BeginMemberLookup, RangeRef.get());
+ if (BeginExpr.isInvalid())
+ return StmtError();
+
+ EndExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, EndVar,
+ BEF_end, EndNameInfo,
+ EndMemberLookup, RangeRef.get());
+ if (EndExpr.isInvalid())
+ return StmtError();
+ }
+
+ // C++0x [decl.spec.auto]p6: BeginType and EndType must be the same.
+ QualType BeginType = BeginVar->getType(), EndType = EndVar->getType();
+ if (!Context.hasSameType(BeginType, EndType)) {
+ Diag(RangeLoc, diag::err_for_range_begin_end_types_differ)
+ << BeginType << EndType;
+ NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
+ NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end);
+ }
+
+ Decl *BeginEndDecls[] = { BeginVar, EndVar };
+ // Claim the type doesn't contain auto: we've already done the checking.
+ DeclGroupPtrTy BeginEndGroup =
+ BuildDeclaratorGroup(BeginEndDecls, 2, /*TypeMayContainAuto=*/false);
+ BeginEndDecl = ActOnDeclStmt(BeginEndGroup, ColonLoc, ColonLoc);
+
+ ExprResult BeginRef = BuildDeclRefExpr(BeginVar,
+ BeginType.getNonReferenceType(),
+ VK_LValue, ColonLoc);
+ ExprResult EndRef = BuildDeclRefExpr(EndVar, EndType.getNonReferenceType(),
+ VK_LValue, ColonLoc);
+
+ // Build and check __begin != __end expression.
+ NotEqExpr = ActOnBinOp(S, ColonLoc, tok::exclaimequal,
+ BeginRef.get(), EndRef.get());
+ NotEqExpr = ActOnBooleanCondition(S, ColonLoc, NotEqExpr.get());
+ NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get());
+ if (NotEqExpr.isInvalid()) {
+ NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
+ if (!Context.hasSameType(BeginType, EndType))
+ NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end);
+ return StmtError();
+ }
+
+ // Build and check ++__begin expression.
+ IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get());
+ IncrExpr = ActOnFinishFullExpr(IncrExpr.get());
+ if (IncrExpr.isInvalid()) {
+ NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
+ return StmtError();
+ }
+
+ // Build and check *__begin expression.
+ ExprResult DerefExpr = ActOnUnaryOp(S, ColonLoc, tok::star, BeginRef.get());
+ if (DerefExpr.isInvalid()) {
+ NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
+ return StmtError();
+ }
+
+ // Attach *__begin as initializer for VD.
+ if (!LoopVar->isInvalidDecl()) {
+ AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false,
+ /*TypeMayContainAuto=*/true);
+ if (LoopVar->isInvalidDecl())
+ NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
+ }
+ }
+
+ return Owned(new (Context) CXXForRangeStmt(RangeDS,
+ cast_or_null<DeclStmt>(BeginEndDecl.get()),
+ NotEqExpr.take(), IncrExpr.take(),
+ LoopVarDS, /*Body=*/0, ForLoc,
+ ColonLoc, RParenLoc));
+}
+
+/// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement.
+/// This is a separate step from ActOnCXXForRangeStmt because analysis of the
+/// body cannot be performed until after the type of the range variable is
+/// determined.
+StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) {
+ if (!S || !B)
+ return StmtError();
+
+ cast<CXXForRangeStmt>(S)->setBody(B);
+ return S;
+}
+
StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc,
SourceLocation LabelLoc,
LabelDecl *TheDecl) {
@@ -1020,8 +1407,12 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
if (!E->isTypeDependent()) {
QualType ETy = E->getType();
QualType DestTy = Context.getPointerType(Context.VoidTy.withConst());
+ ExprResult ExprRes = Owned(E);
AssignConvertType ConvTy =
- CheckSingleAssignmentConstraints(DestTy, E);
+ CheckSingleAssignmentConstraints(DestTy, ExprRes);
+ if (ExprRes.isInvalid())
+ return StmtError();
+ E = ExprRes.take();
if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing))
return StmtError();
}
@@ -1188,7 +1579,10 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (RetValExp) {
// Don't call UsualUnaryConversions(), since we don't want to do
// integer promotions here.
- DefaultFunctionArrayLvalueConversion(RetValExp);
+ ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp);
+ if (Result.isInvalid())
+ return StmtError();
+ RetValExp = Result.take();
CurBlock->ReturnType = RetValExp->getType();
if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) {
// We have to remove a 'const' added to copied-in variable which was
@@ -1290,8 +1684,12 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (RetValExp->getType()->isVoidType())
D = diag::ext_return_has_void_expr;
else {
- IgnoredValueConversions(RetValExp);
- ImpCastExprToType(RetValExp, Context.VoidTy, CK_ToVoid);
+ ExprResult Result = Owned(RetValExp);
+ Result = IgnoredValueConversions(Result.take());
+ if (Result.isInvalid())
+ return StmtError();
+ RetValExp = Result.take();
+ RetValExp = ImpCastExprToType(RetValExp, Context.VoidTy, CK_ToVoid).take();
}
// return (some void expression); is legal in C++.
@@ -1498,8 +1896,11 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple,
}
}
- DefaultFunctionArrayLvalueConversion(Exprs[i]);
+ ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
+ if (Result.isInvalid())
+ return StmtError();
+ Exprs[i] = Result.take();
InputConstraintInfos.push_back(Info);
}
@@ -1614,7 +2015,7 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple,
if (InputDomain == AD_Int && OutputDomain == AD_Int &&
!isOperandMentioned(InputOpNo, Pieces) &&
InputExpr->isEvaluatable(Context)) {
- ImpCastExprToType(InputExpr, OutTy, CK_IntegralCast);
+ InputExpr = ImpCastExprToType(InputExpr, OutTy, CK_IntegralCast).take();
Exprs[InputOpNo] = InputExpr;
NS->setInputExpr(i, InputExpr);
continue;
@@ -1663,8 +2064,11 @@ Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc,
Expr *Throw) {
if (Throw) {
- DefaultLvalueConversion(Throw);
+ ExprResult Result = DefaultLvalueConversion(Throw);
+ if (Result.isInvalid())
+ return StmtError();
+ Throw = Result.take();
QualType ThrowType = Throw->getType();
// Make sure the expression type is an ObjC pointer or "void *".
if (!ThrowType->isDependentType() &&
@@ -1703,8 +2107,11 @@ Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr,
Stmt *SyncBody) {
getCurFunction()->setHasBranchProtectedScope();
- DefaultLvalueConversion(SyncExpr);
+ ExprResult Result = DefaultLvalueConversion(SyncExpr);
+ if (Result.isInvalid())
+ return StmtError();
+ SyncExpr = Result.take();
// Make sure the expression type is an ObjC pointer or "void *".
if (!SyncExpr->getType()->isDependentType() &&
!SyncExpr->getType()->isObjCObjectPointerType()) {
@@ -1766,7 +2173,7 @@ StmtResult
Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
MultiStmtArg RawHandlers) {
// Don't report an error if 'try' is used in system headers.
- if (!getLangOptions().Exceptions &&
+ if (!getLangOptions().CXXExceptions &&
!getSourceManager().isInSystemHeader(TryLoc))
Diag(TryLoc, diag::err_exceptions_disabled) << "try";
@@ -1824,3 +2231,36 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock,
Handlers, NumHandlers));
}
+
+StmtResult
+Sema::ActOnSEHTryBlock(bool IsCXXTry,
+ SourceLocation TryLoc,
+ Stmt *TryBlock,
+ Stmt *Handler) {
+ assert(TryBlock && Handler);
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return Owned(SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler));
+}
+
+StmtResult
+Sema::ActOnSEHExceptBlock(SourceLocation Loc,
+ Expr *FilterExpr,
+ Stmt *Block) {
+ assert(FilterExpr && Block);
+
+ if(!FilterExpr->getType()->isIntegerType()) {
+ return StmtError(Diag(FilterExpr->getExprLoc(), diag::err_filter_expression_integral) << FilterExpr->getType());
+ }
+
+ return Owned(SEHExceptStmt::Create(Context,Loc,FilterExpr,Block));
+}
+
+StmtResult
+Sema::ActOnSEHFinallyBlock(SourceLocation Loc,
+ Stmt *Block) {
+ assert(Block);
+ return Owned(SEHFinallyStmt::Create(Context,Loc,Block));
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
index f02dd25..ef09124 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -76,13 +76,13 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
return 0;
}
-static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) {
+void Sema::FilterAcceptableTemplateNames(LookupResult &R) {
// The set of class templates we've already seen.
llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates;
LookupResult::Filter filter = R.makeFilter();
while (filter.hasNext()) {
NamedDecl *Orig = filter.next();
- NamedDecl *Repl = isAcceptableTemplateName(C, Orig);
+ NamedDecl *Repl = isAcceptableTemplateName(Context, Orig);
if (!Repl)
filter.erase();
else if (Repl != Orig) {
@@ -114,6 +114,14 @@ static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) {
filter.done();
}
+bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R) {
+ for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I)
+ if (isAcceptableTemplateName(Context, *I))
+ return true;
+
+ return false;
+}
+
TemplateNameKind Sema::isTemplateName(Scope *S,
CXXScopeSpec &SS,
bool hasTemplateKeyword,
@@ -289,7 +297,7 @@ void Sema::LookupTemplateName(LookupResult &Found,
DeclarationName Name = Found.getLookupName();
if (DeclarationName Corrected = CorrectTypo(Found, S, &SS, LookupCtx,
false, CTC_CXXCasts)) {
- FilterAcceptableTemplateNames(Context, Found);
+ FilterAcceptableTemplateNames(Found);
if (!Found.empty()) {
if (LookupCtx)
Diag(Found.getNameLoc(), diag::err_no_member_template_suggest)
@@ -311,7 +319,7 @@ void Sema::LookupTemplateName(LookupResult &Found,
}
}
- FilterAcceptableTemplateNames(Context, Found);
+ FilterAcceptableTemplateNames(Found);
if (Found.empty()) {
if (isDependent)
MemberOfUnknownSpecialization = true;
@@ -327,7 +335,7 @@ void Sema::LookupTemplateName(LookupResult &Found,
LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(),
LookupOrdinaryName);
LookupName(FoundOuter, S);
- FilterAcceptableTemplateNames(Context, FoundOuter);
+ FilterAcceptableTemplateNames(FoundOuter);
if (FoundOuter.empty()) {
// - if the name is not found, the name found in the class of the
@@ -368,9 +376,6 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
const DeclarationNameInfo &NameInfo,
bool isAddressOfOperand,
const TemplateArgumentListInfo *TemplateArgs) {
- NestedNameSpecifier *Qualifier
- = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
-
DeclContext *DC = getFunctionLevelDeclContext();
if (!isAddressOfOperand &&
@@ -386,7 +391,7 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
/*This*/ 0, ThisType,
/*IsArrow*/ true,
/*Op*/ SourceLocation(),
- Qualifier, SS.getRange(),
+ SS.getWithLocInContext(Context),
FirstQualifierInScope,
NameInfo,
TemplateArgs));
@@ -472,7 +477,8 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
else
TArg = Template;
return TemplateArgumentLoc(TArg,
- Arg.getScopeSpec().getRange(),
+ Arg.getScopeSpec().getWithLocInContext(
+ SemaRef.Context),
Arg.getLocation(),
Arg.getEllipsisLoc());
}
@@ -497,7 +503,7 @@ void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn,
/// (otherwise, "class" was used), and KeyLoc is the location of the
/// "class" or "typename" keyword. ParamName is the name of the
/// parameter (NULL indicates an unnamed template parameter) and
-/// ParamName is the location of the parameter name (if any).
+/// ParamNameLoc is the location of the parameter name (if any).
/// If the type parameter has a default argument, it will be added
/// later via ActOnTypeParameterDefault.
Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
@@ -527,8 +533,9 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
TemplateTypeParmDecl *Param
= TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(),
- Loc, Depth, Position, ParamName, Typename,
- Ellipsis);
+ KeyLoc, Loc, Depth, Position, ParamName,
+ Typename, Ellipsis);
+ Param->setAccess(AS_public);
if (Invalid)
Param->setInvalidDecl();
@@ -651,9 +658,12 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
bool IsParameterPack = D.hasEllipsis();
NonTypeTemplateParmDecl *Param
= NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
+ D.getSourceRange().getBegin(),
D.getIdentifierLoc(),
Depth, Position, ParamName, T,
IsParameterPack, TInfo);
+ Param->setAccess(AS_public);
+
if (Invalid)
Param->setInvalidDecl();
@@ -678,10 +688,12 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
return Param;
TemplateArgument Converted;
- if (CheckTemplateArgument(Param, Param->getType(), Default, Converted)) {
+ ExprResult DefaultRes = CheckTemplateArgument(Param, Param->getType(), Default, Converted);
+ if (DefaultRes.isInvalid()) {
Param->setInvalidDecl();
return Param;
}
+ Default = DefaultRes.take();
Param->setDefaultArgument(Default, false);
}
@@ -707,13 +719,13 @@ Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,
// Construct the parameter object.
bool IsParameterPack = EllipsisLoc.isValid();
- // FIXME: Pack-ness is dropped
TemplateTemplateParmDecl *Param =
TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
NameLoc.isInvalid()? TmpLoc : NameLoc,
Depth, Position, IsParameterPack,
Name, Params);
-
+ Param->setAccess(AS_public);
+
// If the template template parameter has a name, then link the identifier
// into the scope and lookup mechanisms.
if (Name) {
@@ -791,7 +803,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr,
TemplateParameterList *TemplateParams,
- AccessSpecifier AS) {
+ AccessSpecifier AS,
+ unsigned NumOuterTemplateParamLists,
+ TemplateParameterList** OuterTemplateParamLists) {
assert(TemplateParams && TemplateParams->size() > 0 &&
"No template parameters");
assert(TUK != TUK_Reference && "Can only declare or define class templates");
@@ -961,11 +975,15 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
CXXRecordDecl *NewClass =
- CXXRecordDecl::Create(Context, Kind, SemanticContext, NameLoc, Name, KWLoc,
+ CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
PrevClassTemplate?
PrevClassTemplate->getTemplatedDecl() : 0,
/*DelayTypeCreation=*/true);
SetNestedNameSpecifier(NewClass, SS);
+ if (NumOuterTemplateParamLists > 0)
+ NewClass->setTemplateParameterListsInfo(Context,
+ NumOuterTemplateParamLists,
+ OuterTemplateParamLists);
ClassTemplateDecl *NewTemplate
= ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
@@ -1089,7 +1107,8 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S,
/// \brief Check for unexpanded parameter packs within the template parameters
/// of a template template parameter, recursively.
-bool DiagnoseUnexpandedParameterPacks(Sema &S, TemplateTemplateParmDecl *TTP){
+static bool DiagnoseUnexpandedParameterPacks(Sema &S,
+ TemplateTemplateParmDecl *TTP) {
TemplateParameterList *Params = TTP->getTemplateParameters();
for (unsigned I = 0, N = Params->size(); I != N; ++I) {
NamedDecl *P = Params->getParam(I);
@@ -1448,9 +1467,9 @@ DependsOnTemplateParameters(const TemplateSpecializationType *TemplateId,
///
/// \returns the template parameter list, if any, that corresponds to the
/// name that is preceded by the scope specifier @p SS. This template
-/// parameter list may be have template parameters (if we're declaring a
+/// parameter list may have template parameters (if we're declaring a
/// template) or may have no template parameters (if we're declaring a
-/// template specialization), or may be NULL (if we were's declaring isn't
+/// template specialization), or may be NULL (if what we're declaring isn't
/// itself a template).
TemplateParameterList *
Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
@@ -1631,14 +1650,42 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
return ParamLists[NumParamLists - 1];
}
+void Sema::NoteAllFoundTemplates(TemplateName Name) {
+ if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ Diag(Template->getLocation(), diag::note_template_declared_here)
+ << (isa<FunctionTemplateDecl>(Template)? 0
+ : isa<ClassTemplateDecl>(Template)? 1
+ : 2)
+ << Template->getDeclName();
+ return;
+ }
+
+ if (OverloadedTemplateStorage *OST = Name.getAsOverloadedTemplate()) {
+ for (OverloadedTemplateStorage::iterator I = OST->begin(),
+ IEnd = OST->end();
+ I != IEnd; ++I)
+ Diag((*I)->getLocation(), diag::note_template_declared_here)
+ << 0 << (*I)->getDeclName();
+
+ return;
+ }
+}
+
+
QualType Sema::CheckTemplateIdType(TemplateName Name,
SourceLocation TemplateLoc,
- const TemplateArgumentListInfo &TemplateArgs) {
+ TemplateArgumentListInfo &TemplateArgs) {
TemplateDecl *Template = Name.getAsTemplateDecl();
- if (!Template) {
- // The template name does not resolve to a template, so we just
- // build a dependent template-id type.
- return Context.getTemplateSpecializationType(Name, TemplateArgs);
+ if (!Template || isa<FunctionTemplateDecl>(Template)) {
+ // We might have a substituted template template parameter pack. If so,
+ // build a template specialization type for it.
+ if (Name.getAsSubstTemplateTemplateParmPack())
+ return Context.getTemplateSpecializationType(Name, TemplateArgs);
+
+ Diag(TemplateLoc, diag::err_template_id_not_a_type)
+ << Name;
+ NoteAllFoundTemplates(Name);
+ return QualType();
}
// Check that the template argument list is well-formed for this
@@ -1727,6 +1774,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
ClassTemplate->getTemplatedDecl()->getTagKind(),
ClassTemplate->getDeclContext(),
ClassTemplate->getLocation(),
+ ClassTemplate->getLocation(),
ClassTemplate,
Converted.data(),
Converted.size(), 0);
@@ -1746,77 +1794,148 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
}
TypeResult
-Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
+Sema::ActOnTemplateIdType(CXXScopeSpec &SS,
+ TemplateTy TemplateD, SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation RAngleLoc) {
+ if (SS.isInvalid())
+ return true;
+
TemplateName Template = TemplateD.getAsVal<TemplateName>();
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+ if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
+ QualType T = Context.getDependentTemplateSpecializationType(ETK_None,
+ DTN->getQualifier(),
+ DTN->getIdentifier(),
+ TemplateArgs);
+
+ // Build type-source information.
+ TypeLocBuilder TLB;
+ DependentTemplateSpecializationTypeLoc SpecTL
+ = TLB.push<DependentTemplateSpecializationTypeLoc>(T);
+ SpecTL.setKeywordLoc(SourceLocation());
+ SpecTL.setNameLoc(TemplateLoc);
+ SpecTL.setLAngleLoc(LAngleLoc);
+ SpecTL.setRAngleLoc(RAngleLoc);
+ SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I)
+ SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+ return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
+ }
+
QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
TemplateArgsIn.release();
if (Result.isNull())
return true;
- TypeSourceInfo *DI = Context.CreateTypeSourceInfo(Result);
- TemplateSpecializationTypeLoc TL
- = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc());
- TL.setTemplateNameLoc(TemplateLoc);
- TL.setLAngleLoc(LAngleLoc);
- TL.setRAngleLoc(RAngleLoc);
- for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
- TL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
-
- return CreateParsedType(Result, DI);
+ // Build type-source information.
+ TypeLocBuilder TLB;
+ TemplateSpecializationTypeLoc SpecTL
+ = TLB.push<TemplateSpecializationTypeLoc>(Result);
+ SpecTL.setTemplateNameLoc(TemplateLoc);
+ SpecTL.setLAngleLoc(LAngleLoc);
+ SpecTL.setRAngleLoc(RAngleLoc);
+ for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i)
+ SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
+
+ if (SS.isNotEmpty()) {
+ // Create an elaborated-type-specifier containing the nested-name-specifier.
+ Result = Context.getElaboratedType(ETK_None, SS.getScopeRep(), Result);
+ ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result);
+ ElabTL.setKeywordLoc(SourceLocation());
+ ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ }
+
+ return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
}
-TypeResult Sema::ActOnTagTemplateIdType(CXXScopeSpec &SS,
- TypeResult TypeResult,
- TagUseKind TUK,
+TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
TypeSpecifierType TagSpec,
- SourceLocation TagLoc) {
- if (TypeResult.isInvalid())
- return ::TypeResult();
-
- TypeSourceInfo *DI;
- QualType Type = GetTypeFromParser(TypeResult.get(), &DI);
-
- // Verify the tag specifier.
+ SourceLocation TagLoc,
+ CXXScopeSpec &SS,
+ TemplateTy TemplateD,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation RAngleLoc) {
+ TemplateName Template = TemplateD.getAsVal<TemplateName>();
+
+ // Translate the parser's template argument list in our AST format.
+ TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+ translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+ // Determine the tag kind
TagTypeKind TagKind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+ ElaboratedTypeKeyword Keyword
+ = TypeWithKeyword::getKeywordForTagTypeKind(TagKind);
- if (const RecordType *RT = Type->getAs<RecordType>()) {
+ if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
+ QualType T = Context.getDependentTemplateSpecializationType(Keyword,
+ DTN->getQualifier(),
+ DTN->getIdentifier(),
+ TemplateArgs);
+
+ // Build type-source information.
+ TypeLocBuilder TLB;
+ DependentTemplateSpecializationTypeLoc SpecTL
+ = TLB.push<DependentTemplateSpecializationTypeLoc>(T);
+ SpecTL.setKeywordLoc(TagLoc);
+ SpecTL.setNameLoc(TemplateLoc);
+ SpecTL.setLAngleLoc(LAngleLoc);
+ SpecTL.setRAngleLoc(RAngleLoc);
+ SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I)
+ SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+ return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
+ }
+
+ QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
+ if (Result.isNull())
+ return TypeResult();
+
+ // Check the tag kind
+ if (const RecordType *RT = Result->getAs<RecordType>()) {
RecordDecl *D = RT->getDecl();
-
+
IdentifierInfo *Id = D->getIdentifier();
assert(Id && "templated class must have an identifier");
-
+
if (!isAcceptableTagRedeclaration(D, TagKind, TagLoc, *Id)) {
Diag(TagLoc, diag::err_use_with_wrong_tag)
- << Type
+ << Result
<< FixItHint::CreateReplacement(SourceRange(TagLoc), D->getKindName());
Diag(D->getLocation(), diag::note_previous_use);
}
}
-
- ElaboratedTypeKeyword Keyword
- = TypeWithKeyword::getKeywordForTagTypeKind(TagKind);
- QualType ElabType = Context.getElaboratedType(Keyword, /*NNS=*/0, Type);
-
- TypeSourceInfo *ElabDI = Context.CreateTypeSourceInfo(ElabType);
- ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(ElabDI->getTypeLoc());
- TL.setKeywordLoc(TagLoc);
- TL.setQualifierRange(SS.getRange());
- TL.getNamedTypeLoc().initializeFullCopy(DI->getTypeLoc());
- return CreateParsedType(ElabType, ElabDI);
+
+ // Provide source-location information for the template specialization.
+ TypeLocBuilder TLB;
+ TemplateSpecializationTypeLoc SpecTL
+ = TLB.push<TemplateSpecializationTypeLoc>(Result);
+ SpecTL.setTemplateNameLoc(TemplateLoc);
+ SpecTL.setLAngleLoc(LAngleLoc);
+ SpecTL.setRAngleLoc(RAngleLoc);
+ for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i)
+ SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
+
+ // Construct an elaborated type containing the nested-name-specifier (if any)
+ // and keyword.
+ Result = Context.getElaboratedType(Keyword, SS.getScopeRep(), Result);
+ ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result);
+ ElabTL.setKeywordLoc(TagLoc);
+ ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
}
ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
- LookupResult &R,
- bool RequiresADL,
+ LookupResult &R,
+ bool RequiresADL,
const TemplateArgumentListInfo &TemplateArgs) {
// FIXME: Can we do any checking at this point? I guess we could check the
// template arguments that we have against the template name, if the template
@@ -1832,19 +1951,12 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
assert(!R.empty() && "empty lookup results when building templateid");
assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");
- NestedNameSpecifier *Qualifier = 0;
- SourceRange QualifierRange;
- if (SS.isSet()) {
- Qualifier = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
- QualifierRange = SS.getRange();
- }
-
// We don't want lookup warnings at this point.
R.suppressDiagnostics();
UnresolvedLookupExpr *ULE
= UnresolvedLookupExpr::Create(Context, R.getNamingClass(),
- Qualifier, QualifierRange,
+ SS.getWithLocInContext(Context),
R.getLookupNameInfo(),
RequiresADL, TemplateArgs,
R.begin(), R.end());
@@ -1935,7 +2047,8 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
MemberOfUnknownSpecialization);
if (TNK == TNK_Non_template && LookupCtx->isDependentContext() &&
isa<CXXRecordDecl>(LookupCtx) &&
- cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()) {
+ (!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() ||
+ cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases())) {
// This is a dependent template. Handle it below.
} else if (TNK == TNK_Non_template) {
Diag(Name.getSourceRange().getBegin(),
@@ -2043,7 +2156,6 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
///
/// \param Converted the list of template arguments provided for template
/// parameters that precede \p Param in the template parameter list.
-///
/// \returns the substituted template argument, or NULL if an error occurred.
static TypeSourceInfo *
SubstDefaultTemplateArgument(Sema &SemaRef,
@@ -2140,6 +2252,9 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
/// \param Converted the list of template arguments provided for template
/// parameters that precede \p Param in the template parameter list.
///
+/// \param QualifierLoc Will be set to the nested-name-specifier (with
+/// source-location information) that precedes the template name.
+///
/// \returns the substituted template argument, or NULL if an error occurred.
static TemplateName
SubstDefaultTemplateArgument(Sema &SemaRef,
@@ -2147,7 +2262,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
TemplateTemplateParmDecl *Param,
- llvm::SmallVectorImpl<TemplateArgument> &Converted) {
+ llvm::SmallVectorImpl<TemplateArgument> &Converted,
+ NestedNameSpecifierLoc &QualifierLoc) {
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
Converted.data(), Converted.size());
@@ -2159,7 +2275,16 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
Converted.size(),
SourceRange(TemplateLoc, RAngleLoc));
- return SemaRef.SubstTemplateName(
+ // Substitute into the nested-name-specifier first,
+ QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
+ AllTemplateArgs);
+ if (!QualifierLoc)
+ return TemplateName();
+ }
+
+ return SemaRef.SubstTemplateName(QualifierLoc,
Param->getDefaultArgument().getArgument().getAsTemplate(),
Param->getDefaultArgument().getTemplateNameLoc(),
AllTemplateArgs);
@@ -2195,10 +2320,10 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
return TemplateArgumentLoc();
ExprResult Arg = SubstDefaultTemplateArgument(*this, Template,
- TemplateLoc,
- RAngleLoc,
- NonTypeParm,
- Converted);
+ TemplateLoc,
+ RAngleLoc,
+ NonTypeParm,
+ Converted);
if (Arg.isInvalid())
return TemplateArgumentLoc();
@@ -2211,16 +2336,19 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
if (!TempTempParm->hasDefaultArgument())
return TemplateArgumentLoc();
+
+ NestedNameSpecifierLoc QualifierLoc;
TemplateName TName = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
RAngleLoc,
TempTempParm,
- Converted);
+ Converted,
+ QualifierLoc);
if (TName.isNull())
return TemplateArgumentLoc();
return TemplateArgumentLoc(TemplateArgument(TName),
- TempTempParm->getDefaultArgument().getTemplateQualifierRange(),
+ TempTempParm->getDefaultArgument().getTemplateQualifierLoc(),
TempTempParm->getDefaultArgument().getTemplateNameLoc());
}
@@ -2300,9 +2428,11 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
return true;
case TemplateArgument::Expression: {
- Expr *E = Arg.getArgument().getAsExpr();
TemplateArgument Result;
- if (CheckTemplateArgument(NTTP, NTTPType, E, Result, CTAK))
+ ExprResult Res =
+ CheckTemplateArgument(NTTP, NTTPType, Arg.getArgument().getAsExpr(),
+ Result, CTAK);
+ if (Res.isInvalid())
return true;
Converted.push_back(Result);
@@ -2331,28 +2461,23 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
DeclarationNameInfo NameInfo(DTN->getIdentifier(),
Arg.getTemplateNameLoc());
- // FIXME: TemplateArgumentLoc should store a NestedNameSpecifierLoc
- // for the template name.
CXXScopeSpec SS;
- SS.MakeTrivial(Context, DTN->getQualifier(),
- Arg.getTemplateQualifierRange());
- Expr *E = DependentScopeDeclRefExpr::Create(Context,
+ SS.Adopt(Arg.getTemplateQualifierLoc());
+ ExprResult E = Owned(DependentScopeDeclRefExpr::Create(Context,
SS.getWithLocInContext(Context),
- NameInfo);
+ NameInfo));
// If we parsed the template argument as a pack expansion, create a
// pack expansion expression.
if (Arg.getArgument().getKind() == TemplateArgument::TemplateExpansion){
- ExprResult Expansion = ActOnPackExpansion(E,
- Arg.getTemplateEllipsisLoc());
- if (Expansion.isInvalid())
+ E = ActOnPackExpansion(E.take(), Arg.getTemplateEllipsisLoc());
+ if (E.isInvalid())
return true;
-
- E = Expansion.get();
}
TemplateArgument Result;
- if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
+ E = CheckTemplateArgument(NTTP, NTTPType, E.take(), Result);
+ if (E.isInvalid())
return true;
Converted.push_back(Result);
@@ -2461,7 +2586,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
/// for specializing the given template.
bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
SourceLocation TemplateLoc,
- const TemplateArgumentListInfo &TemplateArgs,
+ TemplateArgumentListInfo &TemplateArgs,
bool PartialTemplateArgs,
llvm::SmallVectorImpl<TemplateArgument> &Converted) {
TemplateParameterList *Params = Template->getTemplateParameters();
@@ -2499,6 +2624,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// a template-id shall match the type and form specified for the
// corresponding parameter declared by the template in its
// template-parameter-list.
+ bool isTemplateTemplateParameter = isa<TemplateTemplateParmDecl>(Template);
llvm::SmallVector<TemplateArgument, 2> ArgumentPack;
TemplateParameterList::iterator Param = Params->begin(),
ParamEnd = Params->end();
@@ -2604,17 +2730,18 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
break;
}
+ NestedNameSpecifierLoc QualifierLoc;
TemplateName Name = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
RAngleLoc,
TempParm,
- Converted);
+ Converted,
+ QualifierLoc);
if (Name.isNull())
return true;
- Arg = TemplateArgumentLoc(TemplateArgument(Name),
- TempParm->getDefaultArgument().getTemplateQualifierRange(),
- TempParm->getDefaultArgument().getTemplateNameLoc());
+ Arg = TemplateArgumentLoc(TemplateArgument(Name), QualifierLoc,
+ TempParm->getDefaultArgument().getTemplateNameLoc());
}
// Introduce an instantiation record that describes where we are using
@@ -2628,6 +2755,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
RAngleLoc, 0, Converted))
return true;
+ // Core issue 150 (assumed resolution): if this is a template template
+ // parameter, keep track of the default template arguments from the
+ // template definition.
+ if (isTemplateTemplateParameter)
+ TemplateArgs.addArgument(Arg);
+
// Move to the next template parameter and argument.
++Param;
++ArgIdx;
@@ -2853,7 +2986,7 @@ bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
return true;
}
- if (!Tag->getDeclName() && !Tag->getTypedefForAnonDecl()) {
+ if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) {
S.Diag(SR.getBegin(), diag::ext_template_arg_unnamed_type) << SR;
S.Diag(Tag->getLocation(), diag::note_template_unnamed_type_here);
return true;
@@ -2961,13 +3094,25 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
SourceLocation AddrOpLoc;
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
if (UnOp->getOpcode() == UO_AddrOf) {
+ // Support &__uuidof(class_with_uuid) as a non-type template argument.
+ // Very common in Microsoft COM headers.
+ if (S.getLangOptions().Microsoft &&
+ isa<CXXUuidofExpr>(UnOp->getSubExpr())) {
+ Converted = TemplateArgument(ArgIn);
+ return false;
+ }
+
DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
AddressTaken = true;
AddrOpLoc = UnOp->getOperatorLoc();
}
- } else
+ } else {
+ if (S.getLangOptions().Microsoft && isa<CXXUuidofExpr>(Arg)) {
+ Converted = TemplateArgument(ArgIn);
+ return false;
+ }
DRE = dyn_cast<DeclRefExpr>(Arg);
-
+ }
if (!DRE) {
S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
<< Arg->getSourceRange();
@@ -3266,15 +3411,14 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg,
/// non-type template parameter.
///
/// This routine implements the semantics of C++ [temp.arg.nontype].
-/// It returns true if an error occurred, and false otherwise. \p
+/// If an error occurred, it returns ExprError(); otherwise, it
+/// returns the converted template argument. \p
/// InstantiatedParamType is the type of the non-type template
/// parameter after it has been instantiated.
-///
-/// If no error was detected, Converted receives the converted template argument.
-bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
- QualType InstantiatedParamType, Expr *&Arg,
- TemplateArgument &Converted,
- CheckTemplateArgumentKind CTAK) {
+ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
+ QualType InstantiatedParamType, Expr *Arg,
+ TemplateArgument &Converted,
+ CheckTemplateArgumentKind CTAK) {
SourceLocation StartLoc = Arg->getSourceRange().getBegin();
// If either the parameter has a dependent type or the argument is
@@ -3282,7 +3426,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) {
// FIXME: Produce a cloned, canonical expression?
Converted = TemplateArgument(Arg);
- return false;
+ return Owned(Arg);
}
// C++ [temp.arg.nontype]p5:
@@ -3312,12 +3456,12 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
diag::err_template_arg_not_integral_or_enumeral)
<< ArgType << Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
- return true;
+ return ExprError();
} else if (!Arg->isValueDependent() &&
!Arg->isIntegerConstantExpr(Value, Context, &NonConstantLoc)) {
Diag(NonConstantLoc, diag::err_template_arg_not_ice)
<< ArgType << Arg->getSourceRange();
- return true;
+ return ExprError();
}
// From here on out, all we care about are the unqualified forms
@@ -3340,21 +3484,21 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
<< ArgType << ParamType;
Diag(Param->getLocation(), diag::note_template_param_here);
- return true;
+ return ExprError();
} else if (ParamType->isBooleanType()) {
// This is an integral-to-boolean conversion.
- ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean);
+ Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean).take();
} else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
!ParamType->isEnumeralType()) {
// This is an integral promotion or conversion.
- ImpCastExprToType(Arg, ParamType, CK_IntegralCast);
+ Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralCast).take();
} else {
// We can't perform this conversion.
Diag(Arg->getSourceRange().getBegin(),
diag::err_template_arg_not_convertible)
<< Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
- return true;
+ return ExprError();
}
QualType IntegerType = Context.getCanonicalType(ParamType);
@@ -3404,13 +3548,13 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// The argument is value-dependent. Create a new
// TemplateArgument with the converted expression.
Converted = TemplateArgument(Arg);
- return false;
+ return Owned(Arg);
}
Converted = TemplateArgument(Value,
ParamType->isEnumeralType() ? ParamType
: IntegerType);
- return false;
+ return Owned(Arg);
}
DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction
@@ -3422,7 +3566,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (ArgType->isNullPtrType() &&
(ParamType->isPointerType() || ParamType->isMemberPointerType())) {
Converted = TemplateArgument((NamedDecl *)0);
- return false;
+ return Owned(Arg);
}
// Handle pointer-to-function, reference-to-function, and
@@ -3454,22 +3598,25 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
true,
FoundResult)) {
if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
- return true;
+ return ExprError();
Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
ArgType = Arg->getType();
} else
- return true;
+ return ExprError();
}
- if (!ParamType->isMemberPointerType())
- return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
- ParamType,
- Arg, Converted);
+ if (!ParamType->isMemberPointerType()) {
+ if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
+ ParamType,
+ Arg, Converted))
+ return ExprError();
+ return Owned(Arg);
+ }
if (IsQualificationConversion(ArgType, ParamType.getNonReferenceType(),
false)) {
- ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg));
+ Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)).take();
} else if (!Context.hasSameUnqualifiedType(ArgType,
ParamType.getNonReferenceType())) {
// We can't perform this conversion.
@@ -3477,10 +3624,12 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
diag::err_template_arg_not_convertible)
<< Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
- return true;
+ return ExprError();
}
- return CheckTemplateArgumentPointerToMember(Arg, Converted);
+ if (CheckTemplateArgumentPointerToMember(Arg, Converted))
+ return ExprError();
+ return Owned(Arg);
}
if (ParamType->isPointerType()) {
@@ -3491,9 +3640,11 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
assert(ParamType->getPointeeType()->isIncompleteOrObjectType() &&
"Only object pointers allowed here");
- return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
- ParamType,
- Arg, Converted);
+ if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
+ ParamType,
+ Arg, Converted))
+ return ExprError();
+ return Owned(Arg);
}
if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) {
@@ -3512,17 +3663,19 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
true,
FoundResult)) {
if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
- return true;
+ return ExprError();
Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
ArgType = Arg->getType();
} else
- return true;
+ return ExprError();
}
- return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
- ParamType,
- Arg, Converted);
+ if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
+ ParamType,
+ Arg, Converted))
+ return ExprError();
+ return Owned(Arg);
}
// -- For a non-type template-parameter of type pointer to data
@@ -3532,17 +3685,19 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (Context.hasSameUnqualifiedType(ParamType, ArgType)) {
// Types match exactly: nothing more to do here.
} else if (IsQualificationConversion(ArgType, ParamType, false)) {
- ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg));
+ Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)).take();
} else {
// We can't perform this conversion.
Diag(Arg->getSourceRange().getBegin(),
diag::err_template_arg_not_convertible)
<< Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
- return true;
+ return ExprError();
}
- return CheckTemplateArgumentPointerToMember(Arg, Converted);
+ if (CheckTemplateArgumentPointerToMember(Arg, Converted))
+ return ExprError();
+ return Owned(Arg);
}
/// \brief Check a template argument against its corresponding
@@ -3636,11 +3791,8 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
// the element type on the parameter could be more qualified than the
// element type in the expression we constructed.
if (IsQualificationConversion(((Expr*) RefExpr.get())->getType(),
- ParamType.getUnqualifiedType(), false)) {
- Expr *RefE = RefExpr.takeAs<Expr>();
- ImpCastExprToType(RefE, ParamType.getUnqualifiedType(), CK_NoOp);
- RefExpr = Owned(RefE);
- }
+ ParamType.getUnqualifiedType(), false))
+ RefExpr = ImpCastExprToType(RefExpr.take(), ParamType.getUnqualifiedType(), CK_NoOp);
assert(!RefExpr.isInvalid() &&
Context.hasSameType(((Expr*) RefExpr.get())->getType(),
@@ -3659,12 +3811,9 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
if (T->isFunctionType() || T->isArrayType()) {
// Decay functions and arrays.
- Expr *RefE = (Expr *)RefExpr.get();
- DefaultFunctionArrayConversion(RefE);
- if (RefE != RefExpr.get()) {
- RefExpr.release();
- RefExpr = Owned(RefE);
- }
+ RefExpr = DefaultFunctionArrayConversion(RefExpr.take());
+ if (RefExpr.isInvalid())
+ return ExprError();
return move(RefExpr);
}
@@ -3703,18 +3852,18 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
if (T->isCharType() || T->isWideCharType())
return Owned(new (Context) CharacterLiteral(
Arg.getAsIntegral()->getZExtValue(),
- T->isWideCharType(),
- T,
- Loc));
+ T->isWideCharType(), T, Loc));
if (T->isBooleanType())
return Owned(new (Context) CXXBoolLiteralExpr(
Arg.getAsIntegral()->getBoolValue(),
- T,
- Loc));
+ T, Loc));
+ // If this is an enum type that we're instantiating, we need to use an integer
+ // type the same size as the enumerator. We don't want to build an
+ // IntegerLiteral with enum type.
QualType BT;
if (const EnumType *ET = T->getAs<EnumType>())
- BT = ET->getDecl()->getPromotionType();
+ BT = ET->getDecl()->getIntegerType();
else
BT = T;
@@ -3722,10 +3871,9 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
if (T->isEnumeralType()) {
// FIXME: This is a hack. We need a better way to handle substituted
// non-type template parameters.
- E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast,
- E, 0,
- Context.getTrivialTypeSourceInfo(T, Loc),
- Loc, Loc);
+ E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast, E, 0,
+ Context.getTrivialTypeSourceInfo(T, Loc),
+ Loc, Loc);
}
return Owned(E);
@@ -4245,7 +4393,7 @@ static NamedDecl *getPreviousDecl(NamedDecl *ND) {
return FD->getPreviousDeclaration();
if (TagDecl *TD = dyn_cast<TagDecl>(ND))
return TD->getPreviousDeclaration();
- if (TypedefDecl *TD = dyn_cast<TypedefDecl>(ND))
+ if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(ND))
return TD->getPreviousDeclaration();
if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
return FTD->getPreviousDeclaration();
@@ -4268,6 +4416,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
MultiTemplateParamsArg TemplateParameterLists) {
assert(TUK != TUK_Reference && "References are not specializations");
+ // NOTE: KWLoc is the location of the tag keyword. This will instead
+ // store the location of the outermost template keyword in the declaration.
+ SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0
+ ? TemplateParameterLists.get()[0]->getTemplateLoc() : SourceLocation();
+
// Find the class template we're specializing
TemplateName Name = TemplateD.getAsVal<TemplateName>();
ClassTemplateDecl *ClassTemplate
@@ -4298,10 +4451,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
if (Invalid)
return true;
- unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
- if (TemplateParams)
- --NumMatchedTemplateParamLists;
-
if (TemplateParams && TemplateParams->size() > 0) {
isPartialSpecialization = true;
@@ -4443,10 +4592,15 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Since the only prior class template specialization with these
// arguments was referenced but not declared, or we're only
// referencing this specialization as a friend, reuse that
- // declaration node as our own, updating its source location to
- // reflect our new declaration.
+ // declaration node as our own, updating its source location and
+ // the list of outer template parameters to reflect our new declaration.
Specialization = PrevDecl;
Specialization->setLocation(TemplateNameLoc);
+ if (TemplateParameterLists.size() > 0) {
+ Specialization->setTemplateParameterListsInfo(Context,
+ TemplateParameterLists.size(),
+ (TemplateParameterList**) TemplateParameterLists.release());
+ }
PrevDecl = 0;
CanonType = Context.getTypeDeclType(Specialization);
} else if (isPartialSpecialization) {
@@ -4471,7 +4625,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TemplateNameLoc,
Attr,
TemplateParams,
- AS_none);
+ AS_none,
+ TemplateParameterLists.size() - 1,
+ (TemplateParameterList**) TemplateParameterLists.release());
}
// Create a new class template partial specialization declaration node.
@@ -4482,7 +4638,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
ClassTemplatePartialSpecializationDecl *Partial
= ClassTemplatePartialSpecializationDecl::Create(Context, Kind,
ClassTemplate->getDeclContext(),
- TemplateNameLoc,
+ KWLoc, TemplateNameLoc,
TemplateParams,
ClassTemplate,
Converted.data(),
@@ -4492,9 +4648,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
PrevPartial,
SequenceNumber);
SetNestedNameSpecifier(Partial, SS);
- if (NumMatchedTemplateParamLists > 0 && SS.isSet()) {
+ if (TemplateParameterLists.size() > 1 && SS.isSet()) {
Partial->setTemplateParameterListsInfo(Context,
- NumMatchedTemplateParamLists,
+ TemplateParameterLists.size() - 1,
(TemplateParameterList**) TemplateParameterLists.release());
}
@@ -4545,15 +4701,15 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Specialization
= ClassTemplateSpecializationDecl::Create(Context, Kind,
ClassTemplate->getDeclContext(),
- TemplateNameLoc,
+ KWLoc, TemplateNameLoc,
ClassTemplate,
Converted.data(),
Converted.size(),
PrevDecl);
SetNestedNameSpecifier(Specialization, SS);
- if (NumMatchedTemplateParamLists > 0 && SS.isSet()) {
+ if (TemplateParameterLists.size() > 0) {
Specialization->setTemplateParameterListsInfo(Context,
- NumMatchedTemplateParamLists,
+ TemplateParameterLists.size(),
(TemplateParameterList**) TemplateParameterLists.release());
}
@@ -4623,8 +4779,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TemplateArgs, CanonType);
if (TUK != TUK_Friend) {
Specialization->setTypeAsWritten(WrittenTy);
- if (TemplateParams)
- Specialization->setTemplateKeywordLoc(TemplateParams->getTemplateLoc());
+ Specialization->setTemplateKeywordLoc(TemplateKWLoc);
}
TemplateArgsIn.release();
@@ -4927,7 +5082,7 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
/// this function specialization.
bool
Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
LookupResult &Previous) {
// The set of function template specializations that could match this
// explicit function template specialization.
@@ -4983,7 +5138,17 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
// Ignore access information; it doesn't figure into redeclaration checking.
FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
- Specialization->setLocation(FD->getLocation());
+
+ FunctionTemplateSpecializationInfo *SpecInfo
+ = Specialization->getTemplateSpecializationInfo();
+ assert(SpecInfo && "Function template specialization info missing?");
+ {
+ // Note: do not overwrite location info if previous template
+ // specialization kind was explicit.
+ TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind();
+ if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation)
+ Specialization->setLocation(FD->getLocation());
+ }
// FIXME: Check if the prior specialization has a point of instantiation.
// If so, we have run afoul of .
@@ -5006,10 +5171,6 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
// before the first use of that specialization that would cause an implicit
// instantiation to take place, in every translation unit in which such a
// use occurs; no diagnostic is required.
- FunctionTemplateSpecializationInfo *SpecInfo
- = Specialization->getTemplateSpecializationInfo();
- assert(SpecInfo && "Function template specialization info missing?");
-
bool HasNoEffect = false;
if (!isFriend &&
CheckSpecializationInstantiationRedecl(FD->getLocation(),
@@ -5402,7 +5563,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Specialization
= ClassTemplateSpecializationDecl::Create(Context, Kind,
ClassTemplate->getDeclContext(),
- TemplateNameLoc,
+ KWLoc, TemplateNameLoc,
ClassTemplate,
Converted.data(),
Converted.size(),
@@ -5883,26 +6044,34 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
return true;
}
+ // Create the resulting type.
ElaboratedTypeKeyword Kwd = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
- return ParsedType::make(Context.getDependentNameType(Kwd, NNS, Name));
+ QualType Result = Context.getDependentNameType(Kwd, NNS, Name);
+
+ // Create type-source location information for this type.
+ TypeLocBuilder TLB;
+ DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(Result);
+ TL.setKeywordLoc(TagLoc);
+ TL.setQualifierLoc(SS.getWithLocInContext(Context));
+ TL.setNameLoc(NameLoc);
+ return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
}
TypeResult
Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
const CXXScopeSpec &SS, const IdentifierInfo &II,
SourceLocation IdLoc) {
- NestedNameSpecifier *NNS
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
- if (!NNS)
+ if (SS.isInvalid())
return true;
-
+
if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() &&
!getLangOptions().CPlusPlus0x)
Diag(TypenameLoc, diag::ext_typename_outside_of_template)
<< FixItHint::CreateRemoval(TypenameLoc);
- QualType T = CheckTypenameType(ETK_Typename, NNS, II,
- TypenameLoc, SS.getRange(), IdLoc);
+ NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
+ QualType T = CheckTypenameType(TypenameLoc.isValid()? ETK_Typename : ETK_None,
+ TypenameLoc, QualifierLoc, II, IdLoc);
if (T.isNull())
return true;
@@ -5910,12 +6079,12 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
if (isa<DependentNameType>(T)) {
DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
TL.setKeywordLoc(TypenameLoc);
- TL.setQualifierRange(SS.getRange());
+ TL.setQualifierLoc(QualifierLoc);
TL.setNameLoc(IdLoc);
} else {
ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc());
TL.setKeywordLoc(TypenameLoc);
- TL.setQualifierRange(SS.getRange());
+ TL.setQualifierLoc(QualifierLoc);
cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(IdLoc);
}
@@ -5923,91 +6092,94 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
}
TypeResult
-Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
- const CXXScopeSpec &SS, SourceLocation TemplateLoc,
- ParsedType Ty) {
+Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation TemplateLoc,
+ TemplateTy TemplateIn,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation RAngleLoc) {
if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() &&
!getLangOptions().CPlusPlus0x)
Diag(TypenameLoc, diag::ext_typename_outside_of_template)
- << FixItHint::CreateRemoval(TypenameLoc);
-
- TypeSourceInfo *InnerTSI = 0;
- QualType T = GetTypeFromParser(Ty, &InnerTSI);
-
- assert(isa<TemplateSpecializationType>(T) &&
- "Expected a template specialization type");
-
- if (computeDeclContext(SS, false)) {
- // If we can compute a declaration context, then the "typename"
- // keyword was superfluous. Just build an ElaboratedType to keep
- // track of the nested-name-specifier.
-
- // Push the inner type, preserving its source locations if possible.
+ << FixItHint::CreateRemoval(TypenameLoc);
+
+ // Translate the parser's template argument list in our AST format.
+ TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+ translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+ TemplateName Template = TemplateIn.get();
+ if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
+ // Construct a dependent template specialization type.
+ assert(DTN && "dependent template has non-dependent name?");
+ assert(DTN->getQualifier()
+ == static_cast<NestedNameSpecifier*>(SS.getScopeRep()));
+ QualType T = Context.getDependentTemplateSpecializationType(ETK_Typename,
+ DTN->getQualifier(),
+ DTN->getIdentifier(),
+ TemplateArgs);
+
+ // Create source-location information for this type.
TypeLocBuilder Builder;
- if (InnerTSI)
- Builder.pushFullCopy(InnerTSI->getTypeLoc());
- else
- Builder.push<TemplateSpecializationTypeLoc>(T).initialize(Context,
- TemplateLoc);
-
- /* Note: NNS already embedded in template specialization type T. */
- T = Context.getElaboratedType(ETK_Typename, /*NNS=*/0, T);
- ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T);
- TL.setKeywordLoc(TypenameLoc);
- TL.setQualifierRange(SS.getRange());
-
- TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T);
- return CreateParsedType(T, TSI);
- }
-
- // TODO: it's really silly that we make a template specialization
- // type earlier only to drop it again here.
- const TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T);
- DependentTemplateName *DTN =
- TST->getTemplateName().getAsDependentTemplateName();
- assert(DTN && "dependent template has non-dependent name?");
- assert(DTN->getQualifier()
- == static_cast<NestedNameSpecifier*>(SS.getScopeRep()));
- T = Context.getDependentTemplateSpecializationType(ETK_Typename,
- DTN->getQualifier(),
- DTN->getIdentifier(),
- TST->getNumArgs(),
- TST->getArgs());
- TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
- DependentTemplateSpecializationTypeLoc TL =
- cast<DependentTemplateSpecializationTypeLoc>(TSI->getTypeLoc());
- if (InnerTSI) {
- TemplateSpecializationTypeLoc TSTL =
- cast<TemplateSpecializationTypeLoc>(InnerTSI->getTypeLoc());
- TL.setLAngleLoc(TSTL.getLAngleLoc());
- TL.setRAngleLoc(TSTL.getRAngleLoc());
- for (unsigned I = 0, E = TST->getNumArgs(); I != E; ++I)
- TL.setArgLocInfo(I, TSTL.getArgLocInfo(I));
- } else {
- // FIXME: Poor source-location information here.
- TL.initializeLocal(Context, TemplateLoc);
+ DependentTemplateSpecializationTypeLoc SpecTL
+ = Builder.push<DependentTemplateSpecializationTypeLoc>(T);
+ SpecTL.setLAngleLoc(LAngleLoc);
+ SpecTL.setRAngleLoc(RAngleLoc);
+ SpecTL.setKeywordLoc(TypenameLoc);
+ SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ SpecTL.setNameLoc(TemplateNameLoc);
+ for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+ SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+ return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
}
+
+ QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
+ if (T.isNull())
+ return true;
+
+ // Provide source-location information for the template specialization
+ // type.
+ TypeLocBuilder Builder;
+ TemplateSpecializationTypeLoc SpecTL
+ = Builder.push<TemplateSpecializationTypeLoc>(T);
+
+ // FIXME: No place to set the location of the 'template' keyword!
+ SpecTL.setLAngleLoc(LAngleLoc);
+ SpecTL.setRAngleLoc(RAngleLoc);
+ SpecTL.setTemplateNameLoc(TemplateNameLoc);
+ for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+ SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+
+ T = Context.getElaboratedType(ETK_Typename, SS.getScopeRep(), T);
+ ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T);
TL.setKeywordLoc(TypenameLoc);
- TL.setQualifierRange(SS.getRange());
+ TL.setQualifierLoc(SS.getWithLocInContext(Context));
+
+ TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T);
return CreateParsedType(T, TSI);
}
+
/// \brief Build the type that describes a C++ typename specifier,
/// e.g., "typename T::type".
QualType
-Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS, const IdentifierInfo &II,
- SourceLocation KeywordLoc, SourceRange NNSRange,
+Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
+ SourceLocation KeywordLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ const IdentifierInfo &II,
SourceLocation IILoc) {
CXXScopeSpec SS;
- SS.MakeTrivial(Context, NNS, NNSRange);
+ SS.Adopt(QualifierLoc);
DeclContext *Ctx = computeDeclContext(SS);
if (!Ctx) {
// If the nested-name-specifier is dependent and couldn't be
// resolved to a type, build a typename type.
- assert(NNS->isDependent());
- return Context.getDependentNameType(Keyword, NNS, &II);
+ assert(QualifierLoc.getNestedNameSpecifier()->isDependent());
+ return Context.getDependentNameType(Keyword,
+ QualifierLoc.getNestedNameSpecifier(),
+ &II);
}
// If the nested-name-specifier refers to the current instantiation,
@@ -6032,7 +6204,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
case LookupResult::FoundUnresolvedValue: {
// We found a using declaration that is a value. Most likely, the using
// declaration itself is meant to have the 'typename' keyword.
- SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : NNSRange.getBegin(),
+ SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(),
IILoc);
Diag(IILoc, diag::err_typename_refers_to_using_value_decl)
<< Name << Ctx << FullRange;
@@ -6048,13 +6220,16 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
case LookupResult::NotFoundInCurrentInstantiation:
// Okay, it's a member of an unknown instantiation.
- return Context.getDependentNameType(Keyword, NNS, &II);
+ return Context.getDependentNameType(Keyword,
+ QualifierLoc.getNestedNameSpecifier(),
+ &II);
case LookupResult::Found:
if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {
// We found a type. Build an ElaboratedType, since the
// typename-specifier was just sugar.
- return Context.getElaboratedType(ETK_Typename, NNS,
+ return Context.getElaboratedType(ETK_Typename,
+ QualifierLoc.getNestedNameSpecifier(),
Context.getTypeDeclType(Type));
}
@@ -6077,7 +6252,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
// If we get here, it's because name lookup did not find a
// type. Emit an appropriate diagnostic and return an error.
- SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : NNSRange.getBegin(),
+ SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(),
IILoc);
Diag(IILoc, DiagID) << FullRange << Name << Ctx;
if (Referenced)
@@ -6225,3 +6400,24 @@ Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
Out << ']';
return Out.str();
}
+
+void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag) {
+ if (!FD)
+ return;
+ FD->setLateTemplateParsed(Flag);
+}
+
+bool Sema::IsInsideALocalClassWithinATemplateFunction() {
+ DeclContext *DC = CurContext;
+
+ while (DC) {
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) {
+ const FunctionDecl *FD = RD->isLocalClass();
+ return (FD && FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate);
+ } else if (DC->isTranslationUnit() || DC->isNamespace())
+ return false;
+
+ DC = DC->getParent();
+ }
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
index 139fafb..235af04 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -800,6 +800,32 @@ DeduceTemplateArguments(Sema &S,
return Sema::TDK_Success;
}
+/// \brief Determine whether the parameter has qualifiers that are either
+/// inconsistent with or a superset of the argument's qualifiers.
+static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
+ QualType ArgType) {
+ Qualifiers ParamQs = ParamType.getQualifiers();
+ Qualifiers ArgQs = ArgType.getQualifiers();
+
+ if (ParamQs == ArgQs)
+ return false;
+
+ // Mismatched (but not missing) Objective-C GC attributes.
+ if (ParamQs.getObjCGCAttr() != ArgQs.getObjCGCAttr() &&
+ ParamQs.hasObjCGCAttr())
+ return true;
+
+ // Mismatched (but not missing) address spaces.
+ if (ParamQs.getAddressSpace() != ArgQs.getAddressSpace() &&
+ ParamQs.hasAddressSpace())
+ return true;
+
+ // CVR qualifier superset.
+ return (ParamQs.getCVRQualifiers() != ArgQs.getCVRQualifiers()) &&
+ ((ParamQs.getCVRQualifiers() | ArgQs.getCVRQualifiers())
+ == ParamQs.getCVRQualifiers());
+}
+
/// \brief Deduce the template arguments by comparing the parameter type and
/// the argument type (C++ [temp.deduct.type]).
///
@@ -875,9 +901,12 @@ DeduceTemplateArguments(Sema &S,
Comparison.ParamIsRvalueRef = ParamRef->getAs<RValueReferenceType>();
Comparison.ArgIsRvalueRef = ArgRef->getAs<RValueReferenceType>();
Comparison.Qualifiers = NeitherMoreQualified;
- if (Param.isMoreQualifiedThan(Arg))
+
+ Qualifiers ParamQuals = Param.getQualifiers();
+ Qualifiers ArgQuals = Arg.getQualifiers();
+ if (ParamQuals.isStrictSupersetOf(ArgQuals))
Comparison.Qualifiers = ParamMoreQualified;
- else if (Arg.isMoreQualifiedThan(Param))
+ else if (ArgQuals.isStrictSupersetOf(ParamQuals))
Comparison.Qualifiers = ArgMoreQualified;
RefParamComparisons->push_back(Comparison);
}
@@ -949,7 +978,6 @@ DeduceTemplateArguments(Sema &S,
// If the argument type is an array type, move the qualifiers up to the
// top level, so they can be matched with the qualifiers on the parameter.
- // FIXME: address spaces, ObjC GC qualifiers
if (isa<ArrayType>(Arg)) {
Qualifiers Quals;
Arg = S.Context.getUnqualifiedArrayType(Arg, Quals);
@@ -961,7 +989,8 @@ DeduceTemplateArguments(Sema &S,
// The argument type can not be less qualified than the parameter
// type.
- if (Param.isMoreQualifiedThan(Arg) && !(TDF & TDF_IgnoreQualifiers)) {
+ if (!(TDF & TDF_IgnoreQualifiers) &&
+ hasInconsistentOrSupersetQualifiersOf(Param, Arg)) {
Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
Info.FirstArg = TemplateArgument(Param);
Info.SecondArg = TemplateArgument(Arg);
@@ -972,8 +1001,18 @@ DeduceTemplateArguments(Sema &S,
assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
QualType DeducedType = Arg;
- // local manipulation is okay because it's canonical
- DeducedType.removeLocalCVRQualifiers(Param.getCVRQualifiers());
+ // Remove any qualifiers on the parameter from the deduced type.
+ // We checked the qualifiers for consistency above.
+ Qualifiers DeducedQs = DeducedType.getQualifiers();
+ Qualifiers ParamQs = Param.getQualifiers();
+ DeducedQs.removeCVRQualifiers(ParamQs.getCVRQualifiers());
+ if (ParamQs.hasObjCGCAttr())
+ DeducedQs.removeObjCGCAttr();
+ if (ParamQs.hasAddressSpace())
+ DeducedQs.removeAddressSpace();
+ DeducedType = S.Context.getQualifiedType(DeducedType.getUnqualifiedType(),
+ DeducedQs);
+
if (RecanonicalizeArg)
DeducedType = S.Context.getCanonicalType(DeducedType);
@@ -1006,7 +1045,7 @@ DeduceTemplateArguments(Sema &S,
// Check the cv-qualifiers on the parameter and argument types.
if (!(TDF & TDF_IgnoreQualifiers)) {
if (TDF & TDF_ParamWithReferenceType) {
- if (Param.isMoreQualifiedThan(Arg))
+ if (hasInconsistentOrSupersetQualifiersOf(Param, Arg))
return Sema::TDK_NonDeducedMismatch;
} else if (!IsPossiblyOpaquelyQualifiedType(Param)) {
if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
@@ -1728,11 +1767,24 @@ getTrivialTemplateArgumentLoc(Sema &S,
return TemplateArgumentLoc(TemplateArgument(E), E);
}
- case TemplateArgument::Template:
- return TemplateArgumentLoc(Arg, SourceRange(), Loc);
-
- case TemplateArgument::TemplateExpansion:
- return TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion: {
+ NestedNameSpecifierLocBuilder Builder;
+ TemplateName Template = Arg.getAsTemplate();
+ if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
+ Builder.MakeTrivial(S.Context, DTN->getQualifier(), Loc);
+ else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
+ Builder.MakeTrivial(S.Context, QTN->getQualifier(), Loc);
+
+ if (Arg.getKind() == TemplateArgument::Template)
+ return TemplateArgumentLoc(Arg,
+ Builder.getWithLocInContext(S.Context),
+ Loc);
+
+
+ return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(S.Context),
+ Loc, Loc);
+ }
case TemplateArgument::Expression:
return TemplateArgumentLoc(Arg, Arg.getAsExpr());
@@ -1996,7 +2048,7 @@ static bool isSimpleTemplateIdType(QualType T) {
Sema::TemplateDeductionResult
Sema::SubstituteExplicitTemplateArguments(
FunctionTemplateDecl *FunctionTemplate,
- const TemplateArgumentListInfo &ExplicitTemplateArgs,
+ TemplateArgumentListInfo &ExplicitTemplateArgs,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
llvm::SmallVectorImpl<QualType> &ParamTypes,
QualType *FunctionType,
@@ -2442,8 +2494,8 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
// C++0x [temp.deduct.call]p3:
// If P is a cv-qualified type, the top level cv-qualifiers of P's type
// are ignored for type deduction.
- if (ParamType.getCVRQualifiers())
- ParamType = ParamType.getLocalUnqualifiedType();
+ if (ParamType.hasQualifiers())
+ ParamType = ParamType.getUnqualifiedType();
const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
if (ParamRefType) {
QualType PointeeType = ParamRefType->getPointeeType();
@@ -2499,8 +2551,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
else {
// - If A is a cv-qualified type, the top level cv-qualifiers of A's
// type are ignored for type deduction.
- if (ArgType.getCVRQualifiers())
- ArgType = ArgType.getUnqualifiedType();
+ ArgType = ArgType.getUnqualifiedType();
}
}
@@ -2563,7 +2614,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
/// \returns the result of template argument deduction.
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
FunctionDecl *&Specialization,
TemplateDeductionInfo &Info) {
@@ -2761,7 +2812,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
/// \returns the result of template argument deduction.
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ArgFunctionType,
FunctionDecl *&Specialization,
TemplateDeductionInfo &Info) {
@@ -2832,18 +2883,18 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
QualType P = Context.getCanonicalType(FromType);
QualType A = Context.getCanonicalType(ToType);
- // C++0x [temp.deduct.conv]p3:
+ // C++0x [temp.deduct.conv]p2:
// If P is a reference type, the type referred to by P is used for
// type deduction.
if (const ReferenceType *PRef = P->getAs<ReferenceType>())
P = PRef->getPointeeType();
- // C++0x [temp.deduct.conv]p3:
- // If A is a reference type, the type referred to by A is used
+ // C++0x [temp.deduct.conv]p4:
+ // [...] If A is a reference type, the type referred to by A is used
// for type deduction.
if (const ReferenceType *ARef = A->getAs<ReferenceType>())
- A = ARef->getPointeeType();
- // C++ [temp.deduct.conv]p2:
+ A = ARef->getPointeeType().getUnqualifiedType();
+ // C++ [temp.deduct.conv]p3:
//
// If A is not a reference type:
else {
@@ -2864,9 +2915,10 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
else
P = P.getUnqualifiedType();
- // C++0x [temp.deduct.conv]p3:
+ // C++0x [temp.deduct.conv]p4:
// If A is a cv-qualified type, the top level cv-qualifiers of A's
- // type are ignored for type deduction.
+ // type are ignored for type deduction. If A is a reference type, the type
+ // referred to by A is used for type deduction.
A = A.getUnqualifiedType();
}
@@ -2941,7 +2993,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
/// \returns the result of template argument deduction.
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
FunctionDecl *&Specialization,
TemplateDeductionInfo &Info) {
return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
@@ -2989,11 +3041,14 @@ namespace {
///
/// \param Result if type deduction was successful, this will be set to the
/// deduced type. This may still contain undeduced autos if the type is
-/// dependent.
+/// dependent. This will be set to null if deduction succeeded, but auto
+/// substitution failed; the appropriate diagnostic will already have been
+/// produced in that case.
///
/// \returns true if deduction succeeded, false if it failed.
bool
-Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) {
+Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *Init,
+ TypeSourceInfo *&Result) {
if (Init->isTypeDependent()) {
Result = Type;
return true;
@@ -3004,14 +3059,18 @@ Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) {
LocalInstantiationScope InstScope(*this);
// Build template<class TemplParam> void Func(FuncParam);
- QualType TemplArg = Context.getTemplateTypeParmType(0, 0, false);
- TemplateTypeParmDecl TemplParam(0, Loc, 0, false, TemplArg, false);
- NamedDecl *TemplParamPtr = &TemplParam;
+ TemplateTypeParmDecl *TemplParam =
+ TemplateTypeParmDecl::Create(Context, 0, SourceLocation(), Loc, 0, 0, 0,
+ false, false);
+ QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0);
+ NamedDecl *TemplParamPtr = TemplParam;
FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr,
Loc);
- QualType FuncParam =
+ TypeSourceInfo *FuncParamInfo =
SubstituteAutoTransform(*this, TemplArg).TransformType(Type);
+ assert(FuncParamInfo && "substituting template parameter for 'auto' failed");
+ QualType FuncParam = FuncParamInfo->getType();
// Deduce type of TemplParam in Func(Init)
llvm::SmallVector<DeducedTemplateArgument, 1> Deduced;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
index ae0ac9c..92ba095 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -95,6 +95,12 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
assert(Function->getPrimaryTemplate() && "No function template?");
if (Function->getPrimaryTemplate()->isMemberSpecialization())
break;
+ } else if (FunctionTemplateDecl *FunTmpl
+ = Function->getDescribedFunctionTemplate()) {
+ // Add the "injected" template arguments.
+ std::pair<const TemplateArgument *, unsigned>
+ Injected = FunTmpl->getInjectedTemplateArgs();
+ Result.addOuterTemplateArguments(Injected.first, Injected.second);
}
// If this is a friend declaration and it declares an entity at
@@ -718,8 +724,9 @@ namespace {
/// as an instantiated local.
VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *Declarator,
- IdentifierInfo *Name,
- SourceLocation Loc);
+ SourceLocation StartLoc,
+ SourceLocation NameLoc,
+ IdentifierInfo *Name);
/// \brief Rebuild the Objective-C exception declaration and register the
/// declaration as an instantiated local.
@@ -730,9 +737,12 @@ namespace {
/// elaborated type.
QualType RebuildElaboratedType(SourceLocation KeywordLoc,
ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS, QualType T);
+ NestedNameSpecifierLoc QualifierLoc,
+ QualType T);
- TemplateName TransformTemplateName(TemplateName Name,
+ TemplateName TransformTemplateName(CXXScopeSpec &SS,
+ TemplateName Name,
+ SourceLocation NameLoc,
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = 0);
@@ -747,6 +757,7 @@ namespace {
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL);
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
+ int indexAdjustment,
llvm::Optional<unsigned> NumExpansions);
/// \brief Transforms a template type parameter type by performing
@@ -871,10 +882,11 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
VarDecl *
TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *Declarator,
- IdentifierInfo *Name,
- SourceLocation Loc) {
+ SourceLocation StartLoc,
+ SourceLocation NameLoc,
+ IdentifierInfo *Name) {
VarDecl *Var = inherited::RebuildExceptionDecl(ExceptionDecl, Declarator,
- Name, Loc);
+ StartLoc, NameLoc, Name);
if (Var)
getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
return Var;
@@ -892,7 +904,7 @@ VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
QualType
TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS,
+ NestedNameSpecifierLoc QualifierLoc,
QualType T) {
if (const TagType *TT = T->getAs<TagType>()) {
TagDecl* TD = TT->getDecl();
@@ -918,10 +930,13 @@ TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
return TreeTransform<TemplateInstantiator>::RebuildElaboratedType(KeywordLoc,
Keyword,
- NNS, T);
+ QualifierLoc,
+ T);
}
-TemplateName TemplateInstantiator::TransformTemplateName(TemplateName Name,
+TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS,
+ TemplateName Name,
+ SourceLocation NameLoc,
QualType ObjectType,
NamedDecl *FirstQualifierInScope) {
if (TemplateTemplateParmDecl *TTP
@@ -955,24 +970,31 @@ TemplateName TemplateInstantiator::TransformTemplateName(TemplateName Name,
TemplateName Template = Arg.getAsTemplate();
assert(!Template.isNull() && Template.getAsTemplateDecl() &&
"Wrong kind of template template argument");
+
+ // We don't ever want to substitute for a qualified template name, since
+ // the qualifier is handled separately. So, look through the qualified
+ // template name to its underlying declaration.
+ if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
+ Template = TemplateName(QTN->getTemplateDecl());
+
return Template;
}
}
if (SubstTemplateTemplateParmPackStorage *SubstPack
- = Name.getAsSubstTemplateTemplateParmPack()) {
+ = Name.getAsSubstTemplateTemplateParmPack()) {
if (getSema().ArgumentPackSubstitutionIndex == -1)
return Name;
-
+
const TemplateArgument &ArgPack = SubstPack->getArgumentPack();
assert(getSema().ArgumentPackSubstitutionIndex < (int)ArgPack.pack_size() &&
"Pack substitution index out-of-range");
return ArgPack.pack_begin()[getSema().ArgumentPackSubstitutionIndex]
- .getAsTemplate();
+ .getAsTemplate();
}
- return inherited::TransformTemplateName(Name, ObjectType,
- FirstQualifierInScope);
+ return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
+ FirstQualifierInScope);
}
ExprResult
@@ -1153,8 +1175,9 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
ParmVarDecl *
TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
+ int indexAdjustment,
llvm::Optional<unsigned> NumExpansions) {
- return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs,
+ return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment,
NumExpansions);
}
@@ -1217,12 +1240,17 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
// the template parameter list of a member template inside the
// template we are instantiating). Create a new template type
// parameter with the template "level" reduced by one.
+ TemplateTypeParmDecl *NewTTPDecl = 0;
+ if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
+ NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
+ TransformDecl(TL.getNameLoc(), OldTTPDecl));
+
QualType Result
= getSema().Context.getTemplateTypeParmType(T->getDepth()
- TemplateArgs.getNumLevels(),
T->getIndex(),
T->isParameterPack(),
- T->getName());
+ NewTTPDecl);
TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
return Result;
@@ -1396,6 +1424,7 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
const MultiLevelTemplateArgumentList &TemplateArgs,
+ int indexAdjustment,
llvm::Optional<unsigned> NumExpansions) {
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
TypeSourceInfo *NewDI = 0;
@@ -1432,9 +1461,10 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
}
ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(),
- NewDI, NewDI->getType(),
- OldParm->getIdentifier(),
+ OldParm->getInnerLocStart(),
OldParm->getLocation(),
+ OldParm->getIdentifier(),
+ NewDI->getType(), NewDI,
OldParm->getStorageClass(),
OldParm->getStorageClassAsWritten());
if (!NewParm)
@@ -1465,6 +1495,9 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
// FIXME: OldParm may come from a FunctionProtoType, in which case CurContext
// can be anything, is this right ?
NewParm->setDeclContext(CurContext);
+
+ NewParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
+ OldParm->getFunctionScopeIndex() + indexAdjustment);
return NewParm;
}
@@ -1508,6 +1541,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
}
SourceLocation EllipsisLoc;
+ TypeSourceInfo *BaseTypeLoc;
if (Base->isPackExpansion()) {
// This is a pack expansion. See whether we should expand it now, or
// wait until later.
@@ -1558,13 +1592,18 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
// The resulting base specifier will (still) be a pack expansion.
EllipsisLoc = Base->getEllipsisLoc();
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
+ BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+ TemplateArgs,
+ Base->getSourceRange().getBegin(),
+ DeclarationName());
+ } else {
+ BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+ TemplateArgs,
+ Base->getSourceRange().getBegin(),
+ DeclarationName());
}
- Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
- TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
- TemplateArgs,
- Base->getSourceRange().getBegin(),
- DeclarationName());
if (!BaseTypeLoc) {
Invalid = true;
continue;
@@ -1622,9 +1661,18 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
CXXRecordDecl *PatternDef
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
- if (!PatternDef) {
- if (!Complain) {
+ if (!PatternDef || PatternDef->isBeingDefined()) {
+ if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) {
// Say nothing
+ } else if (PatternDef) {
+ assert(PatternDef->isBeingDefined());
+ Diag(PointOfInstantiation,
+ diag::err_template_instantiate_within_definition)
+ << (TSK != TSK_ImplicitInstantiation)
+ << Context.getTypeDeclType(Instantiation);
+ // Not much point in noting the template declaration here, since
+ // we're lexically inside it.
+ Instantiation->setInvalidDecl();
} else if (Pattern == Instantiation->getInstantiatedFromMemberClass()) {
Diag(PointOfInstantiation,
diag::err_implicit_instantiate_member_undefined)
@@ -2130,16 +2178,6 @@ bool Sema::SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall,
return Instantiator.TransformExprs(Exprs, NumExprs, IsCall, Outputs);
}
-/// \brief Do template substitution on a nested-name-specifier.
-NestedNameSpecifier *
-Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
- SourceRange Range,
- const MultiLevelTemplateArgumentList &TemplateArgs) {
- TemplateInstantiator Instantiator(*this, TemplateArgs, Range.getBegin(),
- DeclarationName());
- return Instantiator.TransformNestedNameSpecifier(NNS, Range);
-}
-
NestedNameSpecifierLoc
Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
const MultiLevelTemplateArgumentList &TemplateArgs) {
@@ -2161,11 +2199,14 @@ Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
}
TemplateName
-Sema::SubstTemplateName(TemplateName Name, SourceLocation Loc,
+Sema::SubstTemplateName(NestedNameSpecifierLoc QualifierLoc,
+ TemplateName Name, SourceLocation Loc,
const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
DeclarationName());
- return Instantiator.TransformTemplateName(Name);
+ CXXScopeSpec SS;
+ SS.Adopt(QualifierLoc);
+ return Instantiator.TransformTemplateName(SS, Name, Loc);
}
bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 3a40b6f..6e11ef5 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -128,7 +128,8 @@ TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
return Inst;
}
-Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
+Decl *TemplateDeclInstantiator::VisitTypedefNameDecl(TypedefNameDecl *D,
+ bool IsTypeAlias) {
bool Invalid = false;
TypeSourceInfo *DI = D->getTypeSourceInfo();
if (DI->getType()->isDependentType() ||
@@ -144,9 +145,13 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
}
// Create the new typedef
- TypedefDecl *Typedef
- = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocation(),
- D->getIdentifier(), DI);
+ TypedefNameDecl *Typedef;
+ if (IsTypeAlias)
+ Typedef = TypeAliasDecl::Create(SemaRef.Context, Owner, D->getLocStart(),
+ D->getLocation(), D->getIdentifier(), DI);
+ else
+ Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocStart(),
+ D->getLocation(), D->getIdentifier(), DI);
if (Invalid)
Typedef->setInvalidDecl();
@@ -154,17 +159,20 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
// tag decl, re-establish that relationship for the new typedef.
if (const TagType *oldTagType = D->getUnderlyingType()->getAs<TagType>()) {
TagDecl *oldTag = oldTagType->getDecl();
- if (oldTag->getTypedefForAnonDecl() == D) {
+ if (oldTag->getTypedefNameForAnonDecl() == D) {
TagDecl *newTag = DI->getType()->castAs<TagType>()->getDecl();
- assert(!newTag->getIdentifier() && !newTag->getTypedefForAnonDecl());
- newTag->setTypedefForAnonDecl(Typedef);
+ assert(!newTag->getIdentifier() && !newTag->getTypedefNameForAnonDecl());
+ newTag->setTypedefNameForAnonDecl(Typedef);
}
}
- if (TypedefDecl *Prev = D->getPreviousDeclaration()) {
+ if (TypedefNameDecl *Prev = D->getPreviousDeclaration()) {
NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev,
TemplateArgs);
- Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev));
+ if (!InstPrev)
+ return 0;
+
+ Typedef->setPreviousDeclaration(cast<TypedefNameDecl>(InstPrev));
}
SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef);
@@ -175,6 +183,14 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
return Typedef;
}
+Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
+ return VisitTypedefNameDecl(D, /*IsTypeAlias=*/false);
+}
+
+Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) {
+ return VisitTypedefNameDecl(D, /*IsTypeAlias=*/true);
+}
+
/// \brief Instantiate an initializer, breaking it into separate
/// initialization arguments.
///
@@ -261,12 +277,14 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
// Build the instantiated declaration
VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner,
+ D->getInnerLocStart(),
D->getLocation(), D->getIdentifier(),
DI->getType(), DI,
D->getStorageClass(),
D->getStorageClassAsWritten());
Var->setThreadSpecified(D->isThreadSpecified());
Var->setCXXDirectInitializer(D->hasCXXDirectInitializer());
+ Var->setCXXForRangeDecl(D->isCXXForRangeDecl());
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Var))
@@ -280,8 +298,10 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
Var->setAccess(D->getAccess());
- if (!D->isStaticDataMember())
+ if (!D->isStaticDataMember()) {
Var->setUsed(D->isUsed(false));
+ Var->setReferenced(D->isReferenced());
+ }
// FIXME: In theory, we could have a previous declaration for variables that
// are not static data members.
@@ -346,7 +366,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
}
SemaRef.PopExpressionEvaluationContext();
- } else if (!Var->isStaticDataMember() || Var->isOutOfLine())
+ } else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) &&
+ !Var->isCXXForRangeDecl())
SemaRef.ActOnUninitializedDecl(Var, false);
// Diagnose unused local variables.
@@ -448,9 +469,14 @@ Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
int i = 0;
for (IndirectFieldDecl::chain_iterator PI =
D->chain_begin(), PE = D->chain_end();
- PI != PE; ++PI)
- NamedChain[i++] = (SemaRef.FindInstantiatedDecl(D->getLocation(),
- *PI, TemplateArgs));
+ PI != PE; ++PI) {
+ NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), *PI,
+ TemplateArgs);
+ if (!Next)
+ return 0;
+
+ NamedChain[i++] = Next;
+ }
QualType T = cast<FieldDecl>(NamedChain[i-1])->getType();
IndirectFieldDecl* IndirectField
@@ -469,10 +495,18 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
// Handle friend type expressions by simply substituting template
// parameters into the pattern type and checking the result.
if (TypeSourceInfo *Ty = D->getFriendType()) {
- TypeSourceInfo *InstTy =
- SemaRef.SubstType(Ty, TemplateArgs,
- D->getLocation(), DeclarationName());
- if (!InstTy)
+ TypeSourceInfo *InstTy;
+ // If this is an unsupported friend, don't bother substituting template
+ // arguments into it. The actual type referred to won't be used by any
+ // parts of Clang, and may not be valid for instantiating. Just use the
+ // same info for the instantiated friend.
+ if (D->isUnsupportedFriend()) {
+ InstTy = Ty;
+ } else {
+ InstTy = SemaRef.SubstType(Ty, TemplateArgs,
+ D->getLocation(), DeclarationName());
+ }
+ if (!InstTy)
return 0;
FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getFriendLoc(), InstTy);
@@ -519,13 +553,13 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
D->getMessage();
return SemaRef.ActOnStaticAssertDeclaration(D->getLocation(),
InstantiatedAssertExpr.get(),
- Message.get());
+ Message.get(),
+ D->getRParenLoc());
}
Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
- EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner,
+ EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocStart(),
D->getLocation(), D->getIdentifier(),
- D->getTagKeywordLoc(),
/*PrevDecl=*/0, D->isScoped(),
D->isScopedUsingClassTag(), D->isFixed());
if (D->isFixed()) {
@@ -750,8 +784,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
CXXRecordDecl *RecordInst
= CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), DC,
- Pattern->getLocation(), Pattern->getIdentifier(),
- Pattern->getTagKeywordLoc(), PrevDecl,
+ Pattern->getLocStart(), Pattern->getLocation(),
+ Pattern->getIdentifier(), PrevDecl,
/*DelayTypeCreation=*/true);
if (QualifierLoc)
@@ -892,8 +926,8 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
CXXRecordDecl *Record
= CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner,
- D->getLocation(), D->getIdentifier(),
- D->getTagKeywordLoc(), PrevDecl);
+ D->getLocStart(), D->getLocation(),
+ D->getIdentifier(), PrevDecl);
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Record))
@@ -991,8 +1025,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
}
FunctionDecl *Function =
- FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(),
- D->getDeclName(), T, TInfo,
+ FunctionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
+ D->getLocation(), D->getDeclName(), T, TInfo,
D->getStorageClass(), D->getStorageClassAsWritten(),
D->isInlineSpecified(), D->hasWrittenPrototype());
@@ -1288,30 +1322,33 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
CXXMethodDecl *Method = 0;
+ SourceLocation StartLoc = D->getInnerLocStart();
DeclarationNameInfo NameInfo
= SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
Method = CXXConstructorDecl::Create(SemaRef.Context, Record,
- NameInfo, T, TInfo,
+ StartLoc, NameInfo, T, TInfo,
Constructor->isExplicit(),
Constructor->isInlineSpecified(),
false);
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
- NameInfo, T, TInfo,
+ StartLoc, NameInfo, T, TInfo,
Destructor->isInlineSpecified(),
false);
} else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
Method = CXXConversionDecl::Create(SemaRef.Context, Record,
- NameInfo, T, TInfo,
+ StartLoc, NameInfo, T, TInfo,
Conversion->isInlineSpecified(),
- Conversion->isExplicit());
+ Conversion->isExplicit(),
+ Conversion->getLocEnd());
} else {
Method = CXXMethodDecl::Create(SemaRef.Context, Record,
- NameInfo, T, TInfo,
+ StartLoc, NameInfo, T, TInfo,
D->isStatic(),
D->getStorageClassAsWritten(),
- D->isInlineSpecified());
+ D->isInlineSpecified(),
+ D->getLocEnd());
}
if (QualifierLoc)
@@ -1431,23 +1468,24 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
}
ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
- return SemaRef.SubstParmVarDecl(D, TemplateArgs, llvm::Optional<unsigned>());
+ return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0,
+ llvm::Optional<unsigned>());
}
Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
TemplateTypeParmDecl *D) {
// TODO: don't always clone when decls are refcounted.
- const Type* T = D->getTypeForDecl();
- assert(T->isTemplateTypeParmType());
- const TemplateTypeParmType *TTPT = T->getAs<TemplateTypeParmType>();
+ assert(D->getTypeForDecl()->isTemplateTypeParmType());
TemplateTypeParmDecl *Inst =
- TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
- TTPT->getDepth() - TemplateArgs.getNumLevels(),
- TTPT->getIndex(), D->getIdentifier(),
+ TemplateTypeParmDecl::Create(SemaRef.Context, Owner,
+ D->getLocStart(), D->getLocation(),
+ D->getDepth() - TemplateArgs.getNumLevels(),
+ D->getIndex(), D->getIdentifier(),
D->wasDeclaredWithTypename(),
D->isParameterPack());
-
+ Inst->setAccess(AS_public);
+
if (D->hasDefaultArgument())
Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false);
@@ -1567,7 +1605,6 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
return 0;
// Check that this type is acceptable for a non-type template parameter.
- bool Invalid = false;
T = SemaRef.CheckNonTypeTemplateParameterType(DI->getType(),
D->getLocation());
if (T.isNull()) {
@@ -1579,7 +1616,8 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
NonTypeTemplateParmDecl *Param;
if (IsExpandedParameterPack)
Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner,
- D->getLocation(),
+ D->getInnerLocStart(),
+ D->getLocation(),
D->getDepth() - TemplateArgs.getNumLevels(),
D->getPosition(),
D->getIdentifier(), T,
@@ -1589,12 +1627,14 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
ExpandedParameterPackTypesAsWritten.data());
else
Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner,
+ D->getInnerLocStart(),
D->getLocation(),
D->getDepth() - TemplateArgs.getNumLevels(),
D->getPosition(),
D->getIdentifier(), T,
D->isParameterPack(), DI);
+ Param->setAccess(AS_public);
if (Invalid)
Param->setInvalidDecl();
@@ -1628,6 +1668,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
D->getPosition(), D->isParameterPack(),
D->getIdentifier(), InstParams);
Param->setDefaultArgument(D->getDefaultArgument(), false);
+ Param->setAccess(AS_public);
// Introduce this template parameter's instantiation into the instantiation
// scope.
@@ -1719,9 +1760,12 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
I != E; ++I) {
UsingShadowDecl *Shadow = *I;
NamedDecl *InstTarget =
- cast<NamedDecl>(SemaRef.FindInstantiatedDecl(Shadow->getLocation(),
- Shadow->getTargetDecl(),
- TemplateArgs));
+ cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl(
+ Shadow->getLocation(),
+ Shadow->getTargetDecl(),
+ TemplateArgs));
+ if (!InstTarget)
+ return 0;
if (CheckRedeclaration &&
SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev))
@@ -1936,7 +1980,8 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
= ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context,
PartialSpec->getTagKind(),
Owner,
- PartialSpec->getLocation(),
+ PartialSpec->getLocStart(),
+ PartialSpec->getLocation(),
InstParams,
ClassTemplate,
Converted.data(),
@@ -2063,8 +2108,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
const FunctionProtoType *Proto = Tmpl->getType()->getAs<FunctionProtoType>();
assert(Proto && "Function template without prototype?");
- if (Proto->hasExceptionSpec() || Proto->hasAnyExceptionSpec() ||
- Proto->getNoReturnAttr()) {
+ if (Proto->hasExceptionSpec() || Proto->getNoReturnAttr()) {
// The function has an exception specification or a "noreturn"
// attribute. Substitute into each of the exception types.
llvm::SmallVector<QualType, 4> Exceptions;
@@ -2078,7 +2122,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
Unexpanded);
assert(!Unexpanded.empty() &&
"Pack expansion without parameter packs?");
-
+
bool Expand = false;
bool RetainExpansion = false;
llvm::Optional<unsigned> NumExpansions
@@ -2092,7 +2136,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
RetainExpansion,
NumExpansions))
break;
-
+
if (!Expand) {
// We can't expand this pack expansion into separate arguments yet;
// just substitute into the pattern and create a new pack expansion
@@ -2108,7 +2152,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
Exceptions.push_back(T);
continue;
}
-
+
// Substitute into the pack expansion pattern for each template
bool Invalid = false;
for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
@@ -2121,13 +2165,13 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
Invalid = true;
break;
}
-
+
Exceptions.push_back(T);
}
-
+
if (Invalid)
break;
-
+
continue;
}
@@ -2140,14 +2184,20 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
Exceptions.push_back(T);
}
+ Expr *NoexceptExpr = 0;
+ if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
+ ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);
+ if (E.isUsable())
+ NoexceptExpr = E.take();
+ }
// Rebuild the function type
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
- EPI.HasExceptionSpec = Proto->hasExceptionSpec();
- EPI.HasAnyExceptionSpec = Proto->hasAnyExceptionSpec();
+ EPI.ExceptionSpecType = Proto->getExceptionSpecType();
EPI.NumExceptions = Exceptions.size();
EPI.Exceptions = Exceptions.data();
+ EPI.NoexceptExpr = NoexceptExpr;
EPI.ExtInfo = Proto->getExtInfo();
const FunctionProtoType *NewProto
@@ -2218,6 +2268,21 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (PatternDecl)
Pattern = PatternDecl->getBody(PatternDecl);
+ // Postpone late parsed template instantiations.
+ if (PatternDecl->isLateTemplateParsed() && !LateTemplateParser) {
+ PendingInstantiations.push_back(
+ std::make_pair(Function, PointOfInstantiation));
+ return;
+ }
+
+ // Call the LateTemplateParser callback if there a need to late parse
+ // a templated function definition.
+ if (!Pattern && PatternDecl && PatternDecl->isLateTemplateParsed() &&
+ LateTemplateParser) {
+ LateTemplateParser(OpaqueParser, PatternDecl);
+ Pattern = PatternDecl->getBody(PatternDecl);
+ }
+
if (!Pattern) {
if (DefinitionRequired) {
if (Function->getPrimaryTemplate())
@@ -2573,10 +2638,15 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
New->getParent(),
EllipsisLoc);
} else if (Init->isMemberInitializer()) {
- FieldDecl *Member = cast<FieldDecl>(FindInstantiatedDecl(
+ FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl(
Init->getMemberLocation(),
Init->getMember(),
TemplateArgs));
+ if (!Member) {
+ AnyErrors = true;
+ New->setInvalidDecl();
+ continue;
+ }
NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(),
NewArgs.size(),
@@ -2585,10 +2655,16 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
Init->getRParenLoc());
} else if (Init->isIndirectMemberInitializer()) {
IndirectFieldDecl *IndirectMember =
- cast<IndirectFieldDecl>(FindInstantiatedDecl(
+ cast_or_null<IndirectFieldDecl>(FindInstantiatedDecl(
Init->getMemberLocation(),
Init->getIndirectMember(), TemplateArgs));
+ if (!IndirectMember) {
+ AnyErrors = true;
+ New->setInvalidDecl();
+ continue;
+ }
+
NewInit = BuildMemberInitializer(IndirectMember, (Expr **)NewArgs.data(),
NewArgs.size(),
Init->getSourceLocation(),
@@ -2917,7 +2993,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
// FIXME: Can we use the CurrentInstantiationScope to avoid this
// extra instantiation in the common case?
- T = SubstType(T, TemplateArgs, SourceLocation(), DeclarationName());
+ T = SubstType(T, TemplateArgs, Loc, DeclarationName());
assert(!T.isNull() && "Instantiation of injected-class-name cannot fail.");
if (!T->isDependentType()) {
@@ -2974,11 +3050,14 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
// If our context used to be dependent, we may need to instantiate
// it before performing lookup into that context.
+ bool IsBeingInstantiated = false;
if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) {
if (!Spec->isDependentContext()) {
QualType T = Context.getTypeDeclType(Spec);
const RecordType *Tag = T->getAs<RecordType>();
assert(Tag && "type of non-dependent record is not a RecordType");
+ if (Tag->isBeingDefined())
+ IsBeingInstantiated = true;
if (!Tag->isBeingDefined() &&
RequireCompleteType(Loc, T, diag::err_incomplete_type))
return 0;
@@ -3005,11 +3084,29 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
ParentDC->decls_end());
}
- // UsingShadowDecls can instantiate to nothing because of using hiding.
- assert((Result || isa<UsingShadowDecl>(D) || D->isInvalidDecl() ||
- cast<Decl>(ParentDC)->isInvalidDecl())
- && "Unable to find instantiation of declaration!");
-
+ if (!Result) {
+ if (isa<UsingShadowDecl>(D)) {
+ // UsingShadowDecls can instantiate to nothing because of using hiding.
+ } else if (Diags.hasErrorOccurred()) {
+ // We've already complained about something, so most likely this
+ // declaration failed to instantiate. There's no point in complaining
+ // further, since this is normal in invalid code.
+ } else if (IsBeingInstantiated) {
+ // The class in which this member exists is currently being
+ // instantiated, and we haven't gotten around to instantiating this
+ // member yet. This can happen when the code uses forward declarations
+ // of member classes, and introduces ordering dependencies via
+ // template instantiation.
+ Diag(Loc, diag::err_member_not_yet_instantiated)
+ << D->getDeclName()
+ << Context.getTypeDeclType(cast<CXXRecordDecl>(ParentDC));
+ Diag(D->getLocation(), diag::note_non_instantiated_member_here);
+ } else {
+ // We should have found something, but didn't.
+ llvm_unreachable("Unable to find instantiation of declaration!");
+ }
+ }
+
D = Result;
}
@@ -3018,7 +3115,10 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
/// \brief Performs template instantiation for all implicit template
/// instantiations we have seen until this point.
-void Sema::PerformPendingInstantiations(bool LocalOnly) {
+///
+/// \returns true if anything was instantiated.
+bool Sema::PerformPendingInstantiations(bool LocalOnly) {
+ bool InstantiatedAnything = false;
while (!PendingLocalImplicitInstantiations.empty() ||
(!LocalOnly && !PendingInstantiations.empty())) {
PendingImplicitInstantiation Inst;
@@ -3039,6 +3139,7 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
TSK_ExplicitInstantiationDefinition;
InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true,
DefinitionRequired);
+ InstantiatedAnything = true;
continue;
}
@@ -3075,7 +3176,10 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
TSK_ExplicitInstantiationDefinition;
InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true,
DefinitionRequired);
+ InstantiatedAnything = true;
}
+
+ return InstantiatedAnything;
}
void Sema::PerformDependentDiagnostics(const DeclContext *Pattern,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
index 0da801c..096d353 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -167,7 +167,7 @@ DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc,
IdentifierInfo *Name = 0;
if (const TemplateTypeParmType *TTP
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
- Name = TTP->getName();
+ Name = TTP->getIdentifier();
else
Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier();
@@ -483,7 +483,7 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
Depth = TTP->getDepth();
Index = TTP->getIndex();
- Name = TTP->getName();
+ Name = TTP->getIdentifier();
} else {
NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
if (isa<ParmVarDecl>(ND))
@@ -649,6 +649,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_struct:
case TST_class:
case TST_auto:
+ case TST_unknown_anytype:
case TST_error:
break;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
index ba80076..00ac1d6 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
@@ -13,6 +13,7 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
+#include "clang/Basic/OpenCL.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
@@ -22,6 +23,7 @@
#include "clang/AST/Expr.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/ErrorHandling.h"
@@ -70,6 +72,40 @@ static bool isOmittedBlockReturnType(const Declarator &D) {
return false;
}
+/// diagnoseBadTypeAttribute - Diagnoses a type attribute which
+/// doesn't apply to the given type.
+static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
+ QualType type) {
+ bool useInstantiationLoc = false;
+
+ unsigned diagID = 0;
+ switch (attr.getKind()) {
+ case AttributeList::AT_objc_gc:
+ diagID = diag::warn_pointer_attribute_wrong_type;
+ useInstantiationLoc = true;
+ break;
+
+ default:
+ // Assume everything else was a function attribute.
+ diagID = diag::warn_function_attribute_wrong_type;
+ break;
+ }
+
+ SourceLocation loc = attr.getLoc();
+ llvm::StringRef name = attr.getName()->getName();
+
+ // The GC attributes are usually written with macros; special-case them.
+ if (useInstantiationLoc && loc.isMacroID() && attr.getParameterName()) {
+ if (attr.getParameterName()->isStr("strong")) {
+ if (S.findMacroSpelling(loc, "__strong")) name = "__strong";
+ } else if (attr.getParameterName()->isStr("weak")) {
+ if (S.findMacroSpelling(loc, "__weak")) name = "__weak";
+ }
+ }
+
+ S.Diag(loc, diagID) << name << type;
+}
+
// objc_gc applies to Objective-C pointers or, otherwise, to the
// smallest available pointer type (i.e. 'void*' in 'void**').
#define OBJC_POINTER_TYPE_ATTRS_CASELIST \
@@ -83,7 +119,8 @@ static bool isOmittedBlockReturnType(const Declarator &D) {
case AttributeList::AT_stdcall: \
case AttributeList::AT_thiscall: \
case AttributeList::AT_pascal: \
- case AttributeList::AT_regparm
+ case AttributeList::AT_regparm: \
+ case AttributeList::AT_pcs \
namespace {
/// An object which stores processing state for the entire
@@ -102,6 +139,9 @@ namespace {
/// Whether there are non-trivial modifications to the decl spec.
bool trivial;
+ /// Whether we saved the attributes in the decl spec.
+ bool hasSavedAttrs;
+
/// The original set of attributes on the DeclSpec.
llvm::SmallVector<AttributeList*, 2> savedAttrs;
@@ -113,7 +153,7 @@ namespace {
TypeProcessingState(Sema &sema, Declarator &declarator)
: sema(sema), declarator(declarator),
chunkIndex(declarator.getNumTypeObjects()),
- trivial(true) {}
+ trivial(true), hasSavedAttrs(false) {}
Sema &getSema() const {
return sema;
@@ -142,13 +182,14 @@ namespace {
/// Save the current set of attributes on the DeclSpec.
void saveDeclSpecAttrs() {
// Don't try to save them multiple times.
- if (!savedAttrs.empty()) return;
+ if (hasSavedAttrs) return;
DeclSpec &spec = getMutableDeclSpec();
for (AttributeList *attr = spec.getAttributes().getList(); attr;
attr = attr->getNext())
savedAttrs.push_back(attr);
trivial &= savedAttrs.empty();
+ hasSavedAttrs = true;
}
/// Record that we had nowhere to put the given type attribute.
@@ -162,11 +203,8 @@ namespace {
void diagnoseIgnoredTypeAttrs(QualType type) const {
for (llvm::SmallVectorImpl<AttributeList*>::const_iterator
i = ignoredTypeAttrs.begin(), e = ignoredTypeAttrs.end();
- i != e; ++i) {
- AttributeList &attr = **i;
- getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type)
- << attr.getName() << type;
- }
+ i != e; ++i)
+ diagnoseBadTypeAttribute(getSema(), **i, type);
}
~TypeProcessingState() {
@@ -181,7 +219,13 @@ namespace {
}
void restoreDeclSpecAttrs() {
- assert(!savedAttrs.empty());
+ assert(hasSavedAttrs);
+
+ if (savedAttrs.empty()) {
+ getMutableDeclSpec().getAttributes().set(0);
+ return;
+ }
+
getMutableDeclSpec().getAttributes().set(savedAttrs[0]);
for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i)
savedAttrs[i]->setNext(savedAttrs[i+1]);
@@ -287,9 +331,8 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
}
}
error:
-
- state.getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type)
- << attr.getName() << type;
+
+ diagnoseBadTypeAttribute(state.getSema(), attr, type);
}
/// Distribute an objc_gc type attribute that was written on the
@@ -328,8 +371,15 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
// That might actually be the decl spec if we weren't blocked by
// anything in the declarator.
if (considerDeclSpec) {
- if (handleObjCPointerTypeAttr(state, attr, declSpecType))
+ if (handleObjCPointerTypeAttr(state, attr, declSpecType)) {
+ // Splice the attribute into the decl spec. Prevents the
+ // attribute from being applied multiple times and gives
+ // the source-location-filler something to work with.
+ state.saveDeclSpecAttrs();
+ moveAttrFromListToList(attr, declarator.getAttrListRef(),
+ declarator.getMutableDeclSpec().getAttributes().getListRef());
return;
+ }
}
// Otherwise, if we found an appropriate chunk, splice the attribute
@@ -374,8 +424,7 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state,
}
}
- state.getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type)
- << attr.getName() << type;
+ diagnoseBadTypeAttribute(state.getSema(), attr, type);
}
/// Try to distribute a function type attribute to the innermost
@@ -505,13 +554,12 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
// ...and *prepend* it to the declarator.
declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction(
- ParsedAttributes(),
/*proto*/ true,
/*variadic*/ false, SourceLocation(),
/*args*/ 0, 0,
/*type quals*/ 0,
/*ref-qualifier*/true, SourceLocation(),
- /*EH*/ false, SourceLocation(), false, 0, 0, 0,
+ /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0,
/*parens*/ loc, loc,
declarator));
@@ -698,7 +746,7 @@ static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) {
}
// If the type is deprecated or unavailable, diagnose it.
- S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeLoc());
+ S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc());
assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!");
@@ -706,12 +754,11 @@ static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) {
// TypeQuals handled by caller.
Result = Context.getTypeDeclType(D);
- // In C++, make an ElaboratedType.
- if (S.getLangOptions().CPlusPlus) {
- ElaboratedTypeKeyword Keyword
- = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType());
- Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result);
- }
+ // In both C and C++, make an ElaboratedType.
+ ElaboratedTypeKeyword Keyword
+ = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType());
+ Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result);
+
if (D->isInvalidDecl())
declarator.setInvalidType(true);
break;
@@ -795,6 +842,10 @@ static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) {
break;
}
+ case DeclSpec::TST_unknown_anytype:
+ Result = Context.UnknownAnyTy;
+ break;
+
case DeclSpec::TST_error:
Result = Context.IntTy;
declarator.setInvalidType(true);
@@ -1108,8 +1159,13 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
}
// Do lvalue-to-rvalue conversions on the array size expression.
- if (ArraySize && !ArraySize->isRValue())
- DefaultLvalueConversion(ArraySize);
+ if (ArraySize && !ArraySize->isRValue()) {
+ ExprResult Result = DefaultLvalueConversion(ArraySize);
+ if (Result.isInvalid())
+ return QualType();
+
+ ArraySize = Result.take();
+ }
// C99 6.7.5.2p1: The size expression shall have integer type.
// TODO: in theory, if we were insane, we could allow contextual
@@ -1464,19 +1520,27 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
TypeProcessingState state(*this, D);
+ // In C++0x, deallocation functions (normal and array operator delete)
+ // are implicitly noexcept.
+ bool ImplicitlyNoexcept = false;
+
switch (D.getName().getKind()) {
- case UnqualifiedId::IK_Identifier:
case UnqualifiedId::IK_OperatorFunctionId:
+ if (getLangOptions().CPlusPlus0x) {
+ OverloadedOperatorKind OO = D.getName().OperatorFunctionId.Operator;
+ if (OO == OO_Delete || OO == OO_Array_Delete)
+ ImplicitlyNoexcept = true;
+ }
+ // Intentional fall-through.
+ case UnqualifiedId::IK_Identifier:
case UnqualifiedId::IK_LiteralOperatorId:
case UnqualifiedId::IK_TemplateId:
T = ConvertDeclSpecToType(*this, state);
if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
TagDecl* Owned = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
- // Owned is embedded if it was defined here, or if it is the
- // very first (i.e., canonical) declaration of this tag type.
- Owned->setEmbeddedInDeclarator(Owned->isDefinition() ||
- Owned->isCanonicalDecl());
+ // Owned declaration is embedded in declarator.
+ Owned->setEmbeddedInDeclarator(true);
if (OwnedDecl) *OwnedDecl = Owned;
}
break;
@@ -1512,6 +1576,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
case Declarator::KNRTypeListContext:
assert(0 && "K&R type lists aren't allowed in C++");
break;
+ case Declarator::ObjCPrototypeContext:
case Declarator::PrototypeContext:
Error = 0; // Function prototype
break;
@@ -1535,9 +1600,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
case Declarator::TemplateTypeArgContext:
Error = 7; // Template type argument
break;
+ case Declarator::AliasDeclContext:
+ Error = 9; // Type alias
+ break;
case Declarator::TypeNameContext:
if (!AutoAllowedInTypeName)
- Error = 10; // Generic
+ Error = 11; // Generic
break;
case Declarator::FileContext:
case Declarator::BlockContext:
@@ -1551,7 +1619,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// In Objective-C it is an error to use 'auto' on a function declarator.
if (D.isFunctionDeclarator())
- Error = 9;
+ Error = 10;
// C++0x [dcl.spec.auto]p2: 'auto' is always fine if the declarator
// contains a trailing return type. That is only legal at the outermost
@@ -1588,6 +1656,11 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (D.getIdentifier())
Name = D.getIdentifier();
+ // Does this declaration declare a typedef-name?
+ bool IsTypedefName =
+ D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef ||
+ D.getContext() == Declarator::AliasDeclContext;
+
// Walk the DeclTypeInfo, building the recursive type as we go.
// DeclTypeInfos are ordered from the identifier out, which is
// opposite of what we want :).
@@ -1660,8 +1733,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
ASM = ArrayType::Static;
else
ASM = ArrayType::Normal;
- if (ASM == ArrayType::Star &&
- D.getContext() != Declarator::PrototypeContext) {
+ if (ASM == ArrayType::Star && !D.isPrototypeContext()) {
// FIXME: This check isn't quite right: it allows star in prototypes
// for function definitions, and disallows some edge cases detailed
// in http://gcc.gnu.org/ml/gcc-patches/2009-02/msg00133.html
@@ -1728,7 +1800,8 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// cv-qualifiers on return types are pointless except when the type is a
// class type in C++.
- if (T->isPointerType() && T.getCVRQualifiers() &&
+ if (isa<PointerType>(T) && T.getLocalCVRQualifiers() &&
+ (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId) &&
(!getLangOptions().CPlusPlus || !T->isDependentType())) {
assert(chunkIndex + 1 < e && "No DeclaratorChunk for the return type?");
DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
@@ -1764,9 +1837,9 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// Exception specs are not allowed in typedefs. Complain, but add it
// anyway.
- if (FTI.hasExceptionSpec &&
- D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
- Diag(FTI.getThrowLoc(), diag::err_exception_spec_in_typedef);
+ if (IsTypedefName && FTI.getExceptionSpecType())
+ Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef)
+ << (D.getContext() == Declarator::AliasDeclContext);
if (!FTI.NumArgs && !FTI.isVariadic && !getLangOptions().CPlusPlus) {
// Simple void foo(), where the incoming T is the result type.
@@ -1845,9 +1918,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
} else if (!FTI.hasPrototype) {
if (ArgTy->isPromotableIntegerType()) {
ArgTy = Context.getPromotedIntegerType(ArgTy);
+ Param->setKNRPromoted(true);
} else if (const BuiltinType* BTy = ArgTy->getAs<BuiltinType>()) {
- if (BTy->getKind() == BuiltinType::Float)
+ if (BTy->getKind() == BuiltinType::Float) {
ArgTy = Context.DoubleTy;
+ Param->setKNRPromoted(true);
+ }
}
}
@@ -1855,9 +1931,8 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
llvm::SmallVector<QualType, 4> Exceptions;
- if (FTI.hasExceptionSpec) {
- EPI.HasExceptionSpec = FTI.hasExceptionSpec;
- EPI.HasAnyExceptionSpec = FTI.hasAnyExceptionSpec;
+ EPI.ExceptionSpecType = FTI.getExceptionSpecType();
+ if (FTI.getExceptionSpecType() == EST_Dynamic) {
Exceptions.reserve(FTI.NumExceptions);
for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) {
// FIXME: Preserve type source info.
@@ -1869,6 +1944,27 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
EPI.NumExceptions = Exceptions.size();
EPI.Exceptions = Exceptions.data();
+ } else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) {
+ // If an error occurred, there's no expression here.
+ if (Expr *NoexceptExpr = FTI.NoexceptExpr) {
+ assert((NoexceptExpr->isTypeDependent() ||
+ NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
+ Context.BoolTy) &&
+ "Parser should have made sure that the expression is boolean");
+ SourceLocation ErrLoc;
+ llvm::APSInt Dummy;
+ if (!NoexceptExpr->isValueDependent() &&
+ !NoexceptExpr->isIntegerConstantExpr(Dummy, Context, &ErrLoc,
+ /*evaluated*/false))
+ Diag(ErrLoc, diag::err_noexcept_needs_constant_expression)
+ << NoexceptExpr->getSourceRange();
+ else
+ EPI.NoexceptExpr = NoexceptExpr;
+ }
+ } else if (FTI.getExceptionSpecType() == EST_None &&
+ ImplicitlyNoexcept && chunkIndex == 0) {
+ // Only the outermost chunk is marked noexcept, of course.
+ EPI.ExceptionSpecType = EST_BasicNoexcept;
}
T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI);
@@ -1903,11 +1999,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
ClsType = QualType(NNS->getAsType(), 0);
- // Note: if NNS is dependent, then its prefix (if any) is already
- // included in ClsType; this does not hold if the NNS is
- // nondependent: in this case (if there is indeed a prefix)
- // ClsType needs to be wrapped into an elaborated type.
- if (NNSPrefix && !NNS->isDependent())
+ // Note: if the NNS has a prefix and ClsType is a nondependent
+ // TemplateSpecializationType, then the NNS prefix is NOT included
+ // in ClsType; hence we wrap ClsType into an ElaboratedType.
+ // NOTE: in particular, no wrap occurs if ClsType already is an
+ // Elaborated, DependentName, or DependentTemplateSpecialization.
+ if (NNSPrefix && isa<TemplateSpecializationType>(NNS->getAsType()))
ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType);
break;
}
@@ -1968,8 +2065,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// declaration.
if ((FnTy->getTypeQuals() != 0 || FnTy->getRefQualifier()) &&
!(D.getContext() == Declarator::TemplateTypeArgContext &&
- !D.isFunctionDeclarator()) &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+ !D.isFunctionDeclarator()) && !IsTypedefName &&
(FreeFunction ||
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) {
if (D.getContext() == Declarator::TemplateTypeArgContext) {
@@ -2053,8 +2149,10 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// Diagnose any ignored type attributes.
if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T);
- // If there's a constexpr specifier, treat it as a top-level const.
- if (D.getDeclSpec().isConstexprSpecified()) {
+ // C++0x [dcl.constexpr]p9:
+ // A constexpr specifier used in an object declaration declares the object
+ // as const.
+ if (D.getDeclSpec().isConstexprSpecified() && T->isObjectType()) {
T.addConst();
}
@@ -2103,7 +2201,9 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
case Declarator::FileContext:
case Declarator::KNRTypeListContext:
+ case Declarator::ObjCPrototypeContext: // FIXME: special diagnostic here?
case Declarator::TypeNameContext:
+ case Declarator::AliasDeclContext:
case Declarator::MemberContext:
case Declarator::BlockContext:
case Declarator::ForContext:
@@ -2126,6 +2226,62 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
return GetTypeSourceInfoForDeclarator(D, T, ReturnTypeInfo);
}
+/// Map an AttributedType::Kind to an AttributeList::Kind.
+static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
+ switch (kind) {
+ case AttributedType::attr_address_space:
+ return AttributeList::AT_address_space;
+ case AttributedType::attr_regparm:
+ return AttributeList::AT_regparm;
+ case AttributedType::attr_vector_size:
+ return AttributeList::AT_vector_size;
+ case AttributedType::attr_neon_vector_type:
+ return AttributeList::AT_neon_vector_type;
+ case AttributedType::attr_neon_polyvector_type:
+ return AttributeList::AT_neon_polyvector_type;
+ case AttributedType::attr_objc_gc:
+ return AttributeList::AT_objc_gc;
+ case AttributedType::attr_noreturn:
+ return AttributeList::AT_noreturn;
+ case AttributedType::attr_cdecl:
+ return AttributeList::AT_cdecl;
+ case AttributedType::attr_fastcall:
+ return AttributeList::AT_fastcall;
+ case AttributedType::attr_stdcall:
+ return AttributeList::AT_stdcall;
+ case AttributedType::attr_thiscall:
+ return AttributeList::AT_thiscall;
+ case AttributedType::attr_pascal:
+ return AttributeList::AT_pascal;
+ case AttributedType::attr_pcs:
+ return AttributeList::AT_pcs;
+ }
+ llvm_unreachable("unexpected attribute kind!");
+ return AttributeList::Kind();
+}
+
+static void fillAttributedTypeLoc(AttributedTypeLoc TL,
+ const AttributeList *attrs) {
+ AttributedType::Kind kind = TL.getAttrKind();
+
+ assert(attrs && "no type attributes in the expected location!");
+ AttributeList::Kind parsedKind = getAttrListKind(kind);
+ while (attrs->getKind() != parsedKind) {
+ attrs = attrs->getNext();
+ assert(attrs && "no matching attribute in expected location!");
+ }
+
+ TL.setAttrNameLoc(attrs->getLoc());
+ if (TL.hasAttrExprOperand())
+ TL.setAttrExprOperand(attrs->getArg(0));
+ else if (TL.hasAttrEnumOperand())
+ TL.setAttrEnumOperandLoc(attrs->getParameterLoc());
+
+ // FIXME: preserve this information to here.
+ if (TL.hasAttrOperand())
+ TL.setAttrOperandParensRange(SourceRange());
+}
+
namespace {
class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
ASTContext &Context;
@@ -2135,6 +2291,10 @@ namespace {
TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS)
: Context(Context), DS(DS) {}
+ void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+ fillAttributedTypeLoc(TL, DS.getAttributes().getList());
+ Visit(TL.getModifiedLoc());
+ }
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
Visit(TL.getUnqualifiedLoc());
}
@@ -2179,7 +2339,7 @@ namespace {
// If we got no declarator info from previous Sema routines,
// just fill with the typespec loc.
if (!TInfo) {
- TL.initialize(Context, DS.getTypeSpecTypeLoc());
+ TL.initialize(Context, DS.getTypeSpecTypeNameLoc());
return;
}
@@ -2237,7 +2397,7 @@ namespace {
? DS.getTypeSpecTypeLoc()
: SourceLocation());
const CXXScopeSpec& SS = DS.getTypeSpecScope();
- TL.setQualifierRange(SS.isEmpty() ? SourceRange(): SS.getRange());
+ TL.setQualifierLoc(SS.getWithLocInContext(Context));
Visit(TL.getNextTypeLoc().getUnqualifiedLoc());
}
void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
@@ -2255,9 +2415,8 @@ namespace {
? DS.getTypeSpecTypeLoc()
: SourceLocation());
const CXXScopeSpec& SS = DS.getTypeSpecScope();
- TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange());
- // FIXME: load appropriate source location.
- TL.setNameLoc(DS.getTypeSpecTypeLoc());
+ TL.setQualifierLoc(SS.getWithLocInContext(Context));
+ TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
}
void VisitDependentTemplateSpecializationTypeLoc(
DependentTemplateSpecializationTypeLoc TL) {
@@ -2277,9 +2436,11 @@ namespace {
? DS.getTypeSpecTypeLoc()
: SourceLocation());
const CXXScopeSpec& SS = DS.getTypeSpecScope();
- TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange());
- // FIXME: load appropriate source location.
- TL.setNameLoc(DS.getTypeSpecTypeLoc());
+ TL.setQualifierLoc(SS.getWithLocInContext(Context));
+ TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
+ }
+ void VisitTagTypeLoc(TagTypeLoc TL) {
+ TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
}
void VisitTypeLoc(TypeLoc TL) {
@@ -2289,10 +2450,12 @@ namespace {
};
class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
+ ASTContext &Context;
const DeclaratorChunk &Chunk;
public:
- DeclaratorLocFiller(const DeclaratorChunk &Chunk) : Chunk(Chunk) {}
+ DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk)
+ : Context(Context), Chunk(Chunk) {}
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
llvm_unreachable("qualified type locs not expected here!");
@@ -2312,8 +2475,48 @@ namespace {
}
void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
+ const CXXScopeSpec& SS = Chunk.Mem.Scope();
+ NestedNameSpecifierLoc NNSLoc = SS.getWithLocInContext(Context);
+
+ const Type* ClsTy = TL.getClass();
+ QualType ClsQT = QualType(ClsTy, 0);
+ TypeSourceInfo *ClsTInfo = Context.CreateTypeSourceInfo(ClsQT, 0);
+ // Now copy source location info into the type loc component.
+ TypeLoc ClsTL = ClsTInfo->getTypeLoc();
+ switch (NNSLoc.getNestedNameSpecifier()->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc");
+ {
+ DependentNameTypeLoc DNTLoc = cast<DependentNameTypeLoc>(ClsTL);
+ DNTLoc.setKeywordLoc(SourceLocation());
+ DNTLoc.setQualifierLoc(NNSLoc.getPrefix());
+ DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc());
+ }
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ if (isa<ElaboratedType>(ClsTy)) {
+ ElaboratedTypeLoc ETLoc = *cast<ElaboratedTypeLoc>(&ClsTL);
+ ETLoc.setKeywordLoc(SourceLocation());
+ ETLoc.setQualifierLoc(NNSLoc.getPrefix());
+ TypeLoc NamedTL = ETLoc.getNamedTypeLoc();
+ NamedTL.initializeFullCopy(NNSLoc.getTypeLoc());
+ } else {
+ ClsTL.initializeFullCopy(NNSLoc.getTypeLoc());
+ }
+ break;
+
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ case NestedNameSpecifier::Global:
+ llvm_unreachable("Nested-name-specifier must name a type");
+ break;
+ }
+
+ // Finally fill in MemberPointerLocInfo fields.
TL.setStarLoc(Chunk.Loc);
- // FIXME: nested name specifier
+ TL.setClassTInfo(ClsTInfo);
}
void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Reference);
@@ -2334,8 +2537,8 @@ namespace {
}
void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Function);
- TL.setLParenLoc(Chunk.Loc);
- TL.setRParenLoc(Chunk.EndLoc);
+ TL.setLocalRangeBegin(Chunk.Loc);
+ TL.setLocalRangeEnd(Chunk.EndLoc);
TL.setTrailingReturn(!!Chunk.Fun.TrailingReturnType);
const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
@@ -2378,7 +2581,13 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
}
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
- DeclaratorLocFiller(D.getTypeObject(i)).Visit(CurrTL);
+ while (isa<AttributedTypeLoc>(CurrTL)) {
+ AttributedTypeLoc TL = cast<AttributedTypeLoc>(CurrTL);
+ fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs());
+ CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
+ }
+
+ DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
@@ -2434,7 +2643,8 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
// A type-specifier-seq shall not define a class or enumeration
// unless it appears in the type-id of an alias-declaration
// (7.1.3).
- if (OwnedTag && OwnedTag->isDefinition())
+ if (OwnedTag && OwnedTag->isDefinition() &&
+ D.getContext() != Declarator::AliasDeclContext)
Diag(OwnedTag->getLocation(), diag::err_type_defined_in_type_specifier)
<< Context.getTypeDeclType(OwnedTag);
}
@@ -2547,7 +2757,14 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state,
return true;
}
- type = S.Context.getObjCGCQualType(type, GCAttr);
+ QualType origType = type;
+ type = S.Context.getObjCGCQualType(origType, GCAttr);
+
+ // Make an attributed type to preserve the source information.
+ if (attr.getLoc().isValid())
+ type = S.Context.getAttributedType(AttributedType::attr_objc_gc,
+ origType, type);
+
return true;
}
@@ -2775,7 +2992,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
}
// Also diagnose fastcall with regparm.
- if (fn->getRegParmType()) {
+ if (fn->getHasRegParm()) {
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
<< "regparm"
<< FunctionType::getNameForCallConv(CC);
@@ -2789,6 +3006,41 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
return true;
}
+/// Handle OpenCL image access qualifiers: read_only, write_only, read_write
+static void HandleOpenCLImageAccessAttribute(QualType& CurType,
+ const AttributeList &Attr,
+ Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ Attr.setInvalid();
+ return;
+ }
+ Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
+ llvm::APSInt arg(32);
+ if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
+ !sizeExpr->isIntegerConstantExpr(arg, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+ << "opencl_image_access" << sizeExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ unsigned iarg = static_cast<unsigned>(arg.getZExtValue());
+ switch (iarg) {
+ case CLIA_read_only:
+ case CLIA_write_only:
+ case CLIA_read_write:
+ // Implemented in a separate patch
+ break;
+ default:
+ // Implemented in a separate patch
+ S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
+ << sizeExpr->getSourceRange();
+ Attr.setInvalid();
+ break;
+ }
+}
+
/// HandleVectorSizeAttribute - this attribute is only applicable to integral
/// and float scalars, although arrays, pointers, and function return values are
/// allowed in conjunction with this construct. Aggregates with this attribute
@@ -2943,6 +3195,10 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
"neon_polyvector_type");
break;
+ case AttributeList::AT_opencl_image_access:
+ HandleOpenCLImageAccessAttribute(type, attr, state.getSema());
+ break;
+
FUNCTION_TYPE_ATTRS_CASELIST:
// Never process function type attributes as part of the
// declaration-specifiers.
@@ -3088,7 +3344,7 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
}
QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
- ExprResult ER = CheckPlaceholderExpr(E, Loc);
+ ExprResult ER = CheckPlaceholderExpr(E);
if (ER.isInvalid()) return QualType();
E = ER.take();
@@ -3101,7 +3357,7 @@ QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
}
QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) {
- ExprResult ER = CheckPlaceholderExpr(E, Loc);
+ ExprResult ER = CheckPlaceholderExpr(E);
if (ER.isInvalid()) return QualType();
E = ER.take();
diff --git a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp
index c3415cb..ab697ee 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp
@@ -136,7 +136,7 @@ static void HandleX86ForceAlignArgPointerAttr(Decl *D,
if (VD && VD->getType()->isFunctionPointerType())
return;
// Also don't warn on function pointer typedefs.
- TypedefDecl *TD = dyn_cast<TypedefDecl>(D);
+ TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
TD->getUnderlyingType()->isFunctionType()))
return;
diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
index 57a44ad..2a71e14 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
@@ -67,7 +67,7 @@ using namespace sema;
///
/// Subclasses can customize the transformation at various levels. The
/// most coarse-grained transformations involve replacing TransformType(),
-/// TransformExpr(), TransformDecl(), TransformNestedNameSpecifier(),
+/// TransformExpr(), TransformDecl(), TransformNestedNameSpecifierLoc(),
/// TransformTemplateName(), or TransformTemplateArgument() with entirely
/// new implementations.
///
@@ -375,16 +375,6 @@ public:
return cast_or_null<NamedDecl>(getDerived().TransformDecl(Loc, D));
}
- /// \brief Transform the given nested-name-specifier.
- ///
- /// By default, transforms all of the types and declarations within the
- /// nested-name-specifier. Subclasses may override this function to provide
- /// alternate behavior.
- NestedNameSpecifier *TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
- SourceRange Range,
- QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = 0);
-
/// \brief Transform the given nested-name-specifier with source-location
/// information.
///
@@ -407,10 +397,27 @@ public:
/// \brief Transform the given template name.
///
+ /// \param SS The nested-name-specifier that qualifies the template
+ /// name. This nested-name-specifier must already have been transformed.
+ ///
+ /// \param Name The template name to transform.
+ ///
+ /// \param NameLoc The source location of the template name.
+ ///
+ /// \param ObjectType If we're translating a template name within a member
+ /// access expression, this is the type of the object whose member template
+ /// is being referenced.
+ ///
+ /// \param FirstQualifierInScope If the first part of a nested-name-specifier
+ /// also refers to a name within the current (lexical) scope, this is the
+ /// declaration it refers to.
+ ///
/// By default, transforms the template name by transforming the declarations
/// and nested-name-specifiers that occur within the template name.
/// Subclasses may override this function to provide alternate behavior.
- TemplateName TransformTemplateName(TemplateName Name,
+ TemplateName TransformTemplateName(CXXScopeSpec &SS,
+ TemplateName Name,
+ SourceLocation NameLoc,
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = 0);
@@ -483,6 +490,9 @@ public:
QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
#include "clang/AST/TypeLocNodes.def"
+ StmtResult
+ TransformSEHHandler(Stmt *Handler);
+
QualType
TransformTemplateSpecializationType(TypeLocBuilder &TLB,
TemplateSpecializationTypeLoc TL,
@@ -491,7 +501,13 @@ public:
QualType
TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
DependentTemplateSpecializationTypeLoc TL,
- NestedNameSpecifier *Prefix);
+ TemplateName Template,
+ CXXScopeSpec &SS);
+
+ QualType
+ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
+ DependentTemplateSpecializationTypeLoc TL,
+ NestedNameSpecifierLoc QualifierLoc);
/// \brief Transforms the parameters of a function type into the
/// given vectors.
@@ -508,7 +524,11 @@ public:
/// \brief Transforms a single function-type parameter. Return null
/// on error.
+ ///
+ /// \param indexAdjustment - A number to add to the parameter's
+ /// scope index; can be negative
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
+ int indexAdjustment,
llvm::Optional<unsigned> NumExpansions);
QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL);
@@ -656,7 +676,7 @@ public:
QualType RebuildUnresolvedUsingType(Decl *D);
/// \brief Build a new typedef type.
- QualType RebuildTypedefType(TypedefDecl *Typedef) {
+ QualType RebuildTypedefType(TypedefNameDecl *Typedef) {
return SemaRef.Context.getTypeDeclType(Typedef);
}
@@ -701,7 +721,7 @@ public:
/// different behavior.
QualType RebuildTemplateSpecializationType(TemplateName Template,
SourceLocation TemplateLoc,
- const TemplateArgumentListInfo &Args);
+ TemplateArgumentListInfo &Args);
/// \brief Build a new parenthesized type.
///
@@ -718,8 +738,11 @@ public:
/// Subclasses may override this routine to provide different behavior.
QualType RebuildElaboratedType(SourceLocation KeywordLoc,
ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS, QualType Named) {
- return SemaRef.Context.getElaboratedType(Keyword, NNS, Named);
+ NestedNameSpecifierLoc QualifierLoc,
+ QualType Named) {
+ return SemaRef.Context.getElaboratedType(Keyword,
+ QualifierLoc.getNestedNameSpecifier(),
+ Named);
}
/// \brief Build a new typename type that refers to a template-id.
@@ -728,34 +751,40 @@ public:
/// nested-name-specifier and the given type. Subclasses may override
/// this routine to provide different behavior.
QualType RebuildDependentTemplateSpecializationType(
- ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
- const IdentifierInfo *Name,
- SourceLocation NameLoc,
- const TemplateArgumentListInfo &Args) {
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifierLoc QualifierLoc,
+ const IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ TemplateArgumentListInfo &Args) {
// Rebuild the template name.
// TODO: avoid TemplateName abstraction
- TemplateName InstName =
- getDerived().RebuildTemplateName(Qualifier, QualifierRange, *Name,
- QualType(), 0);
+ CXXScopeSpec SS;
+ SS.Adopt(QualifierLoc);
+ TemplateName InstName
+ = getDerived().RebuildTemplateName(SS, *Name, NameLoc, QualType(), 0);
if (InstName.isNull())
return QualType();
-
+
// If it's still dependent, make a dependent specialization.
if (InstName.getAsDependentTemplateName())
- return SemaRef.Context.getDependentTemplateSpecializationType(
- Keyword, Qualifier, Name, Args);
-
+ return SemaRef.Context.getDependentTemplateSpecializationType(Keyword,
+ QualifierLoc.getNestedNameSpecifier(),
+ Name,
+ Args);
+
// Otherwise, make an elaborated type wrapping a non-dependent
// specialization.
QualType T =
- getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args);
+ getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args);
if (T.isNull()) return QualType();
-
- // NOTE: NNS is already recorded in template specialization type T.
- return SemaRef.Context.getElaboratedType(Keyword, /*NNS=*/0, T);
+
+ if (Keyword == ETK_None && QualifierLoc.getNestedNameSpecifier() == 0)
+ return T;
+
+ return SemaRef.Context.getElaboratedType(Keyword,
+ QualifierLoc.getNestedNameSpecifier(),
+ T);
}
/// \brief Build a new typename type that refers to an identifier.
@@ -764,23 +793,24 @@ public:
/// (or elaborated type). Subclasses may override this routine to provide
/// different behavior.
QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS,
- const IdentifierInfo *Id,
SourceLocation KeywordLoc,
- SourceRange NNSRange,
+ NestedNameSpecifierLoc QualifierLoc,
+ const IdentifierInfo *Id,
SourceLocation IdLoc) {
CXXScopeSpec SS;
- SS.MakeTrivial(SemaRef.Context, NNS, NNSRange);
+ SS.Adopt(QualifierLoc);
- if (NNS->isDependent()) {
+ if (QualifierLoc.getNestedNameSpecifier()->isDependent()) {
// If the name is still dependent, just build a new dependent name type.
if (!SemaRef.computeDeclContext(SS))
- return SemaRef.Context.getDependentNameType(Keyword, NNS, Id);
+ return SemaRef.Context.getDependentNameType(Keyword,
+ QualifierLoc.getNestedNameSpecifier(),
+ Id);
}
if (Keyword == ETK_None || Keyword == ETK_Typename)
- return SemaRef.CheckTypenameType(Keyword, NNS, *Id,
- KeywordLoc, NNSRange, IdLoc);
+ return SemaRef.CheckTypenameType(Keyword, KeywordLoc, QualifierLoc,
+ *Id, IdLoc);
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword);
@@ -828,7 +858,8 @@ public:
NamedDecl *SomeDecl = Result.getRepresentativeDecl();
unsigned Kind = 0;
if (isa<TypedefDecl>(SomeDecl)) Kind = 1;
- else if (isa<ClassTemplateDecl>(SomeDecl)) Kind = 2;
+ else if (isa<TypeAliasDecl>(SomeDecl)) Kind = 2;
+ else if (isa<ClassTemplateDecl>(SomeDecl)) Kind = 3;
SemaRef.Diag(IdLoc, diag::err_tag_reference_non_tag) << Kind;
SemaRef.Diag(SomeDecl->getLocation(), diag::note_declared_at);
break;
@@ -850,7 +881,9 @@ public:
// Build the elaborated-type-specifier type.
QualType T = SemaRef.Context.getTypeDeclType(Tag);
- return SemaRef.Context.getElaboratedType(Keyword, NNS, T);
+ return SemaRef.Context.getElaboratedType(Keyword,
+ QualifierLoc.getNestedNameSpecifier(),
+ T);
}
/// \brief Build a new pack expansion type.
@@ -865,56 +898,13 @@ public:
NumExpansions);
}
- /// \brief Build a new nested-name-specifier given the prefix and an
- /// identifier that names the next step in the nested-name-specifier.
- ///
- /// By default, performs semantic analysis when building the new
- /// nested-name-specifier. Subclasses may override this routine to provide
- /// different behavior.
- NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
- SourceRange Range,
- IdentifierInfo &II,
- QualType ObjectType,
- NamedDecl *FirstQualifierInScope);
-
- /// \brief Build a new nested-name-specifier given the prefix and the
- /// namespace named in the next step in the nested-name-specifier.
- ///
- /// By default, performs semantic analysis when building the new
- /// nested-name-specifier. Subclasses may override this routine to provide
- /// different behavior.
- NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
- SourceRange Range,
- NamespaceDecl *NS);
-
- /// \brief Build a new nested-name-specifier given the prefix and the
- /// namespace alias named in the next step in the nested-name-specifier.
- ///
- /// By default, performs semantic analysis when building the new
- /// nested-name-specifier. Subclasses may override this routine to provide
- /// different behavior.
- NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
- SourceRange Range,
- NamespaceAliasDecl *Alias);
-
- /// \brief Build a new nested-name-specifier given the prefix and the
- /// type named in the next step in the nested-name-specifier.
- ///
- /// By default, performs semantic analysis when building the new
- /// nested-name-specifier. Subclasses may override this routine to provide
- /// different behavior.
- NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
- SourceRange Range,
- bool TemplateKW,
- QualType T);
-
/// \brief Build a new template name given a nested name specifier, a flag
/// indicating whether the "template" keyword was provided, and the template
/// that the template name refers to.
///
/// By default, builds the new template name directly. Subclasses may override
/// this routine to provide different behavior.
- TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ TemplateName RebuildTemplateName(CXXScopeSpec &SS,
bool TemplateKW,
TemplateDecl *Template);
@@ -925,9 +915,9 @@ public:
/// be resolved to a specific template, then builds the appropriate kind of
/// template name. Subclasses may override this routine to provide different
/// behavior.
- TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
- const IdentifierInfo &II,
+ TemplateName RebuildTemplateName(CXXScopeSpec &SS,
+ const IdentifierInfo &Name,
+ SourceLocation NameLoc,
QualType ObjectType,
NamedDecl *FirstQualifierInScope);
@@ -938,8 +928,9 @@ public:
/// be resolved to a specific template, then builds the appropriate kind of
/// template name. Subclasses may override this routine to provide different
/// behavior.
- TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ TemplateName RebuildTemplateName(CXXScopeSpec &SS,
OverloadedOperatorKind Operator,
+ SourceLocation NameLoc,
QualType ObjectType);
/// \brief Build a new template name given a template template parameter pack
@@ -1147,9 +1138,10 @@ public:
/// Subclasses may override this routine to provide different behavior.
VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *TInfo, QualType T) {
- return getSema().BuildObjCExceptionDecl(TInfo, T,
- ExceptionDecl->getIdentifier(),
- ExceptionDecl->getLocation());
+ return getSema().BuildObjCExceptionDecl(TInfo, T,
+ ExceptionDecl->getInnerLocStart(),
+ ExceptionDecl->getLocation(),
+ ExceptionDecl->getIdentifier());
}
/// \brief Build a new Objective-C @catch statement.
@@ -1214,11 +1206,16 @@ public:
///
/// By default, performs semantic analysis to build the new decaration.
/// Subclasses may override this routine to provide different behavior.
- VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
+ VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *Declarator,
- IdentifierInfo *Name,
- SourceLocation Loc) {
- return getSema().BuildExceptionDeclaration(0, Declarator, Name, Loc);
+ SourceLocation StartLoc,
+ SourceLocation IdLoc,
+ IdentifierInfo *Id) {
+ VarDecl *Var = getSema().BuildExceptionDeclaration(0, Declarator,
+ StartLoc, IdLoc, Id);
+ if (Var)
+ getSema().CurContext->addDecl(Var);
+ return Var;
}
/// \brief Build a new C++ catch statement.
@@ -1242,6 +1239,46 @@ public:
return getSema().ActOnCXXTryBlock(TryLoc, TryBlock, move(Handlers));
}
+ /// \brief Build a new C++0x range-based for statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildCXXForRangeStmt(SourceLocation ForLoc,
+ SourceLocation ColonLoc,
+ Stmt *Range, Stmt *BeginEnd,
+ Expr *Cond, Expr *Inc,
+ Stmt *LoopVar,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXForRangeStmt(ForLoc, ColonLoc, Range, BeginEnd,
+ Cond, Inc, LoopVar, RParenLoc);
+ }
+
+ /// \brief Attach body to a C++0x range-based for statement.
+ ///
+ /// By default, performs semantic analysis to finish the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body) {
+ return getSema().FinishCXXForRangeStmt(ForRange, Body);
+ }
+
+ StmtResult RebuildSEHTryStmt(bool IsCXXTry,
+ SourceLocation TryLoc,
+ Stmt *TryBlock,
+ Stmt *Handler) {
+ return getSema().ActOnSEHTryBlock(IsCXXTry,TryLoc,TryBlock,Handler);
+ }
+
+ StmtResult RebuildSEHExceptStmt(SourceLocation Loc,
+ Expr *FilterExpr,
+ Stmt *Block) {
+ return getSema().ActOnSEHExceptBlock(Loc,FilterExpr,Block);
+ }
+
+ StmtResult RebuildSEHFinallyStmt(SourceLocation Loc,
+ Stmt *Block) {
+ return getSema().ActOnSEHFinallyBlock(Loc,Block);
+ }
+
/// \brief Build a new expression that references a declaration.
///
/// By default, performs semantic analysis to build the new expression.
@@ -1257,13 +1294,12 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ ExprResult RebuildDeclRefExpr(NestedNameSpecifierLoc QualifierLoc,
ValueDecl *VD,
const DeclarationNameInfo &NameInfo,
TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
- SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
+ SS.Adopt(QualifierLoc);
// FIXME: loses template args.
@@ -1315,25 +1351,28 @@ public:
NumComponents, RParenLoc);
}
- /// \brief Build a new sizeof or alignof expression with a type argument.
+ /// \brief Build a new sizeof, alignof or vec_step expression with a
+ /// type argument.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildSizeOfAlignOf(TypeSourceInfo *TInfo,
- SourceLocation OpLoc,
- bool isSizeOf, SourceRange R) {
- return getSema().CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeOf, R);
+ ExprResult RebuildUnaryExprOrTypeTrait(TypeSourceInfo *TInfo,
+ SourceLocation OpLoc,
+ UnaryExprOrTypeTrait ExprKind,
+ SourceRange R) {
+ return getSema().CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, R);
}
- /// \brief Build a new sizeof or alignof expression with an expression
- /// argument.
+ /// \brief Build a new sizeof, alignof or vec step expression with an
+ /// expression argument.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildSizeOfAlignOf(Expr *SubExpr, SourceLocation OpLoc,
- bool isSizeOf, SourceRange R) {
+ ExprResult RebuildUnaryExprOrTypeTrait(Expr *SubExpr, SourceLocation OpLoc,
+ UnaryExprOrTypeTrait ExprKind,
+ SourceRange R) {
ExprResult Result
- = getSema().CreateSizeOfAlignOfExpr(SubExpr, OpLoc, isSizeOf, R);
+ = getSema().CreateUnaryExprOrTypeTraitExpr(SubExpr, OpLoc, ExprKind, R);
if (Result.isInvalid())
return ExprError();
@@ -1371,8 +1410,7 @@ public:
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildMemberExpr(Expr *Base, SourceLocation OpLoc,
bool isArrow,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &MemberNameInfo,
ValueDecl *Member,
NamedDecl *FoundDecl,
@@ -1382,14 +1420,17 @@ public:
// We have a reference to an unnamed field. This is always the
// base of an anonymous struct/union member access, i.e. the
// field is always of record type.
- assert(!Qualifier && "Can't have an unnamed field with a qualifier!");
+ assert(!QualifierLoc && "Can't have an unnamed field with a qualifier!");
assert(Member->getType()->isRecordType() &&
"unnamed member not of record type?");
- if (getSema().PerformObjectMemberConversion(Base, Qualifier,
- FoundDecl, Member))
+ ExprResult BaseResult =
+ getSema().PerformObjectMemberConversion(Base,
+ QualifierLoc.getNestedNameSpecifier(),
+ FoundDecl, Member);
+ if (BaseResult.isInvalid())
return ExprError();
-
+ Base = BaseResult.take();
ExprValueKind VK = isArrow ? VK_LValue : Base->getValueKind();
MemberExpr *ME =
new (getSema().Context) MemberExpr(Base, isArrow,
@@ -1400,11 +1441,12 @@ public:
}
CXXScopeSpec SS;
- if (Qualifier) {
- SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
- }
+ SS.Adopt(QualifierLoc);
- getSema().DefaultFunctionArrayConversion(Base);
+ ExprResult BaseResult = getSema().DefaultFunctionArrayConversion(Base);
+ if (BaseResult.isInvalid())
+ return ExprError();
+ Base = BaseResult.take();
QualType BaseType = Base->getType();
// FIXME: this involves duplicating earlier analysis in a lot of
@@ -1586,6 +1628,22 @@ public:
RParenLoc);
}
+ /// \brief Build a new generic selection expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildGenericSelectionExpr(SourceLocation KeyLoc,
+ SourceLocation DefaultLoc,
+ SourceLocation RParenLoc,
+ Expr *ControllingExpr,
+ TypeSourceInfo **Types,
+ Expr **Exprs,
+ unsigned NumAssocs) {
+ return getSema().CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
+ ControllingExpr, Types, Exprs,
+ NumAssocs);
+ }
+
/// \brief Build a new overloaded operator call expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -1882,6 +1940,29 @@ public:
return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc);
}
+ /// \brief Build a new array type trait expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildArrayTypeTrait(ArrayTypeTrait Trait,
+ SourceLocation StartLoc,
+ TypeSourceInfo *TSInfo,
+ Expr *DimExpr,
+ SourceLocation RParenLoc) {
+ return getSema().BuildArrayTypeTrait(Trait, StartLoc, TSInfo, DimExpr, RParenLoc);
+ }
+
+ /// \brief Build a new expression trait expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildExpressionTrait(ExpressionTrait Trait,
+ SourceLocation StartLoc,
+ Expr *Queried,
+ SourceLocation RParenLoc) {
+ return getSema().BuildExpressionTrait(Trait, StartLoc, Queried, RParenLoc);
+ }
+
/// \brief Build a new (previously unresolved) declaration reference
/// expression.
///
@@ -1968,16 +2049,15 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildCXXDependentScopeMemberExpr(Expr *BaseE,
- QualType BaseType,
- bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ QualType BaseType,
+ bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc,
NamedDecl *FirstQualifierInScope,
const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
- SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
+ SS.Adopt(QualifierLoc);
return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
OperatorLoc, IsArrow,
@@ -1994,13 +2074,12 @@ public:
QualType BaseType,
SourceLocation OperatorLoc,
bool IsArrow,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ NestedNameSpecifierLoc QualifierLoc,
NamedDecl *FirstQualifierInScope,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
- SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
+ SS.Adopt(QualifierLoc);
return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
OperatorLoc, IsArrow,
@@ -2076,20 +2155,20 @@ public:
bool IsArrow, bool IsFreeIvar) {
// FIXME: We lose track of the IsFreeIvar bit.
CXXScopeSpec SS;
- Expr *Base = BaseArg;
+ ExprResult Base = getSema().Owned(BaseArg);
LookupResult R(getSema(), Ivar->getDeclName(), IvarLoc,
Sema::LookupMemberName);
ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
/*FIME:*/IvarLoc,
SS, 0,
false);
- if (Result.isInvalid())
+ if (Result.isInvalid() || Base.isInvalid())
return ExprError();
if (Result.get())
return move(Result);
- return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
+ return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(),
/*FIXME:*/IvarLoc, IsArrow, SS,
/*FirstQualifierInScope=*/0,
R,
@@ -2104,20 +2183,20 @@ public:
ObjCPropertyDecl *Property,
SourceLocation PropertyLoc) {
CXXScopeSpec SS;
- Expr *Base = BaseArg;
+ ExprResult Base = getSema().Owned(BaseArg);
LookupResult R(getSema(), Property->getDeclName(), PropertyLoc,
Sema::LookupMemberName);
bool IsArrow = false;
ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
/*FIME:*/PropertyLoc,
SS, 0, false);
- if (Result.isInvalid())
+ if (Result.isInvalid() || Base.isInvalid())
return ExprError();
if (Result.get())
return move(Result);
- return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
+ return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(),
/*FIXME:*/PropertyLoc, IsArrow,
SS,
/*FirstQualifierInScope=*/0,
@@ -2148,19 +2227,19 @@ public:
ExprResult RebuildObjCIsaExpr(Expr *BaseArg, SourceLocation IsaLoc,
bool IsArrow) {
CXXScopeSpec SS;
- Expr *Base = BaseArg;
+ ExprResult Base = getSema().Owned(BaseArg);
LookupResult R(getSema(), &getSema().Context.Idents.get("isa"), IsaLoc,
Sema::LookupMemberName);
ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
/*FIME:*/IsaLoc,
SS, 0, false);
- if (Result.isInvalid())
+ if (Result.isInvalid() || Base.isInvalid())
return ExprError();
if (Result.get())
return move(Result);
- return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
+ return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(),
/*FIXME:*/IsaLoc, IsArrow, SS,
/*FirstQualifierInScope=*/0,
R,
@@ -2183,28 +2262,25 @@ public:
// Build a reference to the __builtin_shufflevector builtin
FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first);
- Expr *Callee
- = new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(),
- VK_LValue, BuiltinLoc);
- SemaRef.UsualUnaryConversions(Callee);
+ ExprResult Callee
+ = SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(),
+ VK_LValue, BuiltinLoc));
+ Callee = SemaRef.UsualUnaryConversions(Callee.take());
+ if (Callee.isInvalid())
+ return ExprError();
// Build the CallExpr
unsigned NumSubExprs = SubExprs.size();
Expr **Subs = (Expr **)SubExprs.release();
- CallExpr *TheCall = new (SemaRef.Context) CallExpr(SemaRef.Context, Callee,
+ ExprResult TheCall = SemaRef.Owned(
+ new (SemaRef.Context) CallExpr(SemaRef.Context, Callee.take(),
Subs, NumSubExprs,
Builtin->getCallResultType(),
Expr::getValueKindForType(Builtin->getResultType()),
- RParenLoc);
- ExprResult OwnedCall(SemaRef.Owned(TheCall));
+ RParenLoc));
// Type-check the __builtin_shufflevector expression.
- ExprResult Result = SemaRef.SemaBuiltinShuffleVector(TheCall);
- if (Result.isInvalid())
- return ExprError();
-
- OwnedCall.release();
- return move(Result);
+ return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.take()));
}
/// \brief Build a new template argument pack expansion.
@@ -2230,7 +2306,7 @@ public:
return TemplateArgumentLoc(TemplateArgument(
Pattern.getArgument().getAsTemplate(),
NumExpansions),
- Pattern.getTemplateQualifierRange(),
+ Pattern.getTemplateQualifierLoc(),
Pattern.getTemplateNameLoc(),
EllipsisLoc);
@@ -2265,20 +2341,15 @@ public:
}
private:
- QualType TransformTypeInObjectScope(QualType T,
- QualType ObjectType,
- NamedDecl *FirstQualifierInScope,
- NestedNameSpecifier *Prefix);
-
- TypeSourceInfo *TransformTypeInObjectScope(TypeSourceInfo *T,
- QualType ObjectType,
- NamedDecl *FirstQualifierInScope,
- NestedNameSpecifier *Prefix);
-
TypeLoc TransformTypeInObjectScope(TypeLoc TL,
QualType ObjectType,
NamedDecl *FirstQualifierInScope,
CXXScopeSpec &SS);
+
+ TypeSourceInfo *TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope,
+ CXXScopeSpec &SS);
};
template<typename Derived>
@@ -2426,99 +2497,6 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
}
template<typename Derived>
-NestedNameSpecifier *
-TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
- SourceRange Range,
- QualType ObjectType,
- NamedDecl *FirstQualifierInScope) {
- NestedNameSpecifier *Prefix = NNS->getPrefix();
-
- // Transform the prefix of this nested name specifier.
- if (Prefix) {
- Prefix = getDerived().TransformNestedNameSpecifier(Prefix, Range,
- ObjectType,
- FirstQualifierInScope);
- if (!Prefix)
- return 0;
- }
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- if (Prefix) {
- // The object type and qualifier-in-scope really apply to the
- // leftmost entity.
- ObjectType = QualType();
- FirstQualifierInScope = 0;
- }
-
- assert((Prefix || !ObjectType.isNull()) &&
- "Identifier nested-name-specifier with no prefix or object type");
- if (!getDerived().AlwaysRebuild() && Prefix == NNS->getPrefix() &&
- ObjectType.isNull())
- return NNS;
-
- return getDerived().RebuildNestedNameSpecifier(Prefix, Range,
- *NNS->getAsIdentifier(),
- ObjectType,
- FirstQualifierInScope);
-
- case NestedNameSpecifier::Namespace: {
- NamespaceDecl *NS
- = cast_or_null<NamespaceDecl>(
- getDerived().TransformDecl(Range.getBegin(),
- NNS->getAsNamespace()));
- if (!getDerived().AlwaysRebuild() &&
- Prefix == NNS->getPrefix() &&
- NS == NNS->getAsNamespace())
- return NNS;
-
- return getDerived().RebuildNestedNameSpecifier(Prefix, Range, NS);
- }
-
- case NestedNameSpecifier::NamespaceAlias: {
- NamespaceAliasDecl *Alias
- = cast_or_null<NamespaceAliasDecl>(
- getDerived().TransformDecl(Range.getBegin(),
- NNS->getAsNamespaceAlias()));
- if (!getDerived().AlwaysRebuild() &&
- Prefix == NNS->getPrefix() &&
- Alias == NNS->getAsNamespaceAlias())
- return NNS;
-
- return getDerived().RebuildNestedNameSpecifier(Prefix, Range, Alias);
- }
-
- case NestedNameSpecifier::Global:
- // There is no meaningful transformation that one could perform on the
- // global scope.
- return NNS;
-
- case NestedNameSpecifier::TypeSpecWithTemplate:
- case NestedNameSpecifier::TypeSpec: {
- TemporaryBase Rebase(*this, Range.getBegin(), DeclarationName());
- QualType T = TransformTypeInObjectScope(QualType(NNS->getAsType(), 0),
- ObjectType,
- FirstQualifierInScope,
- Prefix);
- if (T.isNull())
- return 0;
-
- if (!getDerived().AlwaysRebuild() &&
- Prefix == NNS->getPrefix() &&
- T == QualType(NNS->getAsType(), 0))
- return NNS;
-
- return getDerived().RebuildNestedNameSpecifier(Prefix, Range,
- NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate,
- T);
- }
- }
-
- // Required to silence a GCC warning
- return 0;
-}
-
-template<typename Derived>
NestedNameSpecifierLoc
TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
NestedNameSpecifierLoc NNS,
@@ -2594,10 +2572,11 @@ TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
<< TL.getType() << SS.getRange();
return NestedNameSpecifierLoc();
}
- }
+ }
- // The qualifier-in-scope only applies to the leftmost entity.
+ // The qualifier-in-scope and object type only apply to the leftmost entity.
FirstQualifierInScope = 0;
+ ObjectType = QualType();
}
// Don't rebuild the nested-name-specifier if we don't have to.
@@ -2669,89 +2648,73 @@ TreeTransform<Derived>
template<typename Derived>
TemplateName
-TreeTransform<Derived>::TransformTemplateName(TemplateName Name,
+TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
+ TemplateName Name,
+ SourceLocation NameLoc,
QualType ObjectType,
NamedDecl *FirstQualifierInScope) {
- SourceLocation Loc = getDerived().getBaseLocation();
-
if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
- NestedNameSpecifier *NNS
- = getDerived().TransformNestedNameSpecifier(QTN->getQualifier(),
- /*FIXME*/ SourceRange(Loc),
- ObjectType,
- FirstQualifierInScope);
- if (!NNS)
+ TemplateDecl *Template = QTN->getTemplateDecl();
+ assert(Template && "qualified template name must refer to a template");
+
+ TemplateDecl *TransTemplate
+ = cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc,
+ Template));
+ if (!TransTemplate)
return TemplateName();
-
- if (TemplateDecl *Template = QTN->getTemplateDecl()) {
- TemplateDecl *TransTemplate
- = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Loc, Template));
- if (!TransTemplate)
- return TemplateName();
-
- if (!getDerived().AlwaysRebuild() &&
- NNS == QTN->getQualifier() &&
- TransTemplate == Template)
- return Name;
-
- return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(),
- TransTemplate);
- }
-
- // These should be getting filtered out before they make it into the AST.
- llvm_unreachable("overloaded template name survived to here");
+
+ if (!getDerived().AlwaysRebuild() &&
+ SS.getScopeRep() == QTN->getQualifier() &&
+ TransTemplate == Template)
+ return Name;
+
+ return getDerived().RebuildTemplateName(SS, QTN->hasTemplateKeyword(),
+ TransTemplate);
}
-
+
if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
- NestedNameSpecifier *NNS = DTN->getQualifier();
- if (NNS) {
- NNS = getDerived().TransformNestedNameSpecifier(NNS,
- /*FIXME:*/SourceRange(Loc),
- ObjectType,
- FirstQualifierInScope);
- if (!NNS) return TemplateName();
-
+ if (SS.getScopeRep()) {
// These apply to the scope specifier, not the template.
ObjectType = QualType();
FirstQualifierInScope = 0;
- }
-
+ }
+
if (!getDerived().AlwaysRebuild() &&
- NNS == DTN->getQualifier() &&
+ SS.getScopeRep() == DTN->getQualifier() &&
ObjectType.isNull())
return Name;
-
+
if (DTN->isIdentifier()) {
- // FIXME: Bad range
- SourceRange QualifierRange(getDerived().getBaseLocation());
- return getDerived().RebuildTemplateName(NNS, QualifierRange,
+ return getDerived().RebuildTemplateName(SS,
*DTN->getIdentifier(),
+ NameLoc,
ObjectType,
FirstQualifierInScope);
}
- return getDerived().RebuildTemplateName(NNS, DTN->getOperator(),
+ return getDerived().RebuildTemplateName(SS, DTN->getOperator(), NameLoc,
ObjectType);
}
-
+
if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
TemplateDecl *TransTemplate
- = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Loc, Template));
+ = cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc,
+ Template));
if (!TransTemplate)
return TemplateName();
-
+
if (!getDerived().AlwaysRebuild() &&
TransTemplate == Template)
return Name;
-
+
return TemplateName(TransTemplate);
}
-
+
if (SubstTemplateTemplateParmPackStorage *SubstPack
- = Name.getAsSubstTemplateTemplateParmPack()) {
+ = Name.getAsSubstTemplateTemplateParmPack()) {
TemplateTemplateParmDecl *TransParam
- = cast_or_null<TemplateTemplateParmDecl>(
- getDerived().TransformDecl(Loc, SubstPack->getParameterPack()));
+ = cast_or_null<TemplateTemplateParmDecl>(
+ getDerived().TransformDecl(NameLoc, SubstPack->getParameterPack()));
if (!TransParam)
return TemplateName();
@@ -2785,12 +2748,25 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc(
break;
case TemplateArgument::Template:
- Output = TemplateArgumentLoc(Arg, SourceRange(), Loc);
- break;
-
- case TemplateArgument::TemplateExpansion:
- Output = TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
+ case TemplateArgument::TemplateExpansion: {
+ NestedNameSpecifierLocBuilder Builder;
+ TemplateName Template = Arg.getAsTemplate();
+ if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
+ Builder.MakeTrivial(SemaRef.Context, DTN->getQualifier(), Loc);
+ else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
+ Builder.MakeTrivial(SemaRef.Context, QTN->getQualifier(), Loc);
+
+ if (Arg.getKind() == TemplateArgument::Template)
+ Output = TemplateArgumentLoc(Arg,
+ Builder.getWithLocInContext(SemaRef.Context),
+ Loc);
+ else
+ Output = TemplateArgumentLoc(Arg,
+ Builder.getWithLocInContext(SemaRef.Context),
+ Loc, Loc);
+
break;
+ }
case TemplateArgument::Expression:
Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
@@ -2849,14 +2825,22 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
}
case TemplateArgument::Template: {
- TemporaryBase Rebase(*this, Input.getLocation(), DeclarationName());
+ NestedNameSpecifierLoc QualifierLoc = Input.getTemplateQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc);
+ if (!QualifierLoc)
+ return true;
+ }
+
+ CXXScopeSpec SS;
+ SS.Adopt(QualifierLoc);
TemplateName Template
- = getDerived().TransformTemplateName(Arg.getAsTemplate());
+ = getDerived().TransformTemplateName(SS, Arg.getAsTemplate(),
+ Input.getTemplateNameLoc());
if (Template.isNull())
return true;
- Output = TemplateArgumentLoc(TemplateArgument(Template),
- Input.getTemplateQualifierRange(),
+ Output = TemplateArgumentLoc(TemplateArgument(Template), QualifierLoc,
Input.getTemplateNameLoc());
return false;
}
@@ -2872,8 +2856,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
Expr *InputExpr = Input.getSourceExpression();
if (!InputExpr) InputExpr = Input.getArgument().getAsExpr();
- ExprResult E
- = getDerived().TransformExpr(InputExpr);
+ ExprResult E = getDerived().TransformExpr(InputExpr);
if (E.isInvalid()) return true;
Output = TemplateArgumentLoc(TemplateArgument(E.take()), E.take());
return false;
@@ -3177,112 +3160,87 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
return Result;
}
-/// \brief Transforms a type that was written in a scope specifier,
-/// given an object type, the results of unqualified lookup, and
-/// an already-instantiated prefix.
-///
-/// The object type is provided iff the scope specifier qualifies the
-/// member of a dependent member-access expression. The prefix is
-/// provided iff the the scope specifier in which this appears has a
-/// prefix.
-///
-/// This is private to TreeTransform.
template<typename Derived>
-QualType
-TreeTransform<Derived>::TransformTypeInObjectScope(QualType T,
- QualType ObjectType,
- NamedDecl *UnqualLookup,
- NestedNameSpecifier *Prefix) {
- if (getDerived().AlreadyTransformed(T))
- return T;
-
- TypeSourceInfo *TSI =
- SemaRef.Context.getTrivialTypeSourceInfo(T, getDerived().getBaseLocation());
-
- TSI = getDerived().TransformTypeInObjectScope(TSI, ObjectType,
- UnqualLookup, Prefix);
- if (!TSI) return QualType();
- return TSI->getType();
-}
-
-template<typename Derived>
-TypeSourceInfo *
-TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSI,
+TypeLoc
+TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL,
QualType ObjectType,
NamedDecl *UnqualLookup,
- NestedNameSpecifier *Prefix) {
- // TODO: in some cases, we might have some verification to do here.
- if (ObjectType.isNull())
- return getDerived().TransformType(TSI);
-
- QualType T = TSI->getType();
+ CXXScopeSpec &SS) {
+ QualType T = TL.getType();
if (getDerived().AlreadyTransformed(T))
- return TSI;
-
+ return TL;
+
TypeLocBuilder TLB;
QualType Result;
-
+
if (isa<TemplateSpecializationType>(T)) {
- TemplateSpecializationTypeLoc TL
- = cast<TemplateSpecializationTypeLoc>(TSI->getTypeLoc());
-
+ TemplateSpecializationTypeLoc SpecTL
+ = cast<TemplateSpecializationTypeLoc>(TL);
+
TemplateName Template =
- getDerived().TransformTemplateName(TL.getTypePtr()->getTemplateName(),
+ getDerived().TransformTemplateName(SS,
+ SpecTL.getTypePtr()->getTemplateName(),
+ SpecTL.getTemplateNameLoc(),
ObjectType, UnqualLookup);
- if (Template.isNull()) return 0;
-
- Result = getDerived()
- .TransformTemplateSpecializationType(TLB, TL, Template);
+ if (Template.isNull())
+ return TypeLoc();
+
+ Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL,
+ Template);
} else if (isa<DependentTemplateSpecializationType>(T)) {
- DependentTemplateSpecializationTypeLoc TL
- = cast<DependentTemplateSpecializationTypeLoc>(TSI->getTypeLoc());
-
- Result = getDerived()
- .TransformDependentTemplateSpecializationType(TLB, TL, Prefix);
+ DependentTemplateSpecializationTypeLoc SpecTL
+ = cast<DependentTemplateSpecializationTypeLoc>(TL);
+
+ TemplateName Template
+ = getDerived().RebuildTemplateName(SS,
+ *SpecTL.getTypePtr()->getIdentifier(),
+ SpecTL.getNameLoc(),
+ ObjectType, UnqualLookup);
+ if (Template.isNull())
+ return TypeLoc();
+
+ Result = getDerived().TransformDependentTemplateSpecializationType(TLB,
+ SpecTL,
+ Template,
+ SS);
} else {
// Nothing special needs to be done for these.
- Result = getDerived().TransformType(TLB, TSI->getTypeLoc());
+ Result = getDerived().TransformType(TLB, TL);
}
-
- if (Result.isNull()) return 0;
- return TLB.getTypeSourceInfo(SemaRef.Context, Result);
+
+ if (Result.isNull())
+ return TypeLoc();
+
+ return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc();
}
template<typename Derived>
-TypeLoc
-TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL,
+TypeSourceInfo *
+TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
QualType ObjectType,
NamedDecl *UnqualLookup,
CXXScopeSpec &SS) {
// FIXME: Painfully copy-paste from the above!
- // TODO: in some cases, we might have some verification to do here.
- if (ObjectType.isNull()) {
- TypeLocBuilder TLB;
- TLB.reserve(TL.getFullDataSize());
- QualType Result = getDerived().TransformType(TLB, TL);
- if (Result.isNull())
- return TypeLoc();
-
- return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc();
- }
-
- QualType T = TL.getType();
+ QualType T = TSInfo->getType();
if (getDerived().AlreadyTransformed(T))
- return TL;
+ return TSInfo;
TypeLocBuilder TLB;
QualType Result;
+ TypeLoc TL = TSInfo->getTypeLoc();
if (isa<TemplateSpecializationType>(T)) {
TemplateSpecializationTypeLoc SpecTL
= cast<TemplateSpecializationTypeLoc>(TL);
- TemplateName Template =
- getDerived().TransformTemplateName(SpecTL.getTypePtr()->getTemplateName(),
+ TemplateName Template
+ = getDerived().TransformTemplateName(SS,
+ SpecTL.getTypePtr()->getTemplateName(),
+ SpecTL.getTemplateNameLoc(),
ObjectType, UnqualLookup);
if (Template.isNull())
- return TypeLoc();
+ return 0;
Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL,
Template);
@@ -3290,18 +3248,27 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL,
DependentTemplateSpecializationTypeLoc SpecTL
= cast<DependentTemplateSpecializationTypeLoc>(TL);
+ TemplateName Template
+ = getDerived().RebuildTemplateName(SS,
+ *SpecTL.getTypePtr()->getIdentifier(),
+ SpecTL.getNameLoc(),
+ ObjectType, UnqualLookup);
+ if (Template.isNull())
+ return 0;
+
Result = getDerived().TransformDependentTemplateSpecializationType(TLB,
- SpecTL,
- SS.getScopeRep());
+ SpecTL,
+ Template,
+ SS);
} else {
// Nothing special needs to be done for these.
Result = getDerived().TransformType(TLB, TL);
}
if (Result.isNull())
- return TypeLoc();
+ return 0;
- return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc();
+ return TLB.getTypeSourceInfo(SemaRef.Context, Result);
}
template <class TyLoc> static inline
@@ -3438,23 +3405,34 @@ template<typename Derived>
QualType
TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
MemberPointerTypeLoc TL) {
- const MemberPointerType *T = TL.getTypePtr();
-
QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
if (PointeeType.isNull())
return QualType();
- // TODO: preserve source information for this.
- QualType ClassType
- = getDerived().TransformType(QualType(T->getClass(), 0));
- if (ClassType.isNull())
- return QualType();
+ TypeSourceInfo* OldClsTInfo = TL.getClassTInfo();
+ TypeSourceInfo* NewClsTInfo = 0;
+ if (OldClsTInfo) {
+ NewClsTInfo = getDerived().TransformType(OldClsTInfo);
+ if (!NewClsTInfo)
+ return QualType();
+ }
+
+ const MemberPointerType *T = TL.getTypePtr();
+ QualType OldClsType = QualType(T->getClass(), 0);
+ QualType NewClsType;
+ if (NewClsTInfo)
+ NewClsType = NewClsTInfo->getType();
+ else {
+ NewClsType = getDerived().TransformType(OldClsType);
+ if (NewClsType.isNull())
+ return QualType();
+ }
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
PointeeType != T->getPointeeType() ||
- ClassType != QualType(T->getClass(), 0)) {
- Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType,
+ NewClsType != OldClsType) {
+ Result = getDerived().RebuildMemberPointerType(PointeeType, NewClsType,
TL.getStarLoc());
if (Result.isNull())
return QualType();
@@ -3462,6 +3440,7 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result);
NewTL.setSigilLoc(TL.getSigilLoc());
+ NewTL.setClassTInfo(NewClsTInfo);
return Result;
}
@@ -3707,6 +3686,7 @@ QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
template<typename Derived>
ParmVarDecl *
TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm,
+ int indexAdjustment,
llvm::Optional<unsigned> NumExpansions) {
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
TypeSourceInfo *NewDI = 0;
@@ -3741,18 +3721,22 @@ TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm,
if (!NewDI)
return 0;
- if (NewDI == OldDI)
+ if (NewDI == OldDI && indexAdjustment == 0)
return OldParm;
- else
- return ParmVarDecl::Create(SemaRef.Context,
- OldParm->getDeclContext(),
- OldParm->getLocation(),
- OldParm->getIdentifier(),
- NewDI->getType(),
- NewDI,
- OldParm->getStorageClass(),
- OldParm->getStorageClassAsWritten(),
- /* DefArg */ NULL);
+
+ ParmVarDecl *newParm = ParmVarDecl::Create(SemaRef.Context,
+ OldParm->getDeclContext(),
+ OldParm->getInnerLocStart(),
+ OldParm->getLocation(),
+ OldParm->getIdentifier(),
+ NewDI->getType(),
+ NewDI,
+ OldParm->getStorageClass(),
+ OldParm->getStorageClassAsWritten(),
+ /* DefArg */ NULL);
+ newParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
+ OldParm->getFunctionScopeIndex() + indexAdjustment);
+ return newParm;
}
template<typename Derived>
@@ -3762,9 +3746,14 @@ bool TreeTransform<Derived>::
const QualType *ParamTypes,
llvm::SmallVectorImpl<QualType> &OutParamTypes,
llvm::SmallVectorImpl<ParmVarDecl*> *PVars) {
+ int indexAdjustment = 0;
+
for (unsigned i = 0; i != NumParams; ++i) {
if (ParmVarDecl *OldParm = Params[i]) {
+ assert(OldParm->getFunctionScopeIndex() == i);
+
llvm::Optional<unsigned> NumExpansions;
+ ParmVarDecl *NewParm = 0;
if (OldParm->isParameterPack()) {
// We have a function parameter pack that may need to be expanded.
llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
@@ -3774,7 +3763,8 @@ bool TreeTransform<Derived>::
PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(TL);
TypeLoc Pattern = ExpansionTL.getPatternLoc();
SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded);
-
+ assert(Unexpanded.size() > 0 && "Could not find parameter packs!");
+
// Determine whether we should expand the parameter packs.
bool ShouldExpand = false;
bool RetainExpansion = false;
@@ -3799,6 +3789,7 @@ bool TreeTransform<Derived>::
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
ParmVarDecl *NewParm
= getDerived().TransformFunctionTypeParam(OldParm,
+ indexAdjustment++,
OrigNumExpansions);
if (!NewParm)
return true;
@@ -3814,6 +3805,7 @@ bool TreeTransform<Derived>::
ForgetPartiallySubstitutedPackRAII Forget(getDerived());
ParmVarDecl *NewParm
= getDerived().TransformFunctionTypeParam(OldParm,
+ indexAdjustment++,
OrigNumExpansions);
if (!NewParm)
return true;
@@ -3823,17 +3815,28 @@ bool TreeTransform<Derived>::
PVars->push_back(NewParm);
}
+ // The next parameter should have the same adjustment as the
+ // last thing we pushed, but we post-incremented indexAdjustment
+ // on every push. Also, if we push nothing, the adjustment should
+ // go down by one.
+ indexAdjustment--;
+
// We're done with the pack expansion.
continue;
}
// We'll substitute the parameter now without expanding the pack
// expansion.
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+ NewParm = getDerived().TransformFunctionTypeParam(OldParm,
+ indexAdjustment,
+ NumExpansions);
+ } else {
+ NewParm = getDerived().TransformFunctionTypeParam(OldParm,
+ indexAdjustment,
+ llvm::Optional<unsigned>());
}
-
- Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
- ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm,
- NumExpansions);
+
if (!NewParm)
return true;
@@ -3848,6 +3851,7 @@ bool TreeTransform<Derived>::
QualType OldType = ParamTypes[i];
bool IsPackExpansion = false;
llvm::Optional<unsigned> NumExpansions;
+ QualType NewType;
if (const PackExpansionType *Expansion
= dyn_cast<PackExpansionType>(OldType)) {
// We have a function parameter pack that may need to be expanded.
@@ -3902,10 +3906,12 @@ bool TreeTransform<Derived>::
// expansion.
OldType = Expansion->getPattern();
IsPackExpansion = true;
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+ NewType = getDerived().TransformType(OldType);
+ } else {
+ NewType = getDerived().TransformType(OldType);
}
- Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
- QualType NewType = getDerived().TransformType(OldType);
if (NewType.isNull())
return true;
@@ -3918,8 +3924,16 @@ bool TreeTransform<Derived>::
PVars->push_back(0);
}
- return false;
+#ifndef NDEBUG
+ if (PVars) {
+ for (unsigned i = 0, e = PVars->size(); i != e; ++i)
+ if (ParmVarDecl *parm = (*PVars)[i])
+ assert(parm->getFunctionScopeIndex() == i);
}
+#endif
+
+ return false;
+}
template<typename Derived>
QualType
@@ -3983,8 +3997,8 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
}
FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result);
- NewTL.setLParenLoc(TL.getLParenLoc());
- NewTL.setRParenLoc(TL.getRParenLoc());
+ NewTL.setLocalRangeBegin(TL.getLocalRangeBegin());
+ NewTL.setLocalRangeEnd(TL.getLocalRangeEnd());
NewTL.setTrailingReturn(TL.getTrailingReturn());
for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i)
NewTL.setArg(i, ParamDecls[i]);
@@ -4007,8 +4021,8 @@ QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
Result = getDerived().RebuildFunctionNoProtoType(ResultType);
FunctionNoProtoTypeLoc NewTL = TLB.push<FunctionNoProtoTypeLoc>(Result);
- NewTL.setLParenLoc(TL.getLParenLoc());
- NewTL.setRParenLoc(TL.getRParenLoc());
+ NewTL.setLocalRangeBegin(TL.getLocalRangeBegin());
+ NewTL.setLocalRangeEnd(TL.getLocalRangeEnd());
NewTL.setTrailingReturn(false);
return Result;
@@ -4041,9 +4055,9 @@ template<typename Derived>
QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
TypedefTypeLoc TL) {
const TypedefType *T = TL.getTypePtr();
- TypedefDecl *Typedef
- = cast_or_null<TypedefDecl>(getDerived().TransformDecl(TL.getNameLoc(),
- T->getDecl()));
+ TypedefNameDecl *Typedef
+ = cast_or_null<TypedefNameDecl>(getDerived().TransformDecl(TL.getNameLoc(),
+ T->getDecl()));
if (!Typedef)
return QualType();
@@ -4236,7 +4250,28 @@ template<typename Derived>
QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
TypeLocBuilder &TLB,
SubstTemplateTypeParmTypeLoc TL) {
- return TransformTypeSpecType(TLB, TL);
+ const SubstTemplateTypeParmType *T = TL.getTypePtr();
+
+ // Substitute into the replacement type, which itself might involve something
+ // that needs to be transformed. This only tends to occur with default
+ // template arguments of template template parameters.
+ TemporaryBase Rebase(*this, TL.getNameLoc(), DeclarationName());
+ QualType Replacement = getDerived().TransformType(T->getReplacementType());
+ if (Replacement.isNull())
+ return QualType();
+
+ // Always canonicalize the replacement type.
+ Replacement = SemaRef.Context.getCanonicalType(Replacement);
+ QualType Result
+ = SemaRef.Context.getSubstTemplateTypeParmType(T->getReplacedParameter(),
+ Replacement);
+
+ // Propagate type-source information.
+ SubstTemplateTypeParmTypeLoc NewTL
+ = TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
+
}
template<typename Derived>
@@ -4252,8 +4287,12 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
TemplateSpecializationTypeLoc TL) {
const TemplateSpecializationType *T = TL.getTypePtr();
+ // The nested-name-specifier never matters in a TemplateSpecializationType,
+ // because we can't have a dependent nested-name-specifier anyway.
+ CXXScopeSpec SS;
TemplateName Template
- = getDerived().TransformTemplateName(T->getTemplateName());
+ = getDerived().TransformTemplateName(SS, T->getTemplateName(),
+ TL.getTemplateNameLoc());
if (Template.isNull())
return QualType();
@@ -4362,18 +4401,76 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
return Result;
}
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType(
+ TypeLocBuilder &TLB,
+ DependentTemplateSpecializationTypeLoc TL,
+ TemplateName Template,
+ CXXScopeSpec &SS) {
+ TemplateArgumentListInfo NewTemplateArgs;
+ NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
+ NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
+ typedef TemplateArgumentLocContainerIterator<
+ DependentTemplateSpecializationTypeLoc> ArgIterator;
+ if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0),
+ ArgIterator(TL, TL.getNumArgs()),
+ NewTemplateArgs))
+ return QualType();
+
+ // FIXME: maybe don't rebuild if all the template arguments are the same.
+
+ if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
+ QualType Result
+ = getSema().Context.getDependentTemplateSpecializationType(
+ TL.getTypePtr()->getKeyword(),
+ DTN->getQualifier(),
+ DTN->getIdentifier(),
+ NewTemplateArgs);
+
+ DependentTemplateSpecializationTypeLoc NewTL
+ = TLB.push<DependentTemplateSpecializationTypeLoc>(Result);
+ NewTL.setKeywordLoc(TL.getKeywordLoc());
+
+ NewTL.setQualifierLoc(SS.getWithLocInContext(SemaRef.Context));
+ NewTL.setNameLoc(TL.getNameLoc());
+ NewTL.setLAngleLoc(TL.getLAngleLoc());
+ NewTL.setRAngleLoc(TL.getRAngleLoc());
+ for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i)
+ NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo());
+ return Result;
+ }
+
+ QualType Result
+ = getDerived().RebuildTemplateSpecializationType(Template,
+ TL.getNameLoc(),
+ NewTemplateArgs);
+
+ if (!Result.isNull()) {
+ /// FIXME: Wrap this in an elaborated-type-specifier?
+ TemplateSpecializationTypeLoc NewTL
+ = TLB.push<TemplateSpecializationTypeLoc>(Result);
+ NewTL.setTemplateNameLoc(TL.getNameLoc());
+ NewTL.setLAngleLoc(TL.getLAngleLoc());
+ NewTL.setRAngleLoc(TL.getRAngleLoc());
+ for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i)
+ NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo());
+ }
+
+ return Result;
+}
+
template<typename Derived>
QualType
TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
ElaboratedTypeLoc TL) {
const ElaboratedType *T = TL.getTypePtr();
- NestedNameSpecifier *NNS = 0;
+ NestedNameSpecifierLoc QualifierLoc;
// NOTE: the qualifier in an ElaboratedType is optional.
- if (T->getQualifier() != 0) {
- NNS = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
- TL.getQualifierRange());
- if (!NNS)
+ if (TL.getQualifierLoc()) {
+ QualifierLoc
+ = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc());
+ if (!QualifierLoc)
return QualType();
}
@@ -4383,18 +4480,18 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
- NNS != T->getQualifier() ||
+ QualifierLoc != TL.getQualifierLoc() ||
NamedT != T->getNamedType()) {
Result = getDerived().RebuildElaboratedType(TL.getKeywordLoc(),
- T->getKeyword(), NNS, NamedT);
+ T->getKeyword(),
+ QualifierLoc, NamedT);
if (Result.isNull())
return QualType();
}
ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
NewTL.setKeywordLoc(TL.getKeywordLoc());
- NewTL.setQualifierRange(TL.getQualifierRange());
-
+ NewTL.setQualifierLoc(QualifierLoc);
return Result;
}
@@ -4462,17 +4559,16 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB,
DependentNameTypeLoc TL) {
const DependentNameType *T = TL.getTypePtr();
- NestedNameSpecifier *NNS
- = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
- TL.getQualifierRange());
- if (!NNS)
+ NestedNameSpecifierLoc QualifierLoc
+ = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc());
+ if (!QualifierLoc)
return QualType();
QualType Result
- = getDerived().RebuildDependentNameType(T->getKeyword(), NNS,
- T->getIdentifier(),
+ = getDerived().RebuildDependentNameType(T->getKeyword(),
TL.getKeywordLoc(),
- TL.getQualifierRange(),
+ QualifierLoc,
+ T->getIdentifier(),
TL.getNameLoc());
if (Result.isNull())
return QualType();
@@ -4483,11 +4579,11 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB,
ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
NewTL.setKeywordLoc(TL.getKeywordLoc());
- NewTL.setQualifierRange(TL.getQualifierRange());
+ NewTL.setQualifierLoc(QualifierLoc);
} else {
DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result);
NewTL.setKeywordLoc(TL.getKeywordLoc());
- NewTL.setQualifierRange(TL.getQualifierRange());
+ NewTL.setQualifierLoc(QualifierLoc);
NewTL.setNameLoc(TL.getNameLoc());
}
return Result;
@@ -4497,65 +4593,79 @@ template<typename Derived>
QualType TreeTransform<Derived>::
TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
DependentTemplateSpecializationTypeLoc TL) {
- const DependentTemplateSpecializationType *T = TL.getTypePtr();
-
- NestedNameSpecifier *NNS
- = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
- TL.getQualifierRange());
- if (!NNS)
- return QualType();
-
+ NestedNameSpecifierLoc QualifierLoc;
+ if (TL.getQualifierLoc()) {
+ QualifierLoc
+ = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc());
+ if (!QualifierLoc)
+ return QualType();
+ }
+
return getDerived()
- .TransformDependentTemplateSpecializationType(TLB, TL, NNS);
+ .TransformDependentTemplateSpecializationType(TLB, TL, QualifierLoc);
}
template<typename Derived>
QualType TreeTransform<Derived>::
- TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
- DependentTemplateSpecializationTypeLoc TL,
- NestedNameSpecifier *NNS) {
+TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
+ DependentTemplateSpecializationTypeLoc TL,
+ NestedNameSpecifierLoc QualifierLoc) {
const DependentTemplateSpecializationType *T = TL.getTypePtr();
-
+
TemplateArgumentListInfo NewTemplateArgs;
NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
-
- // FIXME: Nested-name-specifier source location info!
+
typedef TemplateArgumentLocContainerIterator<
- DependentTemplateSpecializationTypeLoc> ArgIterator;
+ DependentTemplateSpecializationTypeLoc> ArgIterator;
if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0),
ArgIterator(TL, TL.getNumArgs()),
NewTemplateArgs))
return QualType();
-
+
QualType Result
= getDerived().RebuildDependentTemplateSpecializationType(T->getKeyword(),
- NNS,
- TL.getQualifierRange(),
+ QualifierLoc,
T->getIdentifier(),
- TL.getNameLoc(),
- NewTemplateArgs);
+ TL.getNameLoc(),
+ NewTemplateArgs);
if (Result.isNull())
return QualType();
-
+
if (const ElaboratedType *ElabT = dyn_cast<ElaboratedType>(Result)) {
QualType NamedT = ElabT->getNamedType();
-
+
// Copy information relevant to the template specialization.
TemplateSpecializationTypeLoc NamedTL
= TLB.push<TemplateSpecializationTypeLoc>(NamedT);
+ NamedTL.setTemplateNameLoc(TL.getNameLoc());
NamedTL.setLAngleLoc(TL.getLAngleLoc());
NamedTL.setRAngleLoc(TL.getRAngleLoc());
- for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
- NamedTL.setArgLocInfo(I, TL.getArgLocInfo(I));
-
+ for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I)
+ NamedTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo());
+
// Copy information relevant to the elaborated type.
ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
NewTL.setKeywordLoc(TL.getKeywordLoc());
- NewTL.setQualifierRange(TL.getQualifierRange());
+ NewTL.setQualifierLoc(QualifierLoc);
+ } else if (isa<DependentTemplateSpecializationType>(Result)) {
+ DependentTemplateSpecializationTypeLoc SpecTL
+ = TLB.push<DependentTemplateSpecializationTypeLoc>(Result);
+ SpecTL.setKeywordLoc(TL.getKeywordLoc());
+ SpecTL.setQualifierLoc(QualifierLoc);
+ SpecTL.setNameLoc(TL.getNameLoc());
+ SpecTL.setLAngleLoc(TL.getLAngleLoc());
+ SpecTL.setRAngleLoc(TL.getRAngleLoc());
+ for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I)
+ SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo());
} else {
- TypeLoc NewTL(Result, TL.getOpaqueData());
- TLB.pushFullCopy(NewTL);
+ TemplateSpecializationTypeLoc SpecTL
+ = TLB.push<TemplateSpecializationTypeLoc>(Result);
+ SpecTL.setTemplateNameLoc(TL.getNameLoc());
+ SpecTL.setLAngleLoc(TL.getLAngleLoc());
+ SpecTL.setRAngleLoc(TL.getRAngleLoc());
+ for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I)
+ SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo());
}
return Result;
}
@@ -5304,8 +5414,9 @@ TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
return StmtError();
Var = getDerived().RebuildExceptionDecl(ExceptionDecl, T,
- ExceptionDecl->getIdentifier(),
- ExceptionDecl->getLocation());
+ ExceptionDecl->getInnerLocStart(),
+ ExceptionDecl->getLocation(),
+ ExceptionDecl->getIdentifier());
if (!Var || Var->isInvalidDecl())
return StmtError();
}
@@ -5356,6 +5467,112 @@ TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
move_arg(Handlers));
}
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
+ StmtResult Range = getDerived().TransformStmt(S->getRangeStmt());
+ if (Range.isInvalid())
+ return StmtError();
+
+ StmtResult BeginEnd = getDerived().TransformStmt(S->getBeginEndStmt());
+ if (BeginEnd.isInvalid())
+ return StmtError();
+
+ ExprResult Cond = getDerived().TransformExpr(S->getCond());
+ if (Cond.isInvalid())
+ return StmtError();
+
+ ExprResult Inc = getDerived().TransformExpr(S->getInc());
+ if (Inc.isInvalid())
+ return StmtError();
+
+ StmtResult LoopVar = getDerived().TransformStmt(S->getLoopVarStmt());
+ if (LoopVar.isInvalid())
+ return StmtError();
+
+ StmtResult NewStmt = S;
+ if (getDerived().AlwaysRebuild() ||
+ Range.get() != S->getRangeStmt() ||
+ BeginEnd.get() != S->getBeginEndStmt() ||
+ Cond.get() != S->getCond() ||
+ Inc.get() != S->getInc() ||
+ LoopVar.get() != S->getLoopVarStmt())
+ NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(),
+ S->getColonLoc(), Range.get(),
+ BeginEnd.get(), Cond.get(),
+ Inc.get(), LoopVar.get(),
+ S->getRParenLoc());
+
+ StmtResult Body = getDerived().TransformStmt(S->getBody());
+ if (Body.isInvalid())
+ return StmtError();
+
+ // Body has changed but we didn't rebuild the for-range statement. Rebuild
+ // it now so we have a new statement to attach the body to.
+ if (Body.get() != S->getBody() && NewStmt.get() == S)
+ NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(),
+ S->getColonLoc(), Range.get(),
+ BeginEnd.get(), Cond.get(),
+ Inc.get(), LoopVar.get(),
+ S->getRParenLoc());
+
+ if (NewStmt.get() == S)
+ return SemaRef.Owned(S);
+
+ return FinishCXXForRangeStmt(NewStmt.get(), Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) {
+ StmtResult TryBlock; // = getDerived().TransformCompoundStmt(S->getTryBlock());
+ if(TryBlock.isInvalid()) return StmtError();
+
+ StmtResult Handler = getDerived().TransformSEHHandler(S->getHandler());
+ if(!getDerived().AlwaysRebuild() &&
+ TryBlock.get() == S->getTryBlock() &&
+ Handler.get() == S->getHandler())
+ return SemaRef.Owned(S);
+
+ return getDerived().RebuildSEHTryStmt(S->getIsCXXTry(),
+ S->getTryLoc(),
+ TryBlock.take(),
+ Handler.take());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformSEHFinallyStmt(SEHFinallyStmt *S) {
+ StmtResult Block; // = getDerived().TransformCompoundStatement(S->getBlock());
+ if(Block.isInvalid()) return StmtError();
+
+ return getDerived().RebuildSEHFinallyStmt(S->getFinallyLoc(),
+ Block.take());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformSEHExceptStmt(SEHExceptStmt *S) {
+ ExprResult FilterExpr = getDerived().TransformExpr(S->getFilterExpr());
+ if(FilterExpr.isInvalid()) return StmtError();
+
+ StmtResult Block; // = getDerived().TransformCompoundStatement(S->getBlock());
+ if(Block.isInvalid()) return StmtError();
+
+ return getDerived().RebuildSEHExceptStmt(S->getExceptLoc(),
+ FilterExpr.take(),
+ Block.take());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformSEHHandler(Stmt *Handler) {
+ if(isa<SEHFinallyStmt>(Handler))
+ return getDerived().TransformSEHFinallyStmt(cast<SEHFinallyStmt>(Handler));
+ else
+ return getDerived().TransformSEHExceptStmt(cast<SEHExceptStmt>(Handler));
+}
+
//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//
@@ -5368,11 +5585,11 @@ TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
- NestedNameSpecifier *Qualifier = 0;
- if (E->getQualifier()) {
- Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange());
- if (!Qualifier)
+ NestedNameSpecifierLoc QualifierLoc;
+ if (E->getQualifierLoc()) {
+ QualifierLoc
+ = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
+ if (!QualifierLoc)
return ExprError();
}
@@ -5390,7 +5607,7 @@ TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
}
if (!getDerived().AlwaysRebuild() &&
- Qualifier == E->getQualifier() &&
+ QualifierLoc == E->getQualifierLoc() &&
ND == E->getDecl() &&
NameInfo.getName() == E->getDecl()->getDeclName() &&
!E->hasExplicitTemplateArgs()) {
@@ -5413,8 +5630,8 @@ TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
return ExprError();
}
- return getDerived().RebuildDeclRefExpr(Qualifier, E->getQualifierRange(),
- ND, NameInfo, TemplateArgs);
+ return getDerived().RebuildDeclRefExpr(QualifierLoc, ND, NameInfo,
+ TemplateArgs);
}
template<typename Derived>
@@ -5449,6 +5666,42 @@ TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) {
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) {
+ ExprResult ControllingExpr =
+ getDerived().TransformExpr(E->getControllingExpr());
+ if (ControllingExpr.isInvalid())
+ return ExprError();
+
+ llvm::SmallVector<Expr *, 4> AssocExprs;
+ llvm::SmallVector<TypeSourceInfo *, 4> AssocTypes;
+ for (unsigned i = 0; i != E->getNumAssocs(); ++i) {
+ TypeSourceInfo *TS = E->getAssocTypeSourceInfo(i);
+ if (TS) {
+ TypeSourceInfo *AssocType = getDerived().TransformType(TS);
+ if (!AssocType)
+ return ExprError();
+ AssocTypes.push_back(AssocType);
+ } else {
+ AssocTypes.push_back(0);
+ }
+
+ ExprResult AssocExpr = getDerived().TransformExpr(E->getAssocExpr(i));
+ if (AssocExpr.isInvalid())
+ return ExprError();
+ AssocExprs.push_back(AssocExpr.release());
+ }
+
+ return getDerived().RebuildGenericSelectionExpr(E->getGenericLoc(),
+ E->getDefaultLoc(),
+ E->getRParenLoc(),
+ ControllingExpr.release(),
+ AssocTypes.data(),
+ AssocExprs.data(),
+ E->getNumAssocs());
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) {
ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
if (SubExpr.isInvalid())
@@ -5498,8 +5751,8 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
const Node &ON = E->getComponent(I);
Component Comp;
Comp.isBrackets = true;
- Comp.LocStart = ON.getRange().getBegin();
- Comp.LocEnd = ON.getRange().getEnd();
+ Comp.LocStart = ON.getSourceRange().getBegin();
+ Comp.LocEnd = ON.getSourceRange().getEnd();
switch (ON.getKind()) {
case Node::Array: {
Expr *FromIndex = E->getIndexExpr(ON.getArrayExprIndex());
@@ -5552,7 +5805,8 @@ TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) {
template<typename Derived>
ExprResult
-TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr(
+ UnaryExprOrTypeTraitExpr *E) {
if (E->isArgumentType()) {
TypeSourceInfo *OldT = E->getArgumentTypeInfo();
@@ -5563,9 +5817,9 @@ TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
if (!getDerived().AlwaysRebuild() && OldT == NewT)
return SemaRef.Owned(E);
- return getDerived().RebuildSizeOfAlignOf(NewT, E->getOperatorLoc(),
- E->isSizeOf(),
- E->getSourceRange());
+ return getDerived().RebuildUnaryExprOrTypeTrait(NewT, E->getOperatorLoc(),
+ E->getKind(),
+ E->getSourceRange());
}
ExprResult SubExpr;
@@ -5583,9 +5837,10 @@ TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
return SemaRef.Owned(E);
}
- return getDerived().RebuildSizeOfAlignOf(SubExpr.get(), E->getOperatorLoc(),
- E->isSizeOf(),
- E->getSourceRange());
+ return getDerived().RebuildUnaryExprOrTypeTrait(SubExpr.get(),
+ E->getOperatorLoc(),
+ E->getKind(),
+ E->getSourceRange());
}
template<typename Derived>
@@ -5646,12 +5901,12 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
if (Base.isInvalid())
return ExprError();
- NestedNameSpecifier *Qualifier = 0;
+ NestedNameSpecifierLoc QualifierLoc;
if (E->hasQualifier()) {
- Qualifier
- = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange());
- if (Qualifier == 0)
+ QualifierLoc
+ = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
+
+ if (!QualifierLoc)
return ExprError();
}
@@ -5673,7 +5928,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase() &&
- Qualifier == E->getQualifier() &&
+ QualifierLoc == E->getQualifierLoc() &&
Member == E->getMemberDecl() &&
FoundDecl == E->getFoundDecl() &&
!E->hasExplicitTemplateArgs()) {
@@ -5706,8 +5961,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
return getDerived().RebuildMemberExpr(Base.get(), FakeOperatorLoc,
E->isArrow(),
- Qualifier,
- E->getQualifierRange(),
+ QualifierLoc,
E->getMemberNameInfo(),
Member,
FoundDecl,
@@ -6333,7 +6587,7 @@ TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) {
TInfo == E->getTypeOperandSourceInfo())
return SemaRef.Owned(E);
- return getDerived().RebuildCXXTypeidExpr(E->getType(),
+ return getDerived().RebuildCXXUuidofExpr(E->getType(),
E->getLocStart(),
TInfo,
E->getLocEnd());
@@ -6623,8 +6877,7 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
if (E->getDestroyedTypeInfo()) {
TypeSourceInfo *DestroyedTypeInfo
= getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(),
- ObjectType, 0,
- QualifierLoc.getNestedNameSpecifier());
+ ObjectType, 0, SS);
if (!DestroyedTypeInfo)
return ExprError();
Destroyed = DestroyedTypeInfo;
@@ -6670,8 +6923,6 @@ template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformUnresolvedLookupExpr(
UnresolvedLookupExpr *Old) {
- TemporaryBase Rebase(*this, Old->getNameLoc(), DeclarationName());
-
LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(),
Sema::LookupOrdinaryName);
@@ -6708,14 +6959,13 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
// Rebuild the nested-name qualifier, if present.
CXXScopeSpec SS;
- NestedNameSpecifier *Qualifier = 0;
- if (Old->getQualifier()) {
- Qualifier = getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
- Old->getQualifierRange());
- if (!Qualifier)
+ if (Old->getQualifierLoc()) {
+ NestedNameSpecifierLoc QualifierLoc
+ = getDerived().TransformNestedNameSpecifierLoc(Old->getQualifierLoc());
+ if (!QualifierLoc)
return ExprError();
- SS.MakeTrivial(SemaRef.Context, Qualifier, Old->getQualifierRange());
+ SS.Adopt(QualifierLoc);
}
if (Old->getNamingClass()) {
@@ -6785,6 +7035,53 @@ TreeTransform<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
+ TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo());
+ if (!T)
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ T == E->getQueriedTypeSourceInfo())
+ return SemaRef.Owned(E);
+
+ ExprResult SubExpr;
+ {
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+ SubExpr = getDerived().TransformExpr(E->getDimensionExpression());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getDimensionExpression())
+ return SemaRef.Owned(E);
+ }
+
+ return getDerived().RebuildArrayTypeTrait(E->getTrait(),
+ E->getLocStart(),
+ T,
+ SubExpr.get(),
+ E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformExpressionTraitExpr(ExpressionTraitExpr *E) {
+ ExprResult SubExpr;
+ {
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+ SubExpr = getDerived().TransformExpr(E->getQueriedExpression());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getQueriedExpression())
+ return SemaRef.Owned(E);
+ }
+
+ return getDerived().RebuildExpressionTrait(
+ E->getTrait(), E->getLocStart(), SubExpr.get(), E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *E) {
NestedNameSpecifierLoc QualifierLoc
@@ -6994,16 +7291,16 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
// the member name.
NamedDecl *FirstQualifierInScope
= getDerived().TransformFirstQualifierInScope(
- E->getFirstQualifierFoundInScope(),
- E->getQualifierRange().getBegin());
+ E->getFirstQualifierFoundInScope(),
+ E->getQualifierLoc().getBeginLoc());
- NestedNameSpecifier *Qualifier = 0;
+ NestedNameSpecifierLoc QualifierLoc;
if (E->getQualifier()) {
- Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange(),
- ObjectType,
- FirstQualifierInScope);
- if (!Qualifier)
+ QualifierLoc
+ = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc(),
+ ObjectType,
+ FirstQualifierInScope);
+ if (!QualifierLoc)
return ExprError();
}
@@ -7022,7 +7319,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
if (!getDerived().AlwaysRebuild() &&
Base.get() == OldBase &&
BaseType == E->getBaseType() &&
- Qualifier == E->getQualifier() &&
+ QualifierLoc == E->getQualifierLoc() &&
NameInfo.getName() == E->getMember() &&
FirstQualifierInScope == E->getFirstQualifierFoundInScope())
return SemaRef.Owned(E);
@@ -7031,8 +7328,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
BaseType,
E->isArrow(),
E->getOperatorLoc(),
- Qualifier,
- E->getQualifierRange(),
+ QualifierLoc,
FirstQualifierInScope,
NameInfo,
/*TemplateArgs*/ 0);
@@ -7048,8 +7344,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
BaseType,
E->isArrow(),
E->getOperatorLoc(),
- Qualifier,
- E->getQualifierRange(),
+ QualifierLoc,
FirstQualifierInScope,
NameInfo,
&TransArgs);
@@ -7070,12 +7365,11 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
BaseType = getDerived().TransformType(Old->getBaseType());
}
- NestedNameSpecifier *Qualifier = 0;
- if (Old->getQualifier()) {
- Qualifier
- = getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
- Old->getQualifierRange());
- if (Qualifier == 0)
+ NestedNameSpecifierLoc QualifierLoc;
+ if (Old->getQualifierLoc()) {
+ QualifierLoc
+ = getDerived().TransformNestedNameSpecifierLoc(Old->getQualifierLoc());
+ if (!QualifierLoc)
return ExprError();
}
@@ -7093,8 +7387,10 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
// This can happen because of dependent hiding.
if (isa<UsingShadowDecl>(*I))
continue;
- else
+ else {
+ R.clear();
return ExprError();
+ }
}
// Expand using declarations.
@@ -7143,8 +7439,7 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
BaseType,
Old->getOperatorLoc(),
Old->isArrow(),
- Qualifier,
- Old->getQualifierRange(),
+ QualifierLoc,
FirstQualifierInScope,
R,
(Old->hasExplicitTemplateArgs()
@@ -7490,8 +7785,6 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {
- NestedNameSpecifier *Qualifier = 0;
-
ValueDecl *ND
= cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getLocation(),
E->getDecl()));
@@ -7508,7 +7801,7 @@ TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {
}
DeclarationNameInfo NameInfo(E->getDecl()->getDeclName(), E->getLocation());
- return getDerived().RebuildDeclRefExpr(Qualifier, SourceLocation(),
+ return getDerived().RebuildDeclRefExpr(NestedNameSpecifierLoc(),
ND, NameInfo, 0);
}
@@ -7720,88 +8013,33 @@ template<typename Derived>
QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
TemplateName Template,
SourceLocation TemplateNameLoc,
- const TemplateArgumentListInfo &TemplateArgs) {
+ TemplateArgumentListInfo &TemplateArgs) {
return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
}
template<typename Derived>
-NestedNameSpecifier *
-TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
- SourceRange Range,
- IdentifierInfo &II,
- QualType ObjectType,
- NamedDecl *FirstQualifierInScope) {
- CXXScopeSpec SS;
- // FIXME: The source location information is all wrong.
- SS.MakeTrivial(SemaRef.Context, Prefix, Range);
- if (SemaRef.BuildCXXNestedNameSpecifier(0, II, /*FIXME:*/Range.getBegin(),
- /*FIXME:*/Range.getEnd(),
- ObjectType, false,
- SS, FirstQualifierInScope,
- false))
- return 0;
-
- return SS.getScopeRep();
-}
-
-template<typename Derived>
-NestedNameSpecifier *
-TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
- SourceRange Range,
- NamespaceDecl *NS) {
- return NestedNameSpecifier::Create(SemaRef.Context, Prefix, NS);
-}
-
-template<typename Derived>
-NestedNameSpecifier *
-TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
- SourceRange Range,
- NamespaceAliasDecl *Alias) {
- return NestedNameSpecifier::Create(SemaRef.Context, Prefix, Alias);
-}
-
-template<typename Derived>
-NestedNameSpecifier *
-TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
- SourceRange Range,
- bool TemplateKW,
- QualType T) {
- if (T->isDependentType() || T->isRecordType() ||
- (SemaRef.getLangOptions().CPlusPlus0x && T->isEnumeralType())) {
- assert(!T.hasLocalQualifiers() && "Can't get cv-qualifiers here");
- return NestedNameSpecifier::Create(SemaRef.Context, Prefix, TemplateKW,
- T.getTypePtr());
- }
-
- SemaRef.Diag(Range.getBegin(), diag::err_nested_name_spec_non_tag) << T;
- return 0;
-}
-
-template<typename Derived>
TemplateName
-TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
bool TemplateKW,
TemplateDecl *Template) {
- return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW,
+ return SemaRef.Context.getQualifiedTemplateName(SS.getScopeRep(), TemplateKW,
Template);
}
template<typename Derived>
TemplateName
-TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
- const IdentifierInfo &II,
+TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
+ const IdentifierInfo &Name,
+ SourceLocation NameLoc,
QualType ObjectType,
NamedDecl *FirstQualifierInScope) {
- CXXScopeSpec SS;
- SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
- UnqualifiedId Name;
- Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation());
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(&Name, NameLoc);
Sema::TemplateTy Template;
getSema().ActOnDependentTemplateName(/*Scope=*/0,
- /*FIXME:*/getDerived().getBaseLocation(),
+ /*FIXME:*/SourceLocation(),
SS,
- Name,
+ TemplateName,
ParsedType::make(ObjectType),
/*EnteringContext=*/false,
Template);
@@ -7810,18 +8048,17 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
template<typename Derived>
TemplateName
-TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
OverloadedOperatorKind Operator,
+ SourceLocation NameLoc,
QualType ObjectType) {
- CXXScopeSpec SS;
- SS.MakeTrivial(SemaRef.Context, Qualifier, SourceRange(getDerived().getBaseLocation()));
UnqualifiedId Name;
- SourceLocation SymbolLocations[3]; // FIXME: Bogus location information.
- Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(),
- Operator, SymbolLocations);
+ // FIXME: Bogus location information.
+ SourceLocation SymbolLocations[3] = { NameLoc, NameLoc, NameLoc };
+ Name.setOperatorFunctionId(NameLoc, Operator, SymbolLocations);
Sema::TemplateTy Template;
getSema().ActOnDependentTemplateName(/*Scope=*/0,
- /*FIXME:*/getDerived().getBaseLocation(),
+ /*FIXME:*/SourceLocation(),
SS,
Name,
ParsedType::make(ObjectType),
diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
index 1e0a7c4..3570737 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
@@ -44,8 +44,7 @@ class TypeLocBuilder {
public:
TypeLocBuilder()
- : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity)
- {}
+ : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {}
~TypeLocBuilder() {
if (Buffer != InlineBuffer)
OpenPOWER on IntegriCloud