aboutsummaryrefslogtreecommitdiff
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.cpp213
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp40
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp100
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp40
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Sema.cpp188
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp30
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp42
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp50
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp142
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp844
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp218
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp2400
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp1945
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp2108
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp408
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp204
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp2490
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp972
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp175
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp296
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp1166
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp948
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp924
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp444
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp1207
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp1531
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp573
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp1386
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp699
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp295
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp1403
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp97
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaType.cpp804
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp136
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TreeTransform.h691
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.cpp136
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h86
43 files changed, 17597 insertions, 7967 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 1295339aa332..93e3ecfb2947 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -25,6 +25,7 @@
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
+#include "clang/Analysis/Analyses/Consumed.h"
#include "clang/Analysis/Analyses/ReachableCode.h"
#include "clang/Analysis/Analyses/ThreadSafety.h"
#include "clang/Analysis/Analyses/UninitializedValues.h"
@@ -438,22 +439,22 @@ static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
<< FixItHint::CreateInsertion(VD->getLocation(), "__block ");
return true;
}
-
+
// Don't issue a fixit if there is already an initializer.
if (VD->getInit())
return false;
-
- // Suggest possible initialization (if any).
- std::string Init = S.getFixItZeroInitializerForType(VariableTy);
- if (Init.empty())
- return false;
// Don't suggest a fixit inside macros.
if (VD->getLocEnd().isMacroID())
return false;
SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd());
-
+
+ // Suggest possible initialization (if any).
+ std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
+ if (Init.empty())
+ return false;
+
S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName()
<< FixItHint::CreateInsertion(Loc, Init);
return true;
@@ -492,6 +493,31 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
bool IsCapturedByBlock) {
bool Diagnosed = false;
+ switch (Use.getKind()) {
+ case UninitUse::Always:
+ S.Diag(Use.getUser()->getLocStart(), diag::warn_uninit_var)
+ << VD->getDeclName() << IsCapturedByBlock
+ << Use.getUser()->getSourceRange();
+ return;
+
+ case UninitUse::AfterDecl:
+ case UninitUse::AfterCall:
+ S.Diag(VD->getLocation(), diag::warn_sometimes_uninit_var)
+ << VD->getDeclName() << IsCapturedByBlock
+ << (Use.getKind() == UninitUse::AfterDecl ? 4 : 5)
+ << const_cast<DeclContext*>(VD->getLexicalDeclContext())
+ << VD->getSourceRange();
+ S.Diag(Use.getUser()->getLocStart(), diag::note_uninit_var_use)
+ << IsCapturedByBlock << Use.getUser()->getSourceRange();
+ return;
+
+ case UninitUse::Maybe:
+ case UninitUse::Sometimes:
+ // Carry on to report sometimes-uninitialized branches, if possible,
+ // or a 'may be used uninitialized' diagnostic otherwise.
+ break;
+ }
+
// Diagnose each branch which leads to a sometimes-uninitialized use.
for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end();
I != E; ++I) {
@@ -514,14 +540,10 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
: (I->Output ? "1" : "0");
FixItHint Fixit1, Fixit2;
- switch (Term->getStmtClass()) {
+ switch (Term ? Term->getStmtClass() : Stmt::DeclStmtClass) {
default:
// Don't know how to report this. Just fall back to 'may be used
- // uninitialized'. This happens for range-based for, which the user
- // can't explicitly fix.
- // FIXME: This also happens if the first use of a variable is always
- // uninitialized, eg "for (int n; n < 10; ++n)". We should report that
- // with the 'is uninitialized' diagnostic.
+ // uninitialized'. FIXME: Can this happen?
continue;
// "condition is true / condition is false".
@@ -582,6 +604,17 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
else
Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
break;
+ case Stmt::CXXForRangeStmtClass:
+ if (I->Output == 1) {
+ // The use occurs if a range-based for loop's body never executes.
+ // That may be impossible, and there's no syntactic fix for this,
+ // so treat it as a 'may be uninitialized' case.
+ continue;
+ }
+ DiagKind = 1;
+ Str = "for";
+ Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange();
+ break;
// "condition is true / loop is exited".
case Stmt::DoStmtClass:
@@ -618,9 +651,7 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
}
if (!Diagnosed)
- S.Diag(Use.getUser()->getLocStart(),
- Use.getKind() == UninitUse::Always ? diag::warn_uninit_var
- : diag::warn_maybe_uninit_var)
+ S.Diag(Use.getUser()->getLocStart(), diag::warn_maybe_uninit_var)
<< VD->getDeclName() << IsCapturedByBlock
<< Use.getUser()->getSourceRange();
}
@@ -1123,7 +1154,7 @@ static void diagnoseRepeatedUseOfWeak(Sema &S,
// Show the first time the object was read.
S.Diag(FirstRead->getLocStart(), DiagKind)
- << ObjectKind << D << FunctionKind
+ << int(ObjectKind) << D << int(FunctionKind)
<< FirstRead->getSourceRange();
// Print all the other accesses as notes.
@@ -1154,7 +1185,7 @@ struct SLocSort {
class UninitValsDiagReporter : public UninitVariablesHandler {
Sema &S;
typedef SmallVector<UninitUse, 2> UsesVec;
- typedef std::pair<UsesVec*, bool> MappedType;
+ typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType;
// Prefer using MapVector to DenseMap, so that iteration order will be
// the same as insertion order. This is needed to obtain a deterministic
// order of diagnostics when calling flushDiagnostics().
@@ -1172,19 +1203,18 @@ public:
uses = new UsesMap();
MappedType &V = (*uses)[vd];
- UsesVec *&vec = V.first;
- if (!vec)
- vec = new UsesVec();
+ if (!V.getPointer())
+ V.setPointer(new UsesVec());
return V;
}
void handleUseOfUninitVariable(const VarDecl *vd, const UninitUse &use) {
- getUses(vd).first->push_back(use);
+ getUses(vd).getPointer()->push_back(use);
}
void handleSelfInit(const VarDecl *vd) {
- getUses(vd).second = true;
+ getUses(vd).setInt(true);
}
void flushDiagnostics() {
@@ -1195,8 +1225,8 @@ public:
const VarDecl *vd = i->first;
const MappedType &V = i->second;
- UsesVec *vec = V.first;
- bool hasSelfInit = V.second;
+ UsesVec *vec = V.getPointer();
+ bool hasSelfInit = V.getInt();
// Specially handle the case where we have uses of an uninitialized
// variable, but the root cause is an idiomatic self-init. We want
@@ -1233,7 +1263,9 @@ public:
private:
static bool hasAlwaysUninitializedUse(const UsesVec* vec) {
for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) {
- if (i->getKind() == UninitUse::Always) {
+ if (i->getKind() == UninitUse::Always ||
+ i->getKind() == UninitUse::AfterCall ||
+ i->getKind() == UninitUse::AfterDecl) {
return true;
}
}
@@ -1242,12 +1274,8 @@ private:
};
}
-
-//===----------------------------------------------------------------------===//
-// -Wthread-safety
-//===----------------------------------------------------------------------===//
namespace clang {
-namespace thread_safety {
+namespace {
typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
typedef std::list<DelayedDiag> DiagList;
@@ -1262,7 +1290,13 @@ struct SortDiagBySourceLocation {
return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);
}
};
+}}
+//===----------------------------------------------------------------------===//
+// -Wthread-safety
+//===----------------------------------------------------------------------===//
+namespace clang {
+namespace thread_safety {
namespace {
class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
Sema &S;
@@ -1413,6 +1447,102 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
}
//===----------------------------------------------------------------------===//
+// -Wconsumed
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+namespace consumed {
+namespace {
+class ConsumedWarningsHandler : public ConsumedWarningsHandlerBase {
+
+ Sema &S;
+ DiagList Warnings;
+
+public:
+
+ ConsumedWarningsHandler(Sema &S) : S(S) {}
+
+ void emitDiagnostics() {
+ Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
+
+ for (DiagList::iterator I = Warnings.begin(), E = Warnings.end();
+ I != E; ++I) {
+
+ const OptionalNotes &Notes = I->second;
+ S.Diag(I->first.first, I->first.second);
+
+ for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI) {
+ S.Diag(Notes[NoteI].first, Notes[NoteI].second);
+ }
+ }
+ }
+
+ void warnLoopStateMismatch(SourceLocation Loc, StringRef VariableName) {
+ PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_loop_state_mismatch) <<
+ VariableName);
+
+ Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ }
+
+ void warnParamReturnTypestateMismatch(SourceLocation Loc,
+ StringRef VariableName,
+ StringRef ExpectedState,
+ StringRef ObservedState) {
+
+ PartialDiagnosticAt Warning(Loc, S.PDiag(
+ diag::warn_param_return_typestate_mismatch) << VariableName <<
+ ExpectedState << ObservedState);
+
+ Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ }
+
+ void warnParamTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
+ StringRef ObservedState) {
+
+ PartialDiagnosticAt Warning(Loc, S.PDiag(
+ diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
+
+ Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ }
+
+ void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
+ StringRef TypeName) {
+ PartialDiagnosticAt Warning(Loc, S.PDiag(
+ diag::warn_return_typestate_for_unconsumable_type) << TypeName);
+
+ Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ }
+
+ void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
+ StringRef ObservedState) {
+
+ PartialDiagnosticAt Warning(Loc, S.PDiag(
+ diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
+
+ Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ }
+
+ void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State,
+ SourceLocation Loc) {
+
+ PartialDiagnosticAt Warning(Loc, S.PDiag(
+ diag::warn_use_of_temp_in_invalid_state) << MethodName << State);
+
+ Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ }
+
+ void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
+ StringRef State, SourceLocation Loc) {
+
+ PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) <<
+ MethodName << VariableName << State);
+
+ Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ }
+};
+}}}
+
+//===----------------------------------------------------------------------===//
// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
// warnings on a function, method, or block.
//===----------------------------------------------------------------------===//
@@ -1421,6 +1551,7 @@ clang::sema::AnalysisBasedWarnings::Policy::Policy() {
enableCheckFallThrough = 1;
enableCheckUnreachable = 0;
enableThreadSafetyAnalysis = 0;
+ enableConsumedAnalysis = 0;
}
clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s)
@@ -1441,7 +1572,9 @@ clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s)
DefaultPolicy.enableThreadSafetyAnalysis = (unsigned)
(D.getDiagnosticLevel(diag::warn_double_lock, SourceLocation()) !=
DiagnosticsEngine::Ignored);
-
+ DefaultPolicy.enableConsumedAnalysis = (unsigned)
+ (D.getDiagnosticLevel(diag::warn_use_in_invalid_state, SourceLocation()) !=
+ DiagnosticsEngine::Ignored);
}
static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) {
@@ -1486,10 +1619,11 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
const Stmt *Body = D->getBody();
assert(Body);
+ // Construct the analysis context with the specified CFG build options.
AnalysisDeclContext AC(/* AnalysisDeclContextManager */ 0, D);
// Don't generate EH edges for CallExprs as we'd like to avoid the n^2
- // explosion for destrutors that can result and the compile time hit.
+ // explosion for destructors that can result and the compile time hit.
AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true;
AC.getCFGBuildOptions().AddEHEdges = false;
AC.getCFGBuildOptions().AddInitializers = true;
@@ -1502,7 +1636,8 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
// prototyping, but we need a way for analyses to say what expressions they
// expect to always be CFGElements and then fill in the BuildOptions
// appropriately. This is essentially a layering violation.
- if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis) {
+ if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis ||
+ P.enableConsumedAnalysis) {
// Unreachable code analysis and thread safety require a linearized CFG.
AC.getCFGBuildOptions().setAllAlwaysAdd();
}
@@ -1518,8 +1653,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
.setAlwaysAdd(Stmt::AttributedStmtClass);
}
- // Construct the analysis context with the specified CFG build options.
-
+
// Emit delayed diagnostics.
if (!fscope->PossiblyUnreachableDiags.empty()) {
bool analyzed = false;
@@ -1606,6 +1740,13 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
Reporter.emitDiagnostics();
}
+ // Check for violations of consumed properties.
+ if (P.enableConsumedAnalysis) {
+ consumed::ConsumedWarningsHandler WarningHandler(S);
+ consumed::ConsumedAnalyzer Analyzer(WarningHandler);
+ Analyzer.run(AC);
+ }
+
if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart())
!= DiagnosticsEngine::Ignored ||
Diags.getDiagnosticLevel(diag::warn_sometimes_uninit_var,D->getLocStart())
diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
index 9ac4c63e191e..c9807723f064 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
@@ -19,13 +19,21 @@
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
+IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
+ IdentifierInfo *Ident) {
+ IdentifierLoc *Result = new (Ctx) IdentifierLoc;
+ Result->Loc = Loc;
+ Result->Ident = Ident;
+ return Result;
+}
+
size_t AttributeList::allocated_size() const {
if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
else if (IsTypeTagForDatatype)
return AttributeFactory::TypeTagForDatatypeAllocSize;
else if (IsProperty)
return AttributeFactory::PropertyAllocSize;
- return (sizeof(AttributeList) + NumArgs * sizeof(Expr*));
+ return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion));
}
AttributeFactory::AttributeFactory() {
@@ -98,10 +106,9 @@ void AttributePool::takePool(AttributeList *pool) {
AttributeList *
AttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
SourceLocation TokLoc, int Arg) {
- Expr *IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg),
+ ArgsUnion IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg),
C.IntTy, TokLoc);
- return create(Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1,
- AttributeList::AS_GNU);
+ return create(Name, TokLoc, 0, TokLoc, &IArg, 1, AttributeList::AS_GNU);
}
#include "clang/Sema/AttrParsedAttrKinds.inc"
@@ -138,3 +145,28 @@ unsigned AttributeList::getAttributeSpellingListIndex() const {
}
+struct ParsedAttrInfo {
+ unsigned NumArgs : 4;
+ unsigned OptArgs : 4;
+ unsigned HasCustomParsing : 1;
+};
+
+namespace {
+ #include "clang/Sema/AttrParsedAttrImpl.inc"
+}
+
+static const ParsedAttrInfo &getInfo(const AttributeList &A) {
+ return AttrInfoMap[A.getKind()];
+}
+
+unsigned AttributeList::getMinArgs() const {
+ return getInfo(*this).NumArgs;
+}
+
+unsigned AttributeList::getMaxArgs() const {
+ return getMinArgs() + getInfo(*this).OptArgs;
+}
+
+bool AttributeList::hasCustomParsing() const {
+ return getInfo(*this).HasCustomParsing;
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
index 3b3ab2c27b4a..c2f16157b8eb 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
@@ -13,6 +13,7 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TypeLoc.h"
@@ -325,6 +326,19 @@ bool Declarator::isDeclarationOfFunction() const {
llvm_unreachable("Invalid TypeSpecType!");
}
+bool Declarator::isStaticMember() {
+ assert(getContext() == MemberContext);
+ return getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
+ CXXMethodDecl::isStaticOverloadedOperator(
+ getName().OperatorFunctionId.Operator);
+}
+
+bool DeclSpec::hasTagDefinition() const {
+ if (!TypeSpecOwned)
+ return false;
+ return cast<TagDecl>(getRepAsDecl())->isCompleteDefinition();
+}
+
/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
/// declaration specifier includes.
///
@@ -341,7 +355,7 @@ unsigned DeclSpec::getParsedSpecifiers() const {
Res |= PQ_TypeSpecifier;
if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified ||
- FS_noreturn_specified)
+ FS_noreturn_specified || FS_forceinline_specified)
Res |= PQ_FunctionSpecifier;
return Res;
}
@@ -651,7 +665,7 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
DeclRep = Rep;
TSTLoc = TagKwLoc;
TSTNameLoc = TagNameLoc;
- TypeSpecOwned = Owned;
+ TypeSpecOwned = Owned && Rep != 0;
return false;
}
@@ -707,6 +721,20 @@ bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
return false;
}
+bool DeclSpec::SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID) {
+ if (!TypeAltiVecVector || TypeAltiVecBool ||
+ (TypeSpecType != TST_unspecified)) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::err_invalid_vector_bool_decl_spec;
+ return true;
+ }
+ TypeAltiVecBool = isAltiVecBool;
+ TSTLoc = Loc;
+ TSTNameLoc = Loc;
+ return false;
+}
+
bool DeclSpec::SetTypeSpecError() {
TypeSpecType = TST_error;
TypeSpecOwned = false;
@@ -717,9 +745,10 @@ bool DeclSpec::SetTypeSpecError() {
bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID, const LangOptions &Lang) {
- // Duplicates are permitted in C99, but are not permitted in C++. However,
- // since this is likely not what the user intended, we will always warn. We
- // do not need to set the qualifier's location since we already have it.
+ // Duplicates are permitted in C99 onwards, but are not permitted in C89 or
+ // C++. However, since this is likely not what the user intended, we will
+ // always warn. We do not need to set the qualifier's location since we
+ // already have it.
if (TypeQualifiers & T) {
bool IsExtension = true;
if (Lang.C99)
@@ -739,29 +768,72 @@ bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
llvm_unreachable("Unknown type qualifier!");
}
-bool DeclSpec::setFunctionSpecInline(SourceLocation Loc) {
- // 'inline inline' is ok.
+bool DeclSpec::setFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
+ // 'inline inline' is ok. However, since this is likely not what the user
+ // intended, we will always warn, similar to duplicates of type qualifiers.
+ if (FS_inline_specified) {
+ DiagID = diag::warn_duplicate_declspec;
+ PrevSpec = "inline";
+ return true;
+ }
FS_inline_specified = true;
FS_inlineLoc = Loc;
return false;
}
-bool DeclSpec::setFunctionSpecVirtual(SourceLocation Loc) {
- // 'virtual virtual' is ok.
+bool DeclSpec::setFunctionSpecForceInline(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
+ if (FS_forceinline_specified) {
+ DiagID = diag::warn_duplicate_declspec;
+ PrevSpec = "__forceinline";
+ return true;
+ }
+ FS_forceinline_specified = true;
+ FS_forceinlineLoc = Loc;
+ return false;
+}
+
+bool DeclSpec::setFunctionSpecVirtual(SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
+ // 'virtual virtual' is ok, but warn as this is likely not what the user
+ // intended.
+ if (FS_virtual_specified) {
+ DiagID = diag::warn_duplicate_declspec;
+ PrevSpec = "virtual";
+ return true;
+ }
FS_virtual_specified = true;
FS_virtualLoc = Loc;
return false;
}
-bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc) {
- // 'explicit explicit' is ok.
+bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
+ // 'explicit explicit' is ok, but warn as this is likely not what the user
+ // intended.
+ if (FS_explicit_specified) {
+ DiagID = diag::warn_duplicate_declspec;
+ PrevSpec = "explicit";
+ return true;
+ }
FS_explicit_specified = true;
FS_explicitLoc = Loc;
return false;
}
-bool DeclSpec::setFunctionSpecNoreturn(SourceLocation Loc) {
- // '_Noreturn _Noreturn' is ok.
+bool DeclSpec::setFunctionSpecNoreturn(SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
+ // '_Noreturn _Noreturn' is ok, but warn as this is likely not what the user
+ // intended.
+ if (FS_noreturn_specified) {
+ DiagID = diag::warn_duplicate_declspec;
+ PrevSpec = "_Noreturn";
+ return true;
+ }
FS_noreturn_specified = true;
FS_noreturnLoc = Loc;
return false;
@@ -1096,6 +1168,7 @@ bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc,
switch (VS) {
default: llvm_unreachable("Unknown specifier!");
case VS_Override: VS_overrideLoc = Loc; break;
+ case VS_Sealed:
case VS_Final: VS_finalLoc = Loc; break;
}
@@ -1107,5 +1180,6 @@ const char *VirtSpecifiers::getSpecifierName(Specifier VS) {
default: llvm_unreachable("Unknown specifier");
case VS_Override: return "override";
case VS_Final: return "final";
+ case VS_Sealed: return "sealed";
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
index d44c1fb926f5..6e354b9060e3 100644
--- a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
@@ -78,19 +78,6 @@ void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) {
llvm_unreachable("Didn't find this decl on its identifier's chain!");
}
-bool
-IdentifierResolver::IdDeclInfo::ReplaceDecl(NamedDecl *Old, NamedDecl *New) {
- for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
- if (Old == *(I-1)) {
- *(I - 1) = New;
- return true;
- }
- }
-
- return false;
-}
-
-
//===----------------------------------------------------------------------===//
// IdentifierResolver Implementation
//===----------------------------------------------------------------------===//
@@ -113,8 +100,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S,
if (Ctx->isFunctionOrMethod() || S->isFunctionPrototypeScope()) {
// Ignore the scopes associated within transparent declaration contexts.
- while (S->getEntity() &&
- ((DeclContext *)S->getEntity())->isTransparentContext())
+ while (S->getEntity() && S->getEntity()->isTransparentContext())
S = S->getParent();
if (S->isDeclScope(D))
@@ -235,30 +221,6 @@ void IdentifierResolver::RemoveDecl(NamedDecl *D) {
return toIdDeclInfo(Ptr)->RemoveDecl(D);
}
-bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) {
- assert(Old->getDeclName() == New->getDeclName() &&
- "Cannot replace a decl with another decl of a different name");
-
- DeclarationName Name = Old->getDeclName();
- if (IdentifierInfo *II = Name.getAsIdentifierInfo())
- updatingIdentifier(*II);
-
- void *Ptr = Name.getFETokenInfo<void>();
-
- if (!Ptr)
- return false;
-
- if (isDeclPtr(Ptr)) {
- if (Ptr == Old) {
- Name.setFETokenInfo(New);
- return true;
- }
- return false;
- }
-
- return toIdDeclInfo(Ptr)->ReplaceDecl(Old, New);
-}
-
/// begin - Returns an iterator for decls with name 'Name'.
IdentifierResolver::iterator
IdentifierResolver::begin(DeclarationName Name) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
index 5f92cfffc6b0..d3de1732766e 100644
--- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
@@ -175,8 +175,9 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) {
const MaterializeTemporaryExpr *M = NULL;
Init = Init->findMaterializedTemporary(M);
+ SmallVector<const Expr *, 2> CommaLHSs;
SmallVector<SubobjectAdjustment, 2> Adjustments;
- Init = Init->skipRValueSubobjectAdjustments(Adjustments);
+ Init = Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
QualType QT = Init->getType();
if (QT.isNull())
@@ -198,7 +199,11 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) {
if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(Init)) {
const CXXConstructorDecl *ctor = cce->getConstructor();
- if (ctor->isTrivial() && ctor->isDefaultConstructor()) {
+ // For a variable declared without an initializer, we will have
+ // call-style initialization and the initializer will be the
+ // CXXConstructExpr with no intervening nodes.
+ if (ctor->isTrivial() && ctor->isDefaultConstructor() &&
+ VD->getInit() == Init && VD->getInitStyle() == VarDecl::CallInit) {
if (OutDiag)
InDiag = diag::note_protected_by_variable_nontriv_destructor;
else if (!Record->isPOD())
diff --git a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index d85624ba6f64..ad7627a45715 100644
--- a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -267,3 +267,34 @@ void MultiplexExternalSemaSource::ReadPendingInstantiations(
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadPendingInstantiations(Pending);
}
+
+void MultiplexExternalSemaSource::ReadLateParsedTemplates(
+ llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {
+ for (size_t i = 0; i < Sources.size(); ++i)
+ Sources[i]->ReadLateParsedTemplates(LPTMap);
+}
+
+TypoCorrection MultiplexExternalSemaSource::CorrectTypo(
+ const DeclarationNameInfo &Typo,
+ int LookupKind, Scope *S, CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
+ DeclContext *MemberContext,
+ bool EnteringContext,
+ const ObjCObjectPointerType *OPT) {
+ for (size_t I = 0, E = Sources.size(); I < E; ++I) {
+ if (TypoCorrection C = Sources[I]->CorrectTypo(Typo, LookupKind, S, SS, CCC,
+ MemberContext,
+ EnteringContext, OPT))
+ return C;
+ }
+ return TypoCorrection();
+}
+
+bool MultiplexExternalSemaSource::MaybeDiagnoseMissingCompleteType(
+ SourceLocation Loc, QualType T) {
+ for (size_t I = 0, E = Sources.size(); I < E; ++I) {
+ if (Sources[I]->MaybeDiagnoseMissingCompleteType(Loc, T))
+ return true;
+ }
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
index 2f48bec123bf..8b3493ebfef8 100644
--- a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
@@ -184,6 +184,21 @@ void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
ThisUse->markSafe();
}
+void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E) {
+ assert(Idx < getNumPotentialVariableCaptures() &&
+ "Index of potential capture must be within 0 to less than the "
+ "number of captures!");
+ E = PotentiallyCapturingExprs[Idx];
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ VD = dyn_cast<VarDecl>(DRE->getFoundDecl());
+ else if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
+ VD = dyn_cast<VarDecl>(ME->getMemberDecl());
+ else
+ llvm_unreachable("Only DeclRefExprs or MemberExprs should be added for "
+ "potential captures");
+ assert(VD);
+}
+
FunctionScopeInfo::~FunctionScopeInfo() { }
BlockScopeInfo::~BlockScopeInfo() { }
LambdaScopeInfo::~LambdaScopeInfo() { }
diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
index e718be2f8bd5..4d01fb0a6be6 100644
--- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
@@ -89,8 +89,10 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
NumSFINAEErrors(0), InFunctionDeclarator(0),
AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
- CurrentInstantiationScope(0), TyposCorrected(0),
- AnalysisWarnings(*this), CurScope(0), Ident_super(0)
+ CurrentInstantiationScope(0), DisableTypoCorrection(false),
+ TyposCorrected(0), AnalysisWarnings(*this),
+ VarDataSharingAttributesStack(0), CurScope(0),
+ Ident_super(0), Ident___float128(0)
{
TUScope = 0;
@@ -113,6 +115,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
false, 0, false));
FunctionScopes.push_back(new FunctionScopeInfo(Diags));
+
+ // Initilization of data sharing attributes stack for OpenMP
+ InitDataSharingAttributesStack();
}
void Sema::Initialize() {
@@ -173,6 +178,10 @@ void Sema::Initialize() {
}
Sema::~Sema() {
+ for (LateParsedTemplateMapT::iterator I = LateParsedTemplateMap.begin(),
+ E = LateParsedTemplateMap.end();
+ I != E; ++I)
+ delete I->second;
if (PackContext) FreePackedContext();
if (VisContext) FreeVisContext();
delete TheTargetAttributesSema;
@@ -195,6 +204,9 @@ Sema::~Sema() {
// If Sema's ExternalSource is the multiplexer - we own it.
if (isMultiplexExternalSource)
delete ExternalSource;
+
+ // Destroys data sharing attributes stack for OpenMP
+ DestroyDataSharingAttributesStack();
}
/// makeUnavailableInSystemHeader - There is an error in the current
@@ -284,9 +296,6 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
if (ExprTy == TypeTy)
return Owned(E);
- if (getLangOpts().ObjCAutoRefCount)
- CheckObjCARCConversion(SourceRange(), Ty, E, CCK);
-
// If this is a derived-to-base cast to a through a virtual base, we
// need a vtable.
if (Kind == CK_DerivedToBase &&
@@ -332,7 +341,7 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
if (D->getMostRecentDecl()->isUsed())
return true;
- if (D->hasExternalLinkage())
+ if (D->isExternallyVisible())
return true;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
@@ -350,6 +359,15 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
}
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ // If a variable usable in constant expressions is referenced,
+ // don't warn if it isn't used: if the value of a variable is required
+ // for the computation of a constant expression, it doesn't make sense to
+ // warn even if the variable isn't odr-used. (isReferenced doesn't
+ // precisely reflect that, but it's a decent approximation.)
+ if (VD->isReferenced() &&
+ VD->isUsableInConstantExpressions(SemaRef->Context))
+ return true;
+
// UnusedFileScopedDecls stores the first declaration.
// The declaration may have become definition so check again.
const VarDecl *DeclToCheck = VD->getDefinition();
@@ -402,13 +420,13 @@ void Sema::getUndefinedButUsed(
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
if (FD->isDefined())
continue;
- if (FD->hasExternalLinkage() &&
+ if (FD->isExternallyVisible() &&
!FD->getMostRecentDecl()->isInlined())
continue;
} else {
if (cast<VarDecl>(ND)->hasDefinition() != VarDecl::DeclarationOnly)
continue;
- if (ND->hasExternalLinkage())
+ if (ND->isExternallyVisible())
continue;
}
@@ -435,7 +453,7 @@ static void checkUndefinedButUsed(Sema &S) {
I = Undefined.begin(), E = Undefined.end(); I != E; ++I) {
NamedDecl *ND = I->first;
- if (ND->getLinkage() != ExternalLinkage) {
+ if (!ND->isExternallyVisible()) {
S.Diag(ND->getLocation(), diag::warn_undefined_internal)
<< isa<VarDecl>(ND) << ND;
} else {
@@ -551,9 +569,9 @@ void Sema::ActOnEndOfTranslationUnit() {
if (PP.isCodeCompletionEnabled())
return;
- // Only complete translation units define vtables and perform implicit
- // instantiations.
- if (TUKind == TU_Complete) {
+ // Complete translation units and modules define vtables and perform implicit
+ // instantiations. PCH files do not.
+ if (TUKind != TU_Prefix) {
DiagnoseUseOfUnimplementedSelectors();
// If any dynamic classes have their key function defined within
@@ -582,13 +600,18 @@ void Sema::ActOnEndOfTranslationUnit() {
// 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.
+ // so it will find some names that are not required to be found. This is
+ // valid, but we could do better by diagnosing if an instantiation uses a
+ // name that was not visible at its first point of instantiation.
PerformPendingInstantiations();
+ CheckDelayedMemberExceptionSpecs();
}
+ // All delayed member exception specs should be checked or we end up accepting
+ // incompatible declarations.
+ assert(DelayedDefaultedMemberExceptionSpecs.empty());
+ assert(DelayedDestructorExceptionSpecChecks.empty());
+
// Remove file scoped decls that turned out to be used.
UnusedFileScopedDecls.erase(
std::remove_if(UnusedFileScopedDecls.begin(0, true),
@@ -630,14 +653,14 @@ void Sema::ActOnEndOfTranslationUnit() {
SmallVector<Module *, 2> Stack;
Stack.push_back(CurrentModule);
while (!Stack.empty()) {
- Module *Mod = Stack.back();
- Stack.pop_back();
+ Module *Mod = Stack.pop_back_val();
// Resolve the exported declarations and conflicts.
// FIXME: Actually complain, once we figure out how to teach the
// diagnostic client to deal with complaints in the module map at this
// point.
ModMap.resolveExports(Mod, /*Complain=*/false);
+ ModMap.resolveUses(Mod, /*Complain=*/false);
ModMap.resolveConflicts(Mod, /*Complain=*/false);
// Queue the submodules, so their exports will also be resolved.
@@ -681,13 +704,6 @@ void Sema::ActOnEndOfTranslationUnit() {
if (const IncompleteArrayType *ArrayT
= Context.getAsIncompleteArrayType(VD->getType())) {
- if (RequireCompleteType(VD->getLocation(),
- ArrayT->getElementType(),
- diag::err_tentative_def_incomplete_type_arr)) {
- VD->setInvalidDecl();
- continue;
- }
-
// Set the length of the array to 1 (C99 6.9.2p5).
Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
@@ -729,7 +745,7 @@ void Sema::ActOnEndOfTranslationUnit() {
else {
if (FD->getStorageClass() == SC_Static &&
!FD->isInlineSpecified() &&
- !SourceMgr.isFromMainFile(
+ !SourceMgr.isInMainFile(
SourceMgr.getExpansionLoc(FD->getLocation())))
Diag(DiagD->getLocation(), diag::warn_unneeded_static_internal_decl)
<< DiagD->getDeclName();
@@ -750,11 +766,10 @@ void Sema::ActOnEndOfTranslationUnit() {
if (DiagD->isReferenced()) {
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
<< /*variable*/1 << DiagD->getDeclName();
- } else if (getSourceManager().isFromMainFile(DiagD->getLocation())) {
- // If the declaration is in a header which is included into multiple
- // TUs, it will declare one variable per TU, and one of the other
- // variables may be used. So, only warn if the declaration is in the
- // main file.
+ } else if (DiagD->getType().isConstQualified()) {
+ Diag(DiagD->getLocation(), diag::warn_unused_const_variable)
+ << DiagD->getDeclName();
+ } else {
Diag(DiagD->getLocation(), diag::warn_unused_variable)
<< DiagD->getDeclName();
}
@@ -824,6 +839,8 @@ FunctionDecl *Sema::getCurFunctionDecl() {
ObjCMethodDecl *Sema::getCurMethodDecl() {
DeclContext *DC = getFunctionLevelDeclContext();
+ while (isa<RecordDecl>(DC))
+ DC = DC->getParent();
return dyn_cast<ObjCMethodDecl>(DC);
}
@@ -986,7 +1003,7 @@ Scope *Sema::getScopeForContext(DeclContext *Ctx) {
// Ignore scopes that cannot have declarations. This is important for
// out-of-line definitions of static class members.
if (S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope))
- if (DeclContext *Entity = static_cast<DeclContext *> (S->getEntity()))
+ if (DeclContext *Entity = S->getEntity())
if (Ctx == Entity->getPrimaryContext())
return S;
}
@@ -1012,10 +1029,19 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
BlockScope, Block));
}
-void Sema::PushLambdaScope(CXXRecordDecl *Lambda,
- CXXMethodDecl *CallOperator) {
- FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda,
- CallOperator));
+LambdaScopeInfo *Sema::PushLambdaScope() {
+ LambdaScopeInfo *const LSI = new LambdaScopeInfo(getDiagnostics());
+ FunctionScopes.push_back(LSI);
+ return LSI;
+}
+
+void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {
+ if (LambdaScopeInfo *const LSI = getCurLambda()) {
+ LSI->AutoTemplateParameterDepth = Depth;
+ return;
+ }
+ llvm_unreachable(
+ "Remove assertion if intentionally called in a non-lambda context.");
}
void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
@@ -1071,6 +1097,16 @@ LambdaScopeInfo *Sema::getCurLambda() {
return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
}
+// We have a generic lambda if we parsed auto parameters, or we have
+// an associated template parameter list.
+LambdaScopeInfo *Sema::getCurGenericLambda() {
+ if (LambdaScopeInfo *LSI = getCurLambda()) {
+ return (LSI->AutoTemplateParams.size() ||
+ LSI->GLTemplateParameterList) ? LSI : 0;
+ }
+ return 0;
+}
+
void Sema::ActOnComment(SourceRange Comment) {
if (!LangOpts.RetainCommentsFromSystemHeaders &&
@@ -1141,33 +1177,68 @@ void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
/// call; otherwise, it is set to an empty QualType.
/// \param OverloadSet - If the expression is an overloaded function
/// name, this parameter is populated with the decls of the various overloads.
-bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
- UnresolvedSetImpl &OverloadSet) {
+bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
+ UnresolvedSetImpl &OverloadSet) {
ZeroArgCallReturnTy = QualType();
OverloadSet.clear();
+ const OverloadExpr *Overloads = NULL;
+ bool IsMemExpr = false;
if (E.getType() == Context.OverloadTy) {
OverloadExpr::FindResult FR = OverloadExpr::find(const_cast<Expr*>(&E));
- const OverloadExpr *Overloads = FR.Expression;
+ // Ignore overloads that are pointer-to-member constants.
+ if (FR.HasFormOfMemberPointer)
+ return false;
+
+ Overloads = FR.Expression;
+ } else if (E.getType() == Context.BoundMemberTy) {
+ Overloads = dyn_cast<UnresolvedMemberExpr>(E.IgnoreParens());
+ IsMemExpr = true;
+ }
+
+ bool Ambiguous = false;
+
+ if (Overloads) {
for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) {
OverloadSet.addDecl(*it);
- // Check whether the function is a non-template which takes no
+ // Check whether the function is a non-template, non-member which takes no
// arguments.
+ if (IsMemExpr)
+ continue;
if (const FunctionDecl *OverloadDecl
= dyn_cast<FunctionDecl>((*it)->getUnderlyingDecl())) {
- if (OverloadDecl->getMinRequiredArguments() == 0)
- ZeroArgCallReturnTy = OverloadDecl->getResultType();
+ if (OverloadDecl->getMinRequiredArguments() == 0) {
+ if (!ZeroArgCallReturnTy.isNull() && !Ambiguous) {
+ ZeroArgCallReturnTy = QualType();
+ Ambiguous = true;
+ } else
+ ZeroArgCallReturnTy = OverloadDecl->getResultType();
+ }
}
}
- // Ignore overloads that are pointer-to-member constants.
- if (FR.HasFormOfMemberPointer)
- return false;
+ // If it's not a member, use better machinery to try to resolve the call
+ if (!IsMemExpr)
+ return !ZeroArgCallReturnTy.isNull();
+ }
- return true;
+ // Attempt to call the member with no arguments - this will correctly handle
+ // member templates with defaults/deduction of template arguments, overloads
+ // with default arguments, etc.
+ if (IsMemExpr && !E.isTypeDependent()) {
+ bool Suppress = getDiagnostics().getSuppressAllDiagnostics();
+ getDiagnostics().setSuppressAllDiagnostics(true);
+ ExprResult R = BuildCallToMemberFunction(NULL, &E, SourceLocation(), None,
+ SourceLocation());
+ getDiagnostics().setSuppressAllDiagnostics(Suppress);
+ if (R.isUsable()) {
+ ZeroArgCallReturnTy = R.get()->getType();
+ return true;
+ }
+ return false;
}
if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E.IgnoreParens())) {
@@ -1187,14 +1258,6 @@ bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
FunTy = PointeeTy->getAs<FunctionType>();
if (!FunTy)
FunTy = ExprTy->getAs<FunctionType>();
- if (!FunTy && ExprTy == 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 BoundMemberTy = Expr::findBoundMemberType(&E);
- if (!BoundMemberTy.isNull())
- FunTy = BoundMemberTy->castAs<FunctionType>();
- }
if (const FunctionProtoType *FPT =
dyn_cast_or_null<FunctionProtoType>(FunTy)) {
@@ -1207,7 +1270,7 @@ bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
/// \brief Give notes for a set of overloads.
///
-/// A companion to isExprCallable. In cases when the name that the programmer
+/// A companion to tryExprAsCall. In cases when the name that the programmer
/// wrote was an overloaded function, we may be able to make some guesses about
/// plausible overloads based on their return types; such guesses can be handed
/// off to this method to be emitted as notes.
@@ -1277,15 +1340,14 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
QualType ZeroArgCallTy;
UnresolvedSet<4> Overloads;
- if (isExprCallable(*E.get(), ZeroArgCallTy, Overloads) &&
+ if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
!ZeroArgCallTy.isNull() &&
(!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
// At this point, we know E is potentially callable with 0
// arguments and that it returns something of a reasonable type,
// so we can emit a fixit and carry on pretending that E was
// actually a CallExpr.
- SourceLocation ParenInsertionLoc =
- PP.getLocForEndOfToken(Range.getEnd());
+ SourceLocation ParenInsertionLoc = PP.getLocForEndOfToken(Range.getEnd());
Diag(Loc, PD)
<< /*zero-arg*/ 1 << Range
<< (IsCallableWithAppend(E.get())
@@ -1295,8 +1357,8 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
// FIXME: Try this before emitting the fixit, and suppress diagnostics
// while doing so.
- E = ActOnCallExpr(0, E.take(), ParenInsertionLoc,
- None, ParenInsertionLoc.getLocWithOffset(1));
+ E = ActOnCallExpr(0, E.take(), Range.getEnd(), None,
+ Range.getEnd().getLocWithOffset(1));
return true;
}
@@ -1314,6 +1376,12 @@ IdentifierInfo *Sema::getSuperIdentifier() const {
return Ident_super;
}
+IdentifierInfo *Sema::getFloat128Identifier() const {
+ if (!Ident___float128)
+ Ident___float128 = &Context.Idents.get("__float128");
+ return Ident___float128;
+}
+
void Sema::PushCapturedRegionScope(Scope *S, CapturedDecl *CD, RecordDecl *RD,
CapturedRegionKind K) {
CapturingScopeInfo *CSI = new CapturedRegionScopeInfo(getDiagnostics(), S, CD, RD,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
index 3ef1fdebaac7..61dc157f8589 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
@@ -315,8 +315,7 @@ static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
if (Queue.empty()) break;
- Derived = Queue.back();
- Queue.pop_back();
+ Derived = Queue.pop_back_val();
}
return OnFailure;
@@ -1484,7 +1483,9 @@ void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) {
DeclContext *DC = D->getDeclContext();
if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) {
- if (!DC->isFunctionOrMethod())
+ if (D->getLexicalDeclContext()->isFunctionOrMethod())
+ DC = D->getLexicalDeclContext();
+ else
DC = FN;
} else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) {
DC = cast<DeclContext>(TD->getTemplatedDecl());
@@ -1649,9 +1650,9 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
}
case InitializedEntity::EK_LambdaCapture: {
- const VarDecl *Var = Entity.getCapturedVar();
+ StringRef VarName = Entity.getCapturedVarName();
PD = PDiag(diag::err_access_lambda_capture);
- PD << Var->getName() << Entity.getType() << getSpecialMember(Constructor);
+ PD << VarName << Entity.getType() << getSpecialMember(Constructor);
break;
}
@@ -1710,6 +1711,21 @@ Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
return CheckAccess(*this, OpLoc, Entity);
}
+/// \brief Checks access to a member.
+Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc,
+ CXXRecordDecl *NamingClass,
+ DeclAccessPair Found) {
+ if (!getLangOpts().AccessControl ||
+ !NamingClass ||
+ Found.getAccess() == AS_public)
+ return AR_accessible;
+
+ AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
+ Found, QualType());
+
+ return CheckAccess(*this, UseLoc, Entity);
+}
+
/// Checks access to an overloaded member operator, including
/// conversion operators.
Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
@@ -1872,9 +1888,7 @@ bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) {
if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public ||
Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package)
return true;
-
-
-
+
// If we are inside a class or category implementation, determine the
// interface we're in.
ObjCInterfaceDecl *ClassOfMethodDecl = 0;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
index e12bbde0d0dd..8f9ab32517d6 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/ASTConsumer.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
@@ -263,6 +264,30 @@ void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
MSStructPragmaOn = (Kind == PMSST_ON);
}
+void Sema::ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg) {
+ // FIXME: Serialize this.
+ switch (Kind) {
+ case PCK_Unknown:
+ llvm_unreachable("unexpected pragma comment kind");
+ case PCK_Linker:
+ Consumer.HandleLinkerOptionPragma(Arg);
+ return;
+ case PCK_Lib:
+ Consumer.HandleDependentLibrary(Arg);
+ return;
+ case PCK_Compiler:
+ case PCK_ExeStr:
+ case PCK_User:
+ return; // We ignore all of these.
+ }
+ llvm_unreachable("invalid pragma comment kind");
+}
+
+void Sema::ActOnPragmaDetectMismatch(StringRef Name, StringRef Value) {
+ // FIXME: Serialize this.
+ Consumer.HandleDetectMismatch(Name, Value);
+}
+
void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
SourceLocation PragmaLoc) {
@@ -343,21 +368,12 @@ void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType,
SourceLocation PragmaLoc) {
if (VisType) {
// Compute visibility to use.
- VisibilityAttr::VisibilityType type;
- if (VisType->isStr("default"))
- type = VisibilityAttr::Default;
- else if (VisType->isStr("hidden"))
- type = VisibilityAttr::Hidden;
- else if (VisType->isStr("internal"))
- type = VisibilityAttr::Hidden; // FIXME
- else if (VisType->isStr("protected"))
- type = VisibilityAttr::Protected;
- else {
- Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) <<
- VisType->getName();
+ VisibilityAttr::VisibilityType T;
+ if (!VisibilityAttr::ConvertStrToVisibilityType(VisType->getName(), T)) {
+ Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << VisType;
return;
}
- PushPragmaVisibility(*this, type, PragmaLoc);
+ PushPragmaVisibility(*this, T, PragmaLoc);
} else {
PopPragmaVisibility(false, PragmaLoc);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 01ac8f7fb62d..554a114bae60 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -160,16 +160,6 @@ bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
return SS.getScopeRep()->isDependent();
}
-// \brief Determine whether this C++ scope specifier refers to an
-// unknown specialization, i.e., a dependent type that is not the
-// current instantiation.
-bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) {
- if (!isDependentScopeSpecifier(SS))
- return false;
-
- return getCurrentInstantiationOf(SS.getScopeRep()) == 0;
-}
-
/// \brief If the given nested name specifier refers to the current
/// instantiation, return the declaration that corresponds to that
/// current instantiation (C++0x [temp.dep.type]p1).
@@ -494,32 +484,30 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
// FIXME: Deal with ambiguities cleanly.
- if (Found.empty() && !ErrorRecoveryLookup) {
+ if (Found.empty() && !ErrorRecoveryLookup && !getLangOpts().MicrosoftMode) {
// We haven't found anything, and we're not recovering from a
// different kind of error, so look for typos.
DeclarationName Name = Found.getLookupName();
NestedNameSpecifierValidatorCCC Validator(*this);
- TypoCorrection Corrected;
Found.clear();
- if ((Corrected = CorrectTypo(Found.getLookupNameInfo(),
- Found.getLookupKind(), S, &SS, Validator,
- LookupCtx, EnteringContext))) {
- std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
- std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
- if (LookupCtx)
- Diag(Found.getNameLoc(), diag::err_no_member_suggest)
- << Name << LookupCtx << CorrectedQuotedStr << SS.getRange()
- << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
- CorrectedStr);
- else
- Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest)
- << Name << CorrectedQuotedStr
- << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
-
- if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
- Diag(ND->getLocation(), diag::note_previous_decl) << CorrectedQuotedStr;
+ if (TypoCorrection Corrected =
+ CorrectTypo(Found.getLookupNameInfo(), Found.getLookupKind(), S,
+ &SS, Validator, LookupCtx, EnteringContext)) {
+ if (LookupCtx) {
+ bool DroppedSpecifier =
+ Corrected.WillReplaceSpecifier() &&
+ Name.getAsString() == Corrected.getAsString(getLangOpts());
+ if (DroppedSpecifier)
+ SS.clear();
+ diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest)
+ << Name << LookupCtx << DroppedSpecifier
+ << SS.getRange());
+ } else
+ diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
+ << Name);
+
+ if (NamedDecl *ND = Corrected.getCorrectionDecl())
Found.addDecl(ND);
- }
Found.setLookupName(Corrected.getCorrection());
} else {
Found.setLookupName(&Identifier);
@@ -658,7 +646,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
// public:
// void foo() { D::foo2(); }
// };
- if (getLangOpts().MicrosoftExt) {
+ if (getLangOpts().MicrosoftMode) {
DeclContext *DC = LookupCtx ? LookupCtx : CurContext;
if (DC->isDependentContext() && DC->isFunctionOrMethod()) {
SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
index eb11a577cb0a..ba00b712aad5 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
@@ -200,8 +200,9 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
unsigned &msg, CastKind &Kind,
CXXCastPath &BasePath,
bool ListInitialization);
-static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
- bool CStyle, unsigned &msg);
+static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
+ QualType DestType, bool CStyle,
+ unsigned &msg);
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
@@ -242,7 +243,9 @@ 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.get()->isTypeDependent();
+ bool TypeDependent = DestType->isDependentType() ||
+ Ex.get()->isTypeDependent() ||
+ Ex.get()->isValueDependent();
CastOperation Op(*this, DestType, E);
Op.OpRange = SourceRange(OpLoc, Parens.getEnd());
@@ -383,11 +386,6 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
SourceRange opRange, Expr *src, QualType destType,
bool listInitialization) {
- 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,
listInitialization))
@@ -515,8 +513,8 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
QualType SrcConstruct = Self.Context.VoidTy;
QualType DestConstruct = Self.Context.VoidTy;
ASTContext &Context = Self.Context;
- for (SmallVector<Qualifiers, 8>::reverse_iterator i1 = cv1.rbegin(),
- i2 = cv2.rbegin();
+ for (SmallVectorImpl<Qualifiers>::reverse_iterator i1 = cv1.rbegin(),
+ i2 = cv2.rbegin();
i1 != cv1.rend(); ++i1, ++i2) {
SrcConstruct
= Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1));
@@ -558,6 +556,7 @@ void CastOperation::CheckDynamicCast() {
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr)
<< this->DestType << DestRange;
+ SrcExpr = ExprError();
return;
}
@@ -567,11 +566,14 @@ void CastOperation::CheckDynamicCast() {
} else if (DestRecord) {
if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee,
diag::err_bad_dynamic_cast_incomplete,
- DestRange))
+ DestRange)) {
+ SrcExpr = ExprError();
return;
+ }
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
<< DestPointee.getUnqualifiedType() << DestRange;
+ SrcExpr = ExprError();
return;
}
@@ -587,6 +589,7 @@ void CastOperation::CheckDynamicCast() {
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr)
<< OrigSrcType << SrcExpr.get()->getSourceRange();
+ SrcExpr = ExprError();
return;
}
} else if (DestReference->isLValueReferenceType()) {
@@ -603,11 +606,14 @@ void CastOperation::CheckDynamicCast() {
if (SrcRecord) {
if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee,
diag::err_bad_dynamic_cast_incomplete,
- SrcExpr.get()))
+ SrcExpr.get())) {
+ SrcExpr = ExprError();
return;
+ }
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
<< SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange();
+ SrcExpr = ExprError();
return;
}
@@ -621,6 +627,7 @@ void CastOperation::CheckDynamicCast() {
if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) {
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away)
<< CT_Dynamic << OrigSrcType << this->DestType << OpRange;
+ SrcExpr = ExprError();
return;
}
@@ -636,8 +643,10 @@ void CastOperation::CheckDynamicCast() {
if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) {
if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee,
OpRange.getBegin(), OpRange,
- &BasePath))
- return;
+ &BasePath)) {
+ SrcExpr = ExprError();
+ return;
+ }
Kind = CK_DerivedToBase;
@@ -655,10 +664,20 @@ void CastOperation::CheckDynamicCast() {
if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic)
<< SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange();
+ SrcExpr = ExprError();
}
Self.MarkVTableUsed(OpRange.getBegin(),
cast<CXXRecordDecl>(SrcRecord->getDecl()));
+ // dynamic_cast is not available with -fno-rtti.
+ // As an exception, dynamic_cast to void* is available because it doesn't
+ // use RTTI.
+ if (!Self.getLangOpts().RTTI && !DestPointee->isVoidType()) {
+ Self.Diag(OpRange.getBegin(), diag::err_no_dynamic_cast_with_fno_rtti);
+ SrcExpr = ExprError();
+ return;
+ }
+
// Done. Everything else is run-time checks.
Kind = CK_Dynamic;
}
@@ -677,10 +696,12 @@ void CastOperation::CheckConstCast() {
return;
unsigned msg = diag::err_bad_cxx_cast_generic;
- if (TryConstCast(Self, SrcExpr.get(), DestType, /*CStyle*/false, msg) != TC_Success
- && msg != 0)
+ if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success
+ && msg != 0) {
Self.Diag(OpRange.getBegin(), msg) << CT_Const
<< SrcExpr.get()->getType() << DestType << OpRange;
+ SrcExpr = ExprError();
+ }
}
/// Check that a reinterpret_cast\<DestType\>(SrcExpr) is not used as upcast
@@ -758,6 +779,7 @@ static void DiagnoseReinterpretUpDownCast(Sema &Self, const Expr *SrcExpr,
VirtualBase = VirtualBase && IsVirtual;
}
+ (void) NonZeroOffset; // Silence set but not used warning.
assert((VirtualBase || NonZeroOffset) &&
"Should have returned if has non-virtual base with zero offset");
@@ -768,10 +790,10 @@ static void DiagnoseReinterpretUpDownCast(Sema &Self, const Expr *SrcExpr,
SourceLocation BeginLoc = OpRange.getBegin();
Self.Diag(BeginLoc, diag::warn_reinterpret_different_from_static)
- << DerivedType << BaseType << !VirtualBase << ReinterpretKind
+ << DerivedType << BaseType << !VirtualBase << int(ReinterpretKind)
<< OpRange;
Self.Diag(BeginLoc, diag::note_reinterpret_updowncast_use_static)
- << ReinterpretKind
+ << int(ReinterpretKind)
<< FixItHint::CreateReplacement(BeginLoc, "static_cast");
}
@@ -807,6 +829,7 @@ void CastOperation::CheckReinterpretCast() {
diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(),
DestType, /*listInitialization=*/false);
}
+ SrcExpr = ExprError();
} else if (tcr == TC_Success) {
if (Self.getLangOpts().ObjCAutoRefCount)
checkObjCARCConversion(Sema::CCK_OtherCast);
@@ -868,6 +891,7 @@ void CastOperation::CheckStaticCast() {
diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType,
/*listInitialization=*/false);
}
+ SrcExpr = ExprError();
} else if (tcr == TC_Success) {
if (Kind == CK_BitCast)
checkCastAlign();
@@ -1447,12 +1471,26 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
/// TryConstCast - See if a const_cast from source to destination is allowed,
/// and perform it if it is.
-static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
- bool CStyle, unsigned &msg) {
+static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
+ QualType DestType, bool CStyle,
+ unsigned &msg) {
DestType = Self.Context.getCanonicalType(DestType);
- QualType SrcType = SrcExpr->getType();
+ QualType SrcType = SrcExpr.get()->getType();
+ bool NeedToMaterializeTemporary = false;
+
if (const ReferenceType *DestTypeTmp =DestType->getAs<ReferenceType>()) {
- if (isa<LValueReferenceType>(DestTypeTmp) && !SrcExpr->isLValue()) {
+ // C++11 5.2.11p4:
+ // if a pointer to T1 can be explicitly converted to the type "pointer to
+ // T2" using a const_cast, then the following conversions can also be
+ // made:
+ // -- an lvalue of type T1 can be explicitly converted to an lvalue of
+ // type T2 using the cast const_cast<T2&>;
+ // -- a glvalue of type T1 can be explicitly converted to an xvalue of
+ // type T2 using the cast const_cast<T2&&>; and
+ // -- if T1 is a class type, a prvalue of type T1 can be explicitly
+ // converted to an xvalue of type T2 using the cast const_cast<T2&&>.
+
+ if (isa<LValueReferenceType>(DestTypeTmp) && !SrcExpr.get()->isLValue()) {
// Cannot const_cast non-lvalue to lvalue reference type. But if this
// is C-style, static_cast might find a way, so we simply suggest a
// message and tell the parent to keep searching.
@@ -1460,18 +1498,29 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
return TC_NotApplicable;
}
+ if (isa<RValueReferenceType>(DestTypeTmp) && SrcExpr.get()->isRValue()) {
+ if (!SrcType->isRecordType()) {
+ // Cannot const_cast non-class prvalue to rvalue reference type. But if
+ // this is C-style, static_cast can do this.
+ msg = diag::err_bad_cxx_cast_rvalue;
+ return TC_NotApplicable;
+ }
+
+ // Materialize the class prvalue so that the const_cast can bind a
+ // reference to it.
+ NeedToMaterializeTemporary = true;
+ }
+
// It's not completely clear under the standard whether we can
// const_cast bit-field gl-values. Doing so would not be
// intrinsically complicated, but for now, we say no for
// consistency with other compilers and await the word of the
// committee.
- if (SrcExpr->refersToBitField()) {
+ if (SrcExpr.get()->refersToBitField()) {
msg = diag::err_bad_cxx_cast_bitfield;
return TC_NotApplicable;
}
- // C++ 5.2.11p4: An lvalue of type T1 can be [cast] to an lvalue of type T2
- // [...] if a pointer to T1 can be [cast] to the type pointer to T2.
DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
SrcType = Self.Context.getPointerType(SrcType);
}
@@ -1525,6 +1574,13 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
if (SrcType != DestType)
return TC_NotApplicable;
+ if (NeedToMaterializeTemporary)
+ // This is a const_cast from a class prvalue to an rvalue reference type.
+ // Materialize a temporary to store the result of the conversion.
+ SrcExpr = new (Self.Context) MaterializeTemporaryExpr(
+ SrcType, SrcExpr.take(), /*IsLValueReference*/ false,
+ /*ExtendingDecl*/ 0);
+
return TC_Success;
}
@@ -1614,8 +1670,18 @@ static void checkIntToPointerCast(bool CStyle, SourceLocation Loc,
&& !SrcType->isBooleanType()
&& !SrcType->isEnumeralType()
&& !SrcExpr->isIntegerConstantExpr(Self.Context)
- && Self.Context.getTypeSize(DestType) > Self.Context.getTypeSize(SrcType))
- Self.Diag(Loc, diag::warn_int_to_pointer_cast) << SrcType << DestType;
+ && Self.Context.getTypeSize(DestType) >
+ Self.Context.getTypeSize(SrcType)) {
+ // Separate between casts to void* and non-void* pointers.
+ // Some APIs use (abuse) void* for something like a user context,
+ // and often that value is an integer even if it isn't a pointer itself.
+ // Having a separate warning flag allows users to control the warning
+ // for their workflow.
+ unsigned Diag = DestType->isVoidPointerType() ?
+ diag::warn_int_to_void_pointer_cast
+ : diag::warn_int_to_pointer_cast;
+ Self.Diag(Loc, Diag) << SrcType << DestType;
+ }
}
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
@@ -1803,10 +1869,12 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
assert(srcIsPtr && "One type must be a pointer");
// C++ 5.2.10p4: A pointer can be explicitly converted to any integral
// type large enough to hold it; except in Microsoft mode, where the
- // integral type size doesn't matter.
+ // integral type size doesn't matter (except we don't allow bool).
+ bool MicrosoftException = Self.getLangOpts().MicrosoftExt &&
+ !DestType->isBooleanType();
if ((Self.Context.getTypeSize(SrcType) >
Self.Context.getTypeSize(DestType)) &&
- !Self.getLangOpts().MicrosoftExt) {
+ !MicrosoftException) {
msg = diag::err_bad_reinterpret_cast_small_int;
return TC_Failed;
}
@@ -1940,14 +2008,12 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
}
SrcExpr = Self.IgnoredValueConversions(SrcExpr.take());
- if (SrcExpr.isInvalid())
- return;
-
return;
}
// If the type is dependent, we won't do any other semantic analysis now.
- if (DestType->isDependentType() || SrcExpr.get()->isTypeDependent()) {
+ if (DestType->isDependentType() || SrcExpr.get()->isTypeDependent() ||
+ SrcExpr.get()->isValueDependent()) {
assert(Kind == CK_Dependent);
return;
}
@@ -1980,8 +2046,10 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
// even if a cast resulting from that interpretation is ill-formed.
// In plain language, this means trying a const_cast ...
unsigned msg = diag::err_bad_cxx_cast_generic;
- TryCastResult tcr = TryConstCast(Self, SrcExpr.get(), DestType,
+ TryCastResult tcr = TryConstCast(Self, SrcExpr, DestType,
/*CStyle*/true, msg);
+ if (SrcExpr.isInvalid())
+ return;
if (tcr == TC_Success)
Kind = CK_NoOp;
@@ -2298,9 +2366,9 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
return ExprError();
if (CXXConstructExpr *ConstructExpr = dyn_cast<CXXConstructExpr>(Op.SrcExpr.get()))
- ConstructExpr->setParenRange(SourceRange(LPLoc, RPLoc));
+ ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc));
return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType,
- Op.ValueKind, CastTypeInfo, Op.DestRange.getBegin(),
- Op.Kind, Op.SrcExpr.take(), &Op.BasePath, RPLoc));
+ Op.ValueKind, CastTypeInfo, Op.Kind,
+ Op.SrcExpr.take(), &Op.BasePath, LPLoc, RPLoc));
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
index 7b5f4f0705bc..0530a043953f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -32,9 +32,9 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/Sema.h"
-#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/raw_ostream.h"
#include <limits>
@@ -95,6 +95,22 @@ static bool SemaBuiltinAnnotation(Sema &S, CallExpr *TheCall) {
return false;
}
+/// Check that the argument to __builtin_addressof is a glvalue, and set the
+/// result type to the corresponding pointer type.
+static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) {
+ if (checkArgCount(S, TheCall, 1))
+ return true;
+
+ ExprResult Arg(S.Owned(TheCall->getArg(0)));
+ QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getLocStart());
+ if (ResultType.isNull())
+ return true;
+
+ TheCall->setArg(0, Arg.take());
+ TheCall->setType(ResultType);
+ return false;
+}
+
ExprResult
Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
ExprResult TheCallResult(Owned(TheCall));
@@ -275,6 +291,10 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (SemaBuiltinAnnotation(*this, TheCall))
return ExprError();
break;
+ case Builtin::BI__builtin_addressof:
+ if (SemaBuiltinAddressof(*this, TheCall))
+ return ExprError();
+ break;
}
// Since the target specific builtins for each arch overlap, only check those
@@ -286,6 +306,10 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
+ case llvm::Triple::aarch64:
+ if (CheckAArch64BuiltinFunctionCall(BuiltinID, TheCall))
+ return ExprError();
+ break;
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@@ -315,6 +339,7 @@ static unsigned RFT(unsigned t, bool shift = false) {
case NeonTypeFlags::Int32:
return shift ? 31 : (2 << IsQuad) - 1;
case NeonTypeFlags::Int64:
+ case NeonTypeFlags::Poly64:
return shift ? 63 : (1 << IsQuad) - 1;
case NeonTypeFlags::Float16:
assert(!shift && "cannot shift float types!");
@@ -322,6 +347,9 @@ static unsigned RFT(unsigned t, bool shift = false) {
case NeonTypeFlags::Float32:
assert(!shift && "cannot shift float types!");
return (2 << IsQuad) - 1;
+ case NeonTypeFlags::Float64:
+ assert(!shift && "cannot shift float types!");
+ return (1 << IsQuad) - 1;
}
llvm_unreachable("Invalid NeonTypeFlag!");
}
@@ -329,7 +357,8 @@ static unsigned RFT(unsigned t, bool shift = false) {
/// getNeonEltType - Return the QualType corresponding to the elements of
/// the vector type specified by the NeonTypeFlags. This is used to check
/// the pointer arguments for Neon load/store intrinsics.
-static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context) {
+static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context,
+ bool IsAArch64) {
switch (Flags.getEltType()) {
case NeonTypeFlags::Int8:
return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy;
@@ -340,20 +369,213 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context) {
case NeonTypeFlags::Int64:
return Flags.isUnsigned() ? Context.UnsignedLongLongTy : Context.LongLongTy;
case NeonTypeFlags::Poly8:
- return Context.SignedCharTy;
+ return IsAArch64 ? Context.UnsignedCharTy : Context.SignedCharTy;
case NeonTypeFlags::Poly16:
- return Context.ShortTy;
+ return IsAArch64 ? Context.UnsignedShortTy : Context.ShortTy;
+ case NeonTypeFlags::Poly64:
+ return Context.UnsignedLongLongTy;
case NeonTypeFlags::Float16:
- return Context.UnsignedShortTy;
+ return Context.HalfTy;
case NeonTypeFlags::Float32:
return Context.FloatTy;
+ case NeonTypeFlags::Float64:
+ return Context.DoubleTy;
}
llvm_unreachable("Invalid NeonTypeFlag!");
}
+bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
+ CallExpr *TheCall) {
+
+ llvm::APSInt Result;
+
+ uint64_t mask = 0;
+ unsigned TV = 0;
+ int PtrArgNum = -1;
+ bool HasConstPtr = false;
+ switch (BuiltinID) {
+#define GET_NEON_AARCH64_OVERLOAD_CHECK
+#include "clang/Basic/arm_neon.inc"
+#undef GET_NEON_AARCH64_OVERLOAD_CHECK
+ }
+
+ // For NEON intrinsics which are overloaded on vector element type, validate
+ // the immediate which specifies which variant to emit.
+ unsigned ImmArg = TheCall->getNumArgs() - 1;
+ if (mask) {
+ if (SemaBuiltinConstantArg(TheCall, ImmArg, Result))
+ return true;
+
+ TV = Result.getLimitedValue(64);
+ if ((TV > 63) || (mask & (1ULL << TV)) == 0)
+ return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code)
+ << TheCall->getArg(ImmArg)->getSourceRange();
+ }
+
+ if (PtrArgNum >= 0) {
+ // Check that pointer arguments have the specified type.
+ Expr *Arg = TheCall->getArg(PtrArgNum);
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg))
+ Arg = ICE->getSubExpr();
+ ExprResult RHS = DefaultFunctionArrayLvalueConversion(Arg);
+ QualType RHSTy = RHS.get()->getType();
+ QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context, true);
+ if (HasConstPtr)
+ EltTy = EltTy.withConst();
+ QualType LHSTy = Context.getPointerType(EltTy);
+ AssignConvertType ConvTy;
+ ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
+ if (RHS.isInvalid())
+ return true;
+ if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), LHSTy, RHSTy,
+ RHS.get(), AA_Assigning))
+ return true;
+ }
+
+ // For NEON intrinsics which take an immediate value as part of the
+ // instruction, range check them here.
+ unsigned i = 0, l = 0, u = 0;
+ switch (BuiltinID) {
+ default:
+ return false;
+#define GET_NEON_AARCH64_IMMEDIATE_CHECK
+#include "clang/Basic/arm_neon.inc"
+#undef GET_NEON_AARCH64_IMMEDIATE_CHECK
+ }
+ ;
+
+ // We can't check the value of a dependent argument.
+ if (TheCall->getArg(i)->isTypeDependent() ||
+ TheCall->getArg(i)->isValueDependent())
+ return false;
+
+ // Check that the immediate argument is actually a constant.
+ if (SemaBuiltinConstantArg(TheCall, i, Result))
+ return true;
+
+ // Range check against the upper/lower values for this isntruction.
+ unsigned Val = Result.getZExtValue();
+ if (Val < l || Val > (u + l))
+ return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+ << l << u + l << TheCall->getArg(i)->getSourceRange();
+
+ return false;
+}
+
+bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall) {
+ assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
+ BuiltinID == ARM::BI__builtin_arm_strex) &&
+ "unexpected ARM builtin");
+ bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex;
+
+ DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
+
+ // Ensure that we have the proper number of arguments.
+ if (checkArgCount(*this, TheCall, IsLdrex ? 1 : 2))
+ return true;
+
+ // Inspect the pointer argument of the atomic builtin. This should always be
+ // a pointer type, whose element is an integral scalar or pointer type.
+ // Because it is a pointer type, we don't have to worry about any implicit
+ // casts here.
+ Expr *PointerArg = TheCall->getArg(IsLdrex ? 0 : 1);
+ ExprResult PointerArgRes = DefaultFunctionArrayLvalueConversion(PointerArg);
+ if (PointerArgRes.isInvalid())
+ return true;
+ PointerArg = PointerArgRes.take();
+
+ const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
+ if (!pointerType) {
+ Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer)
+ << PointerArg->getType() << PointerArg->getSourceRange();
+ return true;
+ }
+
+ // ldrex takes a "const volatile T*" and strex takes a "volatile T*". Our next
+ // task is to insert the appropriate casts into the AST. First work out just
+ // what the appropriate type is.
+ QualType ValType = pointerType->getPointeeType();
+ QualType AddrType = ValType.getUnqualifiedType().withVolatile();
+ if (IsLdrex)
+ AddrType.addConst();
+
+ // Issue a warning if the cast is dodgy.
+ CastKind CastNeeded = CK_NoOp;
+ if (!AddrType.isAtLeastAsQualifiedAs(ValType)) {
+ CastNeeded = CK_BitCast;
+ Diag(DRE->getLocStart(), diag::ext_typecheck_convert_discards_qualifiers)
+ << PointerArg->getType()
+ << Context.getPointerType(AddrType)
+ << AA_Passing << PointerArg->getSourceRange();
+ }
+
+ // Finally, do the cast and replace the argument with the corrected version.
+ AddrType = Context.getPointerType(AddrType);
+ PointerArgRes = ImpCastExprToType(PointerArg, AddrType, CastNeeded);
+ if (PointerArgRes.isInvalid())
+ return true;
+ PointerArg = PointerArgRes.take();
+
+ TheCall->setArg(IsLdrex ? 0 : 1, PointerArg);
+
+ // In general, we allow ints, floats and pointers to be loaded and stored.
+ if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
+ !ValType->isBlockPointerType() && !ValType->isFloatingType()) {
+ Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
+ << PointerArg->getType() << PointerArg->getSourceRange();
+ return true;
+ }
+
+ // But ARM doesn't have instructions to deal with 128-bit versions.
+ if (Context.getTypeSize(ValType) > 64) {
+ Diag(DRE->getLocStart(), diag::err_atomic_exclusive_builtin_pointer_size)
+ << PointerArg->getType() << PointerArg->getSourceRange();
+ return true;
+ }
+
+ switch (ValType.getObjCLifetime()) {
+ case Qualifiers::OCL_None:
+ case Qualifiers::OCL_ExplicitNone:
+ // okay
+ break;
+
+ case Qualifiers::OCL_Weak:
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Autoreleasing:
+ Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership)
+ << ValType << PointerArg->getSourceRange();
+ return true;
+ }
+
+
+ if (IsLdrex) {
+ TheCall->setType(ValType);
+ return false;
+ }
+
+ // Initialize the argument to be stored.
+ ExprResult ValArg = TheCall->getArg(0);
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ Context, ValType, /*consume*/ false);
+ ValArg = PerformCopyInitialization(Entity, SourceLocation(), ValArg);
+ if (ValArg.isInvalid())
+ return true;
+ TheCall->setArg(0, ValArg.get());
+
+ // __builtin_arm_strex always returns an int. It's marked as such in the .def,
+ // but the custom checker bypasses all default analysis.
+ TheCall->setType(Context.IntTy);
+ return false;
+}
+
bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
llvm::APSInt Result;
+ if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
+ BuiltinID == ARM::BI__builtin_arm_strex) {
+ return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall);
+ }
+
uint64_t mask = 0;
unsigned TV = 0;
int PtrArgNum = -1;
@@ -384,7 +606,7 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
Arg = ICE->getSubExpr();
ExprResult RHS = DefaultFunctionArrayLvalueConversion(Arg);
QualType RHSTy = RHS.get()->getType();
- QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context);
+ QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context, false);
if (HasConstPtr)
EltTy = EltTy.withConst();
QualType LHSTy = Context.getPointerType(EltTy);
@@ -406,6 +628,8 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case ARM::BI__builtin_arm_usat: i = 1; u = 31; break;
case ARM::BI__builtin_arm_vcvtr_f:
case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break;
+ case ARM::BI__builtin_arm_dmb:
+ case ARM::BI__builtin_arm_dsb: l = 0; u = 15; break;
#define GET_NEON_IMMEDIATE_CHECK
#include "clang/Basic/arm_neon.inc"
#undef GET_NEON_IMMEDIATE_CHECK
@@ -494,36 +718,50 @@ void Sema::checkCall(NamedDecl *FDecl,
SourceLocation Loc,
SourceRange Range,
VariadicCallType CallType) {
+ // FIXME: We should check as much as we can in the template definition.
if (CurContext->isDependentContext())
return;
// Printf and scanf checking.
- bool HandledFormatString = false;
- for (specific_attr_iterator<FormatAttr>
- I = FDecl->specific_attr_begin<FormatAttr>(),
- E = FDecl->specific_attr_end<FormatAttr>(); I != E ; ++I)
- if (CheckFormatArguments(*I, Args, IsMemberFunction, CallType, Loc, Range))
- HandledFormatString = true;
+ llvm::SmallBitVector CheckedVarArgs;
+ if (FDecl) {
+ for (specific_attr_iterator<FormatAttr>
+ I = FDecl->specific_attr_begin<FormatAttr>(),
+ E = FDecl->specific_attr_end<FormatAttr>();
+ I != E; ++I) {
+ // Only create vector if there are format attributes.
+ CheckedVarArgs.resize(Args.size());
+
+ CheckFormatArguments(*I, Args, IsMemberFunction, CallType, Loc, Range,
+ CheckedVarArgs);
+ }
+ }
// Refuse POD arguments that weren't caught by the format string
// checks above.
- if (!HandledFormatString && CallType != VariadicDoesNotApply)
+ if (CallType != VariadicDoesNotApply) {
for (unsigned ArgIdx = NumProtoArgs; ArgIdx < Args.size(); ++ArgIdx) {
// Args[ArgIdx] can be null in malformed code.
- if (const Expr *Arg = Args[ArgIdx])
- variadicArgumentPODCheck(Arg, CallType);
+ if (const Expr *Arg = Args[ArgIdx]) {
+ if (CheckedVarArgs.empty() || !CheckedVarArgs[ArgIdx])
+ checkVariadicArgument(Arg, CallType);
+ }
}
+ }
- for (specific_attr_iterator<NonNullAttr>
- I = FDecl->specific_attr_begin<NonNullAttr>(),
- E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I)
- CheckNonNullArguments(*I, Args.data(), Loc);
+ if (FDecl) {
+ for (specific_attr_iterator<NonNullAttr>
+ I = FDecl->specific_attr_begin<NonNullAttr>(),
+ E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I)
+ CheckNonNullArguments(*I, Args.data(), Loc);
- // Type safety checking.
- for (specific_attr_iterator<ArgumentWithTypeTagAttr>
- i = FDecl->specific_attr_begin<ArgumentWithTypeTagAttr>(),
- e = FDecl->specific_attr_end<ArgumentWithTypeTagAttr>(); i != e; ++i) {
- CheckArgumentWithTypeTag(*i, Args.data());
+ // Type safety checking.
+ for (specific_attr_iterator<ArgumentWithTypeTagAttr>
+ i = FDecl->specific_attr_begin<ArgumentWithTypeTagAttr>(),
+ e = FDecl->specific_attr_end<ArgumentWithTypeTagAttr>();
+ i != e; ++i) {
+ CheckArgumentWithTypeTag(*i, Args.data());
+ }
}
}
@@ -597,18 +835,24 @@ bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac,
return false;
}
-bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall,
- const FunctionProtoType *Proto) {
+bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
+ const FunctionProtoType *Proto) {
const VarDecl *V = dyn_cast<VarDecl>(NDecl);
if (!V)
return false;
QualType Ty = V->getType();
- if (!Ty->isBlockPointerType())
+ if (!Ty->isBlockPointerType() && !Ty->isFunctionPointerType())
return false;
- VariadicCallType CallType =
- Proto && Proto->isVariadic() ? VariadicBlock : VariadicDoesNotApply ;
+ VariadicCallType CallType;
+ if (!Proto || !Proto->isVariadic()) {
+ CallType = VariadicDoesNotApply;
+ } else if (Ty->isBlockPointerType()) {
+ CallType = VariadicBlock;
+ } else { // Ty->isFunctionPointerType()
+ CallType = VariadicFunction;
+ }
unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0;
checkCall(NDecl,
@@ -621,6 +865,23 @@ bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall,
return false;
}
+/// Checks function calls when a FunctionDecl or a NamedDecl is not available,
+/// such as function pointers returned from functions.
+bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) {
+ VariadicCallType CallType = getVariadicCallType(/*FDecl=*/0, Proto,
+ TheCall->getCallee());
+ unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0;
+
+ checkCall(/*FDecl=*/0,
+ llvm::makeArrayRef<const Expr *>(TheCall->getArgs(),
+ TheCall->getNumArgs()),
+ NumProtoArgs, /*IsMemberFunction=*/false,
+ TheCall->getRParenLoc(),
+ TheCall->getCallee()->getSourceRange(), CallType);
+
+ return false;
+}
+
ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
AtomicExpr::AtomicOp Op) {
CallExpr *TheCall = cast<CallExpr>(TheCallResult.get());
@@ -786,7 +1047,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
return ExprError();
}
- if (!IsC11 && !AtomTy.isTriviallyCopyableType(Context)) {
+ if (!IsC11 && !AtomTy.isTriviallyCopyableType(Context) &&
+ !AtomTy->isScalarType()) {
// For GNU atomics, require a trivially-copyable type. This is not part of
// the GNU atomics specification, but we enforce it for sanity.
Diag(DRE->getLocStart(), diag::err_atomic_op_needs_trivial_copy)
@@ -908,10 +1170,18 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
SubExprs.push_back(TheCall->getArg(3)); // Weak
break;
}
+
+ AtomicExpr *AE = new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(),
+ SubExprs, ResultType, Op,
+ TheCall->getRParenLoc());
+
+ if ((Op == AtomicExpr::AO__c11_atomic_load ||
+ (Op == AtomicExpr::AO__c11_atomic_store)) &&
+ Context.AtomicUsesUnsupportedLibcall(AE))
+ Diag(AE->getLocStart(), diag::err_atomic_load_store_uses_lib) <<
+ ((Op == AtomicExpr::AO__c11_atomic_load) ? 0 : 1);
- return Owned(new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(),
- SubExprs, ResultType, Op,
- TheCall->getRParenLoc()));
+ return Owned(AE);
}
@@ -1355,6 +1625,11 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
bool SecondArgIsLastNamedArgument = false;
const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts();
+ // These are valid if SecondArgIsLastNamedArgument is false after the next
+ // block.
+ QualType Type;
+ SourceLocation ParamLoc;
+
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) {
if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
// FIXME: This isn't correct for methods (results in bogus warning).
@@ -1367,12 +1642,22 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
else
LastArg = *(getCurMethodDecl()->param_end()-1);
SecondArgIsLastNamedArgument = PV == LastArg;
+
+ Type = PV->getType();
+ ParamLoc = PV->getLocation();
}
}
if (!SecondArgIsLastNamedArgument)
Diag(TheCall->getArg(1)->getLocStart(),
diag::warn_second_parameter_of_va_start_not_last_named_argument);
+ else if (Type->isReferenceType()) {
+ Diag(Arg->getLocStart(),
+ diag::warn_va_start_of_reference_type_is_undefined);
+ Diag(ParamLoc, diag::note_parameter_type) << Type;
+ }
+
+ TheCall->setType(Context.VoidTy);
return false;
}
@@ -1464,8 +1749,8 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
if (TheCall->getNumArgs() < 2)
return ExprError(Diag(TheCall->getLocEnd(),
diag::err_typecheck_call_too_few_args_at_least)
- << 0 /*function call*/ << 2 << TheCall->getNumArgs()
- << TheCall->getSourceRange());
+ << 0 /*function call*/ << 2 << TheCall->getNumArgs()
+ << TheCall->getSourceRange());
// Determine which of the following types of shufflevector we're checking:
// 1) unary, vector mask: (lhs, mask)
@@ -1473,19 +1758,18 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
// 3) binary, scalar mask: (lhs, rhs, index, ..., index)
QualType resType = TheCall->getArg(0)->getType();
unsigned numElements = 0;
-
+
if (!TheCall->getArg(0)->isTypeDependent() &&
!TheCall->getArg(1)->isTypeDependent()) {
QualType LHSType = TheCall->getArg(0)->getType();
QualType RHSType = TheCall->getArg(1)->getType();
-
- if (!LHSType->isVectorType() || !RHSType->isVectorType()) {
- Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector)
- << SourceRange(TheCall->getArg(0)->getLocStart(),
- TheCall->getArg(1)->getLocEnd());
- return ExprError();
- }
-
+
+ if (!LHSType->isVectorType() || !RHSType->isVectorType())
+ return ExprError(Diag(TheCall->getLocStart(),
+ diag::err_shufflevector_non_vector)
+ << SourceRange(TheCall->getArg(0)->getLocStart(),
+ TheCall->getArg(1)->getLocEnd()));
+
numElements = LHSType->getAs<VectorType>()->getNumElements();
unsigned numResElements = TheCall->getNumArgs() - 2;
@@ -1493,18 +1777,17 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
// with mask. If so, verify that RHS is an integer vector type with the
// same number of elts as lhs.
if (TheCall->getNumArgs() == 2) {
- if (!RHSType->hasIntegerRepresentation() ||
+ if (!RHSType->hasIntegerRepresentation() ||
RHSType->getAs<VectorType>()->getNumElements() != numElements)
- Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector)
- << SourceRange(TheCall->getArg(1)->getLocStart(),
- TheCall->getArg(1)->getLocEnd());
- numResElements = numElements;
- }
- else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) {
- Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector)
- << SourceRange(TheCall->getArg(0)->getLocStart(),
- TheCall->getArg(1)->getLocEnd());
- return ExprError();
+ return ExprError(Diag(TheCall->getLocStart(),
+ diag::err_shufflevector_incompatible_vector)
+ << SourceRange(TheCall->getArg(1)->getLocStart(),
+ TheCall->getArg(1)->getLocEnd()));
+ } else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) {
+ return ExprError(Diag(TheCall->getLocStart(),
+ diag::err_shufflevector_incompatible_vector)
+ << SourceRange(TheCall->getArg(0)->getLocStart(),
+ TheCall->getArg(1)->getLocEnd()));
} else if (numElements != numResElements) {
QualType eltType = LHSType->getAs<VectorType>()->getElementType();
resType = Context.getVectorType(eltType, numResElements,
@@ -1520,13 +1803,17 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
llvm::APSInt Result(32);
if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context))
return ExprError(Diag(TheCall->getLocStart(),
- diag::err_shufflevector_nonconstant_argument)
- << TheCall->getArg(i)->getSourceRange());
+ diag::err_shufflevector_nonconstant_argument)
+ << TheCall->getArg(i)->getSourceRange());
+
+ // Allow -1 which will be translated to undef in the IR.
+ if (Result.isSigned() && Result.isAllOnesValue())
+ continue;
if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2)
return ExprError(Diag(TheCall->getLocStart(),
- diag::err_shufflevector_argument_too_large)
- << TheCall->getArg(i)->getSourceRange());
+ diag::err_shufflevector_argument_too_large)
+ << TheCall->getArg(i)->getSourceRange());
}
SmallVector<Expr*, 32> exprs;
@@ -1541,6 +1828,37 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
TheCall->getRParenLoc()));
}
+/// SemaConvertVectorExpr - Handle __builtin_convertvector
+ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc) {
+ ExprValueKind VK = VK_RValue;
+ ExprObjectKind OK = OK_Ordinary;
+ QualType DstTy = TInfo->getType();
+ QualType SrcTy = E->getType();
+
+ if (!SrcTy->isVectorType() && !SrcTy->isDependentType())
+ return ExprError(Diag(BuiltinLoc,
+ diag::err_convertvector_non_vector)
+ << E->getSourceRange());
+ if (!DstTy->isVectorType() && !DstTy->isDependentType())
+ return ExprError(Diag(BuiltinLoc,
+ diag::err_convertvector_non_vector_type));
+
+ if (!SrcTy->isDependentType() && !DstTy->isDependentType()) {
+ unsigned SrcElts = SrcTy->getAs<VectorType>()->getNumElements();
+ unsigned DstElts = DstTy->getAs<VectorType>()->getNumElements();
+ if (SrcElts != DstElts)
+ return ExprError(Diag(BuiltinLoc,
+ diag::err_convertvector_incompatible_vector)
+ << E->getSourceRange());
+ }
+
+ return Owned(new (Context) ConvertVectorExpr(E, TInfo, DstTy, VK, OK,
+ BuiltinLoc, RParenLoc));
+
+}
+
/// SemaBuiltinPrefetch - Handle __builtin_prefetch.
// This is declared to take (const void*, ...) and can take two
// optional constant int args.
@@ -1642,28 +1960,36 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
return false;
}
+namespace {
+enum StringLiteralCheckType {
+ SLCT_NotALiteral,
+ SLCT_UncheckedLiteral,
+ SLCT_CheckedLiteral
+};
+}
+
// Determine if an expression is a string literal or constant string.
// If this function returns false on the arguments to a function expecting a
// format string, we will usually need to emit a warning.
// True string literals are then checked by CheckFormatString.
-Sema::StringLiteralCheckType
-Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args,
- bool HasVAListArg,
- unsigned format_idx, unsigned firstDataArg,
- FormatStringType Type, VariadicCallType CallType,
- bool inFunctionCall) {
+static StringLiteralCheckType
+checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
+ bool HasVAListArg, unsigned format_idx,
+ unsigned firstDataArg, Sema::FormatStringType Type,
+ Sema::VariadicCallType CallType, bool InFunctionCall,
+ llvm::SmallBitVector &CheckedVarArgs) {
tryAgain:
if (E->isTypeDependent() || E->isValueDependent())
return SLCT_NotALiteral;
E = E->IgnoreParenCasts();
- if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
+ if (E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull))
// Technically -Wformat-nonliteral does not warn about this case.
// The behavior of printf and friends in this case is implementation
// dependent. Ideally if the format string cannot be null then
// it should have a 'nonnull' attribute in the function prototype.
- return SLCT_CheckedLiteral;
+ return SLCT_UncheckedLiteral;
switch (E->getStmtClass()) {
case Stmt::BinaryConditionalOperatorClass:
@@ -1673,15 +1999,15 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args,
const AbstractConditionalOperator *C =
cast<AbstractConditionalOperator>(E);
StringLiteralCheckType Left =
- checkFormatStringExpr(C->getTrueExpr(), Args,
+ checkFormatStringExpr(S, C->getTrueExpr(), Args,
HasVAListArg, format_idx, firstDataArg,
- Type, CallType, inFunctionCall);
+ Type, CallType, InFunctionCall, CheckedVarArgs);
if (Left == SLCT_NotALiteral)
return SLCT_NotALiteral;
StringLiteralCheckType Right =
- checkFormatStringExpr(C->getFalseExpr(), Args,
+ checkFormatStringExpr(S, C->getFalseExpr(), Args,
HasVAListArg, format_idx, firstDataArg,
- Type, CallType, inFunctionCall);
+ Type, CallType, InFunctionCall, CheckedVarArgs);
return Left < Right ? Left : Right;
}
@@ -1712,15 +2038,15 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args,
bool isConstant = false;
QualType T = DR->getType();
- if (const ArrayType *AT = Context.getAsArrayType(T)) {
- isConstant = AT->getElementType().isConstant(Context);
+ if (const ArrayType *AT = S.Context.getAsArrayType(T)) {
+ isConstant = AT->getElementType().isConstant(S.Context);
} else if (const PointerType *PT = T->getAs<PointerType>()) {
- isConstant = T.isConstant(Context) &&
- PT->getPointeeType().isConstant(Context);
+ isConstant = T.isConstant(S.Context) &&
+ PT->getPointeeType().isConstant(S.Context);
} else if (T->isObjCObjectPointerType()) {
// In ObjC, there is usually no "const ObjectPointer" type,
// so don't check if the pointee type is constant.
- isConstant = T.isConstant(Context);
+ isConstant = T.isConstant(S.Context);
}
if (isConstant) {
@@ -1730,10 +2056,10 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args,
if (InitList->isStringLiteralInit())
Init = InitList->getInit(0)->IgnoreParenImpCasts();
}
- return checkFormatStringExpr(Init, Args,
+ return checkFormatStringExpr(S, Init, Args,
HasVAListArg, format_idx,
firstDataArg, Type, CallType,
- /*inFunctionCall*/false);
+ /*InFunctionCall*/false, CheckedVarArgs);
}
}
@@ -1750,7 +2076,7 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args,
// va_start(ap, fmt);
// vprintf(fmt, ap); // Do NOT emit a warning about "fmt".
// ...
- //
+ // }
if (HasVAListArg) {
if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(VD)) {
if (const NamedDecl *ND = dyn_cast<NamedDecl>(PV->getDeclContext())) {
@@ -1766,7 +2092,7 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args,
// We also check if the formats are compatible.
// We can't pass a 'scanf' string to a 'printf' function.
if (PVIndex == PVFormat->getFormatIdx() &&
- Type == GetFormatStringType(PVFormat))
+ Type == S.GetFormatStringType(PVFormat))
return SLCT_UncheckedLiteral;
}
}
@@ -1788,24 +2114,46 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args,
--ArgIndex;
const Expr *Arg = CE->getArg(ArgIndex - 1);
- return checkFormatStringExpr(Arg, Args,
+ return checkFormatStringExpr(S, Arg, Args,
HasVAListArg, format_idx, firstDataArg,
- Type, CallType, inFunctionCall);
+ Type, CallType, InFunctionCall,
+ CheckedVarArgs);
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
unsigned BuiltinID = FD->getBuiltinID();
if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString) {
const Expr *Arg = CE->getArg(0);
- return checkFormatStringExpr(Arg, Args,
+ return checkFormatStringExpr(S, Arg, Args,
HasVAListArg, format_idx,
firstDataArg, Type, CallType,
- inFunctionCall);
+ InFunctionCall, CheckedVarArgs);
}
}
}
return SLCT_NotALiteral;
}
+
+ case Stmt::ObjCMessageExprClass: {
+ const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(E);
+ if (const ObjCMethodDecl *MDecl = ME->getMethodDecl()) {
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(MDecl)) {
+ if (const FormatArgAttr *FA = ND->getAttr<FormatArgAttr>()) {
+ unsigned ArgIndex = FA->getFormatIdx();
+ if (ArgIndex <= ME->getNumArgs()) {
+ const Expr *Arg = ME->getArg(ArgIndex-1);
+ return checkFormatStringExpr(S, Arg, Args,
+ HasVAListArg, format_idx,
+ firstDataArg, Type, CallType,
+ InFunctionCall, CheckedVarArgs);
+ }
+ }
+ }
+ }
+
+ return SLCT_NotALiteral;
+ }
+
case Stmt::ObjCStringLiteralClass:
case Stmt::StringLiteralClass: {
const StringLiteral *StrE = NULL;
@@ -1816,8 +2164,8 @@ Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args,
StrE = cast<StringLiteral>(E);
if (StrE) {
- CheckFormatString(StrE, E, Args, HasVAListArg, format_idx,
- firstDataArg, Type, inFunctionCall, CallType);
+ S.CheckFormatString(StrE, E, Args, HasVAListArg, format_idx, firstDataArg,
+ Type, InFunctionCall, CallType, CheckedVarArgs);
return SLCT_CheckedLiteral;
}
@@ -1856,7 +2204,7 @@ Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
}
Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
- return llvm::StringSwitch<FormatStringType>(Format->getType())
+ return llvm::StringSwitch<FormatStringType>(Format->getType()->getName())
.Case("scanf", FST_Scanf)
.Cases("printf", "printf0", FST_Printf)
.Cases("NSString", "CFString", FST_NSString)
@@ -1873,12 +2221,13 @@ bool Sema::CheckFormatArguments(const FormatAttr *Format,
ArrayRef<const Expr *> Args,
bool IsCXXMember,
VariadicCallType CallType,
- SourceLocation Loc, SourceRange Range) {
+ SourceLocation Loc, SourceRange Range,
+ llvm::SmallBitVector &CheckedVarArgs) {
FormatStringInfo FSI;
if (getFormatStringInfo(Format, IsCXXMember, &FSI))
return CheckFormatArguments(Args, FSI.HasVAListArg, FSI.FormatIdx,
FSI.FirstDataArg, GetFormatStringType(Format),
- CallType, Loc, Range);
+ CallType, Loc, Range, CheckedVarArgs);
return false;
}
@@ -1886,7 +2235,8 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args,
bool HasVAListArg, unsigned format_idx,
unsigned firstDataArg, FormatStringType Type,
VariadicCallType CallType,
- SourceLocation Loc, SourceRange Range) {
+ SourceLocation Loc, SourceRange Range,
+ llvm::SmallBitVector &CheckedVarArgs) {
// CHECK: printf/scanf-like function is called with no format string.
if (format_idx >= Args.size()) {
Diag(Loc, diag::warn_missing_format_string) << Range;
@@ -1908,8 +2258,9 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args,
// ObjC string uses the same format specifiers as C string, so we can use
// the same format string checking logic for both ObjC and C strings.
StringLiteralCheckType CT =
- checkFormatStringExpr(OrigFormatExpr, Args, HasVAListArg,
- format_idx, firstDataArg, Type, CallType);
+ checkFormatStringExpr(*this, OrigFormatExpr, Args, HasVAListArg,
+ format_idx, firstDataArg, Type, CallType,
+ /*IsFunctionCall*/true, CheckedVarArgs);
if (CT != SLCT_NotALiteral)
// Literal format string found, check done!
return CT == SLCT_CheckedLiteral;
@@ -1929,7 +2280,7 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args,
// If there are no arguments specified, warn with -Wformat-security, otherwise
// warn only with -Wformat-nonliteral.
- if (Args.size() == format_idx+1)
+ if (Args.size() == firstDataArg)
Diag(Args[format_idx]->getLocStart(),
diag::warn_format_nonliteral_noargs)
<< OrigFormatExpr->getSourceRange();
@@ -1952,27 +2303,30 @@ protected:
const bool HasVAListArg;
ArrayRef<const Expr *> Args;
unsigned FormatIdx;
- llvm::BitVector CoveredArgs;
+ llvm::SmallBitVector CoveredArgs;
bool usesPositionalArgs;
bool atFirstArg;
bool inFunctionCall;
Sema::VariadicCallType CallType;
+ llvm::SmallBitVector &CheckedVarArgs;
public:
CheckFormatHandler(Sema &s, const StringLiteral *fexpr,
const Expr *origFormatExpr, unsigned firstDataArg,
unsigned numDataArgs, const char *beg, bool hasVAListArg,
ArrayRef<const Expr *> Args,
unsigned formatIdx, bool inFunctionCall,
- Sema::VariadicCallType callType)
+ Sema::VariadicCallType callType,
+ llvm::SmallBitVector &CheckedVarArgs)
: S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr),
FirstDataArg(firstDataArg), NumDataArgs(numDataArgs),
Beg(beg), HasVAListArg(hasVAListArg),
Args(Args), FormatIdx(formatIdx),
usesPositionalArgs(false), atFirstArg(true),
- inFunctionCall(inFunctionCall), CallType(callType) {
- CoveredArgs.resize(numDataArgs);
- CoveredArgs.reset();
- }
+ inFunctionCall(inFunctionCall), CallType(callType),
+ CheckedVarArgs(CheckedVarArgs) {
+ CoveredArgs.resize(numDataArgs);
+ CoveredArgs.reset();
+ }
void DoneProcessing();
@@ -2361,10 +2715,12 @@ public:
const char *beg, bool hasVAListArg,
ArrayRef<const Expr *> Args,
unsigned formatIdx, bool inFunctionCall,
- Sema::VariadicCallType CallType)
- : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
- numDataArgs, beg, hasVAListArg, Args,
- formatIdx, inFunctionCall, CallType), ObjCContext(isObjC)
+ Sema::VariadicCallType CallType,
+ llvm::SmallBitVector &CheckedVarArgs)
+ : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
+ numDataArgs, beg, hasVAListArg, Args,
+ formatIdx, inFunctionCall, CallType, CheckedVarArgs),
+ ObjCContext(isObjC)
{}
@@ -2824,7 +3180,15 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// 'unichar' is defined as a typedef of unsigned short, but we should
// prefer using the typedef if it is visible.
IntendedTy = S.Context.UnsignedShortTy;
-
+
+ // While we are here, check if the value is an IntegerLiteral that happens
+ // to be within the valid range.
+ if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(E)) {
+ const llvm::APInt &V = IL->getValue();
+ if (V.getActiveBits() <= S.Context.getTypeSize(IntendedTy))
+ return true;
+ }
+
LookupResult Result(S, &S.Context.Idents.get("unichar"), E->getLocStart(),
Sema::LookupOrdinaryName);
if (S.LookupName(Result, S.getCurScope())) {
@@ -2952,15 +3316,20 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// Since the warning for passing non-POD types to variadic functions
// was deferred until now, we emit a warning for non-POD
// arguments here.
- if (S.isValidVarArgType(ExprTy) == Sema::VAK_Invalid) {
- unsigned DiagKind;
- if (ExprTy->isObjCObjectType())
- DiagKind = diag::err_cannot_pass_objc_interface_to_vararg_format;
- else
- DiagKind = diag::warn_non_pod_vararg_with_format_string;
+ switch (S.isValidVarArgType(ExprTy)) {
+ case Sema::VAK_Valid:
+ case Sema::VAK_ValidInCXX11:
+ EmitFormatDiagnostic(
+ S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
+ << AT.getRepresentativeTypeName(S.Context) << ExprTy
+ << CSR
+ << E->getSourceRange(),
+ E->getLocStart(), /*IsStringLocation*/false, CSR);
+ break;
+ case Sema::VAK_Undefined:
EmitFormatDiagnostic(
- S.PDiag(DiagKind)
+ S.PDiag(diag::warn_non_pod_vararg_with_format_string)
<< S.getLangOpts().CPlusPlus11
<< ExprTy
<< CallType
@@ -2968,15 +3337,33 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
<< CSR
<< E->getSourceRange(),
E->getLocStart(), /*IsStringLocation*/false, CSR);
-
checkForCStrMembers(AT, E, CSR);
- } else
- EmitFormatDiagnostic(
- S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
- << AT.getRepresentativeTypeName(S.Context) << ExprTy
- << CSR
- << E->getSourceRange(),
- E->getLocStart(), /*IsStringLocation*/false, CSR);
+ break;
+
+ case Sema::VAK_Invalid:
+ if (ExprTy->isObjCObjectType())
+ EmitFormatDiagnostic(
+ S.PDiag(diag::err_cannot_pass_objc_interface_to_vararg_format)
+ << S.getLangOpts().CPlusPlus11
+ << ExprTy
+ << CallType
+ << AT.getRepresentativeTypeName(S.Context)
+ << CSR
+ << E->getSourceRange(),
+ E->getLocStart(), /*IsStringLocation*/false, CSR);
+ else
+ // FIXME: If this is an initializer list, suggest removing the braces
+ // or inserting a cast to the target type.
+ S.Diag(E->getLocStart(), diag::err_cannot_pass_to_vararg_format)
+ << isa<InitListExpr>(E) << ExprTy << CallType
+ << AT.getRepresentativeTypeName(S.Context)
+ << E->getSourceRange();
+ break;
+ }
+
+ assert(FirstDataArg + FS.getArgIndex() < CheckedVarArgs.size() &&
+ "format string specifier index out of range");
+ CheckedVarArgs[FirstDataArg + FS.getArgIndex()] = true;
}
return true;
@@ -2992,10 +3379,12 @@ public:
unsigned numDataArgs, const char *beg, bool hasVAListArg,
ArrayRef<const Expr *> Args,
unsigned formatIdx, bool inFunctionCall,
- Sema::VariadicCallType CallType)
- : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
- numDataArgs, beg, hasVAListArg,
- Args, formatIdx, inFunctionCall, CallType)
+ Sema::VariadicCallType CallType,
+ llvm::SmallBitVector &CheckedVarArgs)
+ : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
+ numDataArgs, beg, hasVAListArg,
+ Args, formatIdx, inFunctionCall, CallType,
+ CheckedVarArgs)
{}
bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
@@ -3150,7 +3539,8 @@ void Sema::CheckFormatString(const StringLiteral *FExpr,
ArrayRef<const Expr *> Args,
bool HasVAListArg, unsigned format_idx,
unsigned firstDataArg, FormatStringType Type,
- bool inFunctionCall, VariadicCallType CallType) {
+ bool inFunctionCall, VariadicCallType CallType,
+ llvm::SmallBitVector &CheckedVarArgs) {
// CHECK: is the format string a wide literal?
if (!FExpr->isAscii() && !FExpr->isUTF8()) {
@@ -3180,7 +3570,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr,
CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
numDataArgs, (Type == FST_NSString),
Str, HasVAListArg, Args, format_idx,
- inFunctionCall, CallType);
+ inFunctionCall, CallType, CheckedVarArgs);
if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen,
getLangOpts(),
@@ -3189,7 +3579,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr,
} else if (Type == FST_Scanf) {
CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs,
Str, HasVAListArg, Args, format_idx,
- inFunctionCall, CallType);
+ inFunctionCall, CallType, CheckedVarArgs);
if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen,
getLangOpts(),
@@ -3688,7 +4078,7 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
Decl *ParentDecl) {
if (E->isTypeDependent())
- return NULL;
+ return NULL;
// We should only be called for evaluating pointer expressions.
assert((E->getType()->isAnyPointerType() ||
@@ -4130,6 +4520,13 @@ static IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty,
return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType());
}
+static QualType GetExprType(Expr *E) {
+ QualType Ty = E->getType();
+ if (const AtomicType *AtomicRHS = Ty->getAs<AtomicType>())
+ Ty = AtomicRHS->getValueType();
+ return Ty;
+}
+
/// Pseudo-evaluate the given integer expression, estimating the
/// range of values it might take.
///
@@ -4140,7 +4537,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
// Try a full evaluation first.
Expr::EvalResult result;
if (E->EvaluateAsRValue(result, C))
- return GetValueRange(C, result.Val, E->getType(), MaxWidth);
+ return GetValueRange(C, result.Val, GetExprType(E), MaxWidth);
// I think we only want to look through implicit casts here; if the
// user has an explicit widening cast, we should treat the value as
@@ -4149,7 +4546,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue)
return GetExprRange(C, CE->getSubExpr(), MaxWidth);
- IntRange OutputTypeRange = IntRange::forValueOfType(C, CE->getType());
+ IntRange OutputTypeRange = IntRange::forValueOfType(C, GetExprType(CE));
bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast);
@@ -4209,7 +4606,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
case BO_XorAssign:
case BO_OrAssign:
// TODO: bitfields?
- return IntRange::forValueOfType(C, E->getType());
+ return IntRange::forValueOfType(C, GetExprType(E));
// Simple assignments just pass through the RHS, which will have
// been coerced to the LHS type.
@@ -4220,7 +4617,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
// Operations with opaque sources are black-listed.
case BO_PtrMemD:
case BO_PtrMemI:
- return IntRange::forValueOfType(C, E->getType());
+ return IntRange::forValueOfType(C, GetExprType(E));
// Bitwise-and uses the *infinum* of the two source ranges.
case BO_And:
@@ -4235,14 +4632,14 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
if (IntegerLiteral *I
= dyn_cast<IntegerLiteral>(BO->getLHS()->IgnoreParenCasts())) {
if (I->getValue() == 1) {
- IntRange R = IntRange::forValueOfType(C, E->getType());
+ IntRange R = IntRange::forValueOfType(C, GetExprType(E));
return IntRange(R.Width, /*NonNegative*/ true);
}
}
// fallthrough
case BO_ShlAssign:
- return IntRange::forValueOfType(C, E->getType());
+ return IntRange::forValueOfType(C, GetExprType(E));
// Right shift by a constant can narrow its left argument.
case BO_Shr:
@@ -4271,14 +4668,14 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
// Black-list pointer subtractions.
case BO_Sub:
if (BO->getLHS()->getType()->isPointerType())
- return IntRange::forValueOfType(C, E->getType());
+ return IntRange::forValueOfType(C, GetExprType(E));
break;
// The width of a division result is mostly determined by the size
// of the LHS.
case BO_Div: {
// Don't 'pre-truncate' the operands.
- unsigned opWidth = C.getIntWidth(E->getType());
+ unsigned opWidth = C.getIntWidth(GetExprType(E));
IntRange L = GetExprRange(C, BO->getLHS(), opWidth);
// If the divisor is constant, use that.
@@ -4301,7 +4698,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
// either side.
case BO_Rem: {
// Don't 'pre-truncate' the operands.
- unsigned opWidth = C.getIntWidth(E->getType());
+ unsigned opWidth = C.getIntWidth(GetExprType(E));
IntRange L = GetExprRange(C, BO->getLHS(), opWidth);
IntRange R = GetExprRange(C, BO->getRHS(), opWidth);
@@ -4334,26 +4731,25 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
// Operations with opaque sources are black-listed.
case UO_Deref:
case UO_AddrOf: // should be impossible
- return IntRange::forValueOfType(C, E->getType());
+ return IntRange::forValueOfType(C, GetExprType(E));
default:
return GetExprRange(C, UO->getSubExpr(), MaxWidth);
}
}
-
- if (dyn_cast<OffsetOfExpr>(E)) {
- IntRange::forValueOfType(C, E->getType());
- }
+
+ if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
+ return GetExprRange(C, OVE->getSourceExpr(), MaxWidth);
if (FieldDecl *BitField = E->getSourceBitField())
return IntRange(BitField->getBitWidthValue(C),
BitField->getType()->isUnsignedIntegerOrEnumerationType());
- return IntRange::forValueOfType(C, E->getType());
+ return IntRange::forValueOfType(C, GetExprType(E));
}
static IntRange GetExprRange(ASTContext &C, Expr *E) {
- return GetExprRange(C, E, C.getIntWidth(E->getType()));
+ return GetExprRange(C, E, C.getIntWidth(GetExprType(E)));
}
/// Checks whether the given value, which currently has the given
@@ -4424,6 +4820,10 @@ static bool HasEnumType(Expr *E) {
}
static void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) {
+ // Disable warning in template instantiations.
+ if (!S.ActiveTemplateInstantiations.empty())
+ return;
+
BinaryOperatorKind op = E->getOpcode();
if (E->isValueDependent())
return;
@@ -4451,6 +4851,10 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E,
Expr *Constant, Expr *Other,
llvm::APSInt Value,
bool RhsConstant) {
+ // Disable warning in template instantiations.
+ if (!S.ActiveTemplateInstantiations.empty())
+ return;
+
// 0 values are handled later by CheckTrivialUnsignedComparison().
if (Value == 0)
return;
@@ -4770,8 +5174,16 @@ void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T,
== llvm::APFloat::opOK && isExact)
return;
+ // FIXME: Force the precision of the source value down so we don't print
+ // digits which are usually useless (we don't really care here if we
+ // truncate a digit by accident in edge cases). Ideally, APFloat::toString
+ // would automatically print the shortest representation, but it's a bit
+ // tricky to implement.
SmallString<16> PrettySourceValue;
- Value.toString(PrettySourceValue);
+ unsigned precision = llvm::APFloat::semanticsPrecision(Value.getSemantics());
+ precision = (precision * 59 + 195) / 196;
+ Value.toString(PrettySourceValue, precision);
+
SmallString<16> PrettyTargetValue;
if (T->isSpecificBuiltinType(BuiltinType::Bool))
PrettyTargetValue = IntegerValue == 0 ? "false" : "true";
@@ -4877,7 +5289,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
<< FixItHint::CreateInsertion(E->getExprLoc(), "&");
QualType ReturnType;
UnresolvedSet<4> NonTemplateOverloads;
- S.isExprCallable(*E, ReturnType, NonTemplateOverloads);
+ S.tryExprAsCall(*E, ReturnType, NonTemplateOverloads);
if (!ReturnType.isNull()
&& ReturnType->isSpecificBuiltinType(BuiltinType::Bool))
S.Diag(E->getExprLoc(), diag::note_function_to_bool_call)
@@ -5000,7 +5412,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
if (!Loc.isMacroID() || CC.isMacroID())
S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer)
<< T << clang::SourceRange(CC)
- << FixItHint::CreateReplacement(Loc, S.getFixItZeroLiteralForType(T));
+ << FixItHint::CreateReplacement(Loc,
+ S.getFixItZeroLiteralForType(T, Loc));
}
if (!Source->isIntegerType() || !Target->isIntegerType())
@@ -5167,7 +5580,15 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
CheckImplicitConversion(S, E, T, CC);
// Now continue drilling into this expression.
-
+
+ if (PseudoObjectExpr * POE = dyn_cast<PseudoObjectExpr>(E)) {
+ if (POE->getResultExpr())
+ E = POE->getResultExpr();
+ }
+
+ if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
+ return AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC);
+
// Skip past explicit casts.
if (isa<ExplicitCastExpr>(E)) {
E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts();
@@ -5240,16 +5661,16 @@ void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) {
/// Diagnose when expression is an integer constant expression and its evaluation
/// results in integer overflow
void Sema::CheckForIntOverflow (Expr *E) {
- if (isa<BinaryOperator>(E->IgnoreParens())) {
- llvm::SmallVector<PartialDiagnosticAt, 4> Diags;
- E->EvaluateForOverflow(Context, &Diags);
- }
+ if (isa<BinaryOperator>(E->IgnoreParens()))
+ E->EvaluateForOverflow(Context);
}
namespace {
/// \brief Visitor for expressions which looks for unsequenced operations on the
/// same object.
class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
+ typedef EvaluatedExprVisitor<SequenceChecker> Base;
+
/// \brief A tree of sequenced regions within an expression. Two regions are
/// unsequenced if one is an ancestor or a descendent of the other. When we
/// finish processing an expression with sequencing, such as a comma
@@ -5261,7 +5682,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
unsigned Parent : 31;
bool Merged : 1;
};
- llvm::SmallVector<Value, 8> Values;
+ SmallVector<Value, 8> Values;
public:
/// \brief A region within an expression which may be sequenced with respect
@@ -5323,7 +5744,7 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
/// A read of an object. Multiple unsequenced reads are OK.
UK_Use,
/// A modification of an object which is sequenced before the value
- /// computation of the expression, such as ++n.
+ /// computation of the expression, such as ++n in C++.
UK_ModAsValue,
/// A modification of an object which is not sequenced before the value
/// computation of the expression, such as n++.
@@ -5355,10 +5776,10 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
SequenceTree::Seq Region;
/// Filled in with declarations which were modified as a side-effect
/// (that is, post-increment operations).
- llvm::SmallVectorImpl<std::pair<Object, Usage> > *ModAsSideEffect;
+ SmallVectorImpl<std::pair<Object, Usage> > *ModAsSideEffect;
/// Expressions to check later. We defer checking these to reduce
/// stack usage.
- llvm::SmallVectorImpl<Expr*> &WorkList;
+ SmallVectorImpl<Expr *> &WorkList;
/// RAII object wrapping the visitation of a sequenced subexpression of an
/// expression. At the end of this process, the side-effects of the evaluation
@@ -5381,10 +5802,39 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
}
SequenceChecker &Self;
- llvm::SmallVector<std::pair<Object, Usage>, 4> ModAsSideEffect;
- llvm::SmallVectorImpl<std::pair<Object, Usage> > *OldModAsSideEffect;
+ SmallVector<std::pair<Object, Usage>, 4> ModAsSideEffect;
+ SmallVectorImpl<std::pair<Object, Usage> > *OldModAsSideEffect;
};
+ /// RAII object wrapping the visitation of a subexpression which we might
+ /// choose to evaluate as a constant. If any subexpression is evaluated and
+ /// found to be non-constant, this allows us to suppress the evaluation of
+ /// the outer expression.
+ class EvaluationTracker {
+ public:
+ EvaluationTracker(SequenceChecker &Self)
+ : Self(Self), Prev(Self.EvalTracker), EvalOK(true) {
+ Self.EvalTracker = this;
+ }
+ ~EvaluationTracker() {
+ Self.EvalTracker = Prev;
+ if (Prev)
+ Prev->EvalOK &= EvalOK;
+ }
+
+ bool evaluate(const Expr *E, bool &Result) {
+ if (!EvalOK || E->isValueDependent())
+ return false;
+ EvalOK = E->EvaluateAsBooleanCondition(Result, Self.SemaRef.Context);
+ return EvalOK;
+ }
+
+ private:
+ SequenceChecker &Self;
+ EvaluationTracker *Prev;
+ bool EvalOK;
+ } *EvalTracker;
+
/// \brief Find the object which is produced by the specified expression,
/// if any.
Object getObject(Expr *E, bool Mod) const {
@@ -5463,10 +5913,9 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
}
public:
- SequenceChecker(Sema &S, Expr *E,
- llvm::SmallVectorImpl<Expr*> &WorkList)
- : EvaluatedExprVisitor<SequenceChecker>(S.Context), SemaRef(S),
- Region(Tree.root()), ModAsSideEffect(0), WorkList(WorkList) {
+ SequenceChecker(Sema &S, Expr *E, SmallVectorImpl<Expr *> &WorkList)
+ : Base(S.Context), SemaRef(S), Region(Tree.root()), ModAsSideEffect(0),
+ WorkList(WorkList), EvalTracker(0) {
Visit(E);
}
@@ -5476,7 +5925,7 @@ public:
void VisitExpr(Expr *E) {
// By default, just recurse to evaluated subexpressions.
- EvaluatedExprVisitor<SequenceChecker>::VisitStmt(E);
+ Base::VisitStmt(E);
}
void VisitCastExpr(CastExpr *E) {
@@ -5543,7 +5992,12 @@ public:
Visit(BO->getRHS());
- notePostMod(O, BO, UK_ModAsValue);
+ // C++11 [expr.ass]p1:
+ // the assignment is sequenced [...] before the value computation of the
+ // assignment expression.
+ // C11 6.5.16/3 has no such rule.
+ notePostMod(O, BO, SemaRef.getLangOpts().CPlusPlus ? UK_ModAsValue
+ : UK_ModAsSideEffect);
}
void VisitCompoundAssignOperator(CompoundAssignOperator *CAO) {
VisitBinAssign(CAO);
@@ -5558,7 +6012,10 @@ public:
notePreMod(O, UO);
Visit(UO->getSubExpr());
- notePostMod(O, UO, UK_ModAsValue);
+ // C++11 [expr.pre.incr]p1:
+ // the expression ++x is equivalent to x+=1
+ notePostMod(O, UO, SemaRef.getLangOpts().CPlusPlus ? UK_ModAsValue
+ : UK_ModAsSideEffect);
}
void VisitUnaryPostInc(UnaryOperator *UO) { VisitUnaryPostIncDec(UO); }
@@ -5579,14 +6036,14 @@ public:
// value computation of the RHS, and hence before the value computation
// of the '&&' itself, unless the LHS evaluates to zero. We treat them
// as if they were unconditionally sequenced.
+ EvaluationTracker Eval(*this);
{
SequencedSubexpression Sequenced(*this);
Visit(BO->getLHS());
}
bool Result;
- if (!BO->getLHS()->isValueDependent() &&
- BO->getLHS()->EvaluateAsBooleanCondition(Result, SemaRef.Context)) {
+ if (Eval.evaluate(BO->getLHS(), Result)) {
if (!Result)
Visit(BO->getRHS());
} else {
@@ -5600,14 +6057,14 @@ public:
}
}
void VisitBinLAnd(BinaryOperator *BO) {
+ EvaluationTracker Eval(*this);
{
SequencedSubexpression Sequenced(*this);
Visit(BO->getLHS());
}
bool Result;
- if (!BO->getLHS()->isValueDependent() &&
- BO->getLHS()->EvaluateAsBooleanCondition(Result, SemaRef.Context)) {
+ if (Eval.evaluate(BO->getLHS(), Result)) {
if (Result)
Visit(BO->getRHS());
} else {
@@ -5618,12 +6075,14 @@ public:
// Only visit the condition, unless we can be sure which subexpression will
// be chosen.
void VisitAbstractConditionalOperator(AbstractConditionalOperator *CO) {
- SequencedSubexpression Sequenced(*this);
- Visit(CO->getCond());
+ EvaluationTracker Eval(*this);
+ {
+ SequencedSubexpression Sequenced(*this);
+ Visit(CO->getCond());
+ }
bool Result;
- if (!CO->getCond()->isValueDependent() &&
- CO->getCond()->EvaluateAsBooleanCondition(Result, SemaRef.Context))
+ if (Eval.evaluate(CO->getCond(), Result))
Visit(Result ? CO->getTrueExpr() : CO->getFalseExpr());
else {
WorkList.push_back(CO->getTrueExpr());
@@ -5631,12 +6090,28 @@ public:
}
}
+ void VisitCallExpr(CallExpr *CE) {
+ // C++11 [intro.execution]p15:
+ // When calling a function [...], every value computation and side effect
+ // associated with any argument expression, or with the postfix expression
+ // designating the called function, is sequenced before execution of every
+ // expression or statement in the body of the function [and thus before
+ // the value computation of its result].
+ SequencedSubexpression Sequenced(*this);
+ Base::VisitCallExpr(CE);
+
+ // FIXME: CXXNewExpr and CXXDeleteExpr implicitly call functions.
+ }
+
void VisitCXXConstructExpr(CXXConstructExpr *CCE) {
+ // This is a call, so all subexpressions are sequenced before the result.
+ SequencedSubexpression Sequenced(*this);
+
if (!CCE->isListInitialization())
return VisitExpr(CCE);
// In C++11, list initializations are sequenced.
- llvm::SmallVector<SequenceTree::Seq, 32> Elts;
+ SmallVector<SequenceTree::Seq, 32> Elts;
SequenceTree::Seq Parent = Region;
for (CXXConstructExpr::arg_iterator I = CCE->arg_begin(),
E = CCE->arg_end();
@@ -5657,7 +6132,7 @@ public:
return VisitExpr(ILE);
// In C++11, list initializations are sequenced.
- llvm::SmallVector<SequenceTree::Seq, 32> Elts;
+ SmallVector<SequenceTree::Seq, 32> Elts;
SequenceTree::Seq Parent = Region;
for (unsigned I = 0; I < ILE->getNumInits(); ++I) {
Expr *E = ILE->getInit(I);
@@ -5676,11 +6151,10 @@ public:
}
void Sema::CheckUnsequencedOperations(Expr *E) {
- llvm::SmallVector<Expr*, 8> WorkList;
+ SmallVector<Expr *, 8> WorkList;
WorkList.push_back(E);
while (!WorkList.empty()) {
- Expr *Item = WorkList.back();
- WorkList.pop_back();
+ Expr *Item = WorkList.pop_back_val();
SequenceChecker(*this, Item, WorkList);
}
}
@@ -5704,7 +6178,8 @@ void Sema::CheckBitFieldInitialization(SourceLocation InitLoc,
/// takes care of any checks that cannot be performed on the
/// declaration itself, e.g., that the types of each of the function
/// parameters are complete.
-bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd,
+bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P,
+ ParmVarDecl *const *PEnd,
bool CheckParameterNames) {
bool HasInvalidParm = false;
for (; P != PEnd; ++P) {
@@ -5745,6 +6220,15 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd,
}
PType= AT->getElementType();
}
+
+ // MSVC destroys objects passed by value in the callee. Therefore a
+ // function definition which takes such a parameter must be able to call the
+ // object's destructor.
+ if (getLangOpts().CPlusPlus &&
+ Context.getTargetInfo().getCXXABI().isArgumentDestroyedByCallee()) {
+ if (const RecordType *RT = Param->getType()->getAs<RecordType>())
+ FinalizeVarWithDestructor(Param, RT);
+ }
}
return HasInvalidParm;
@@ -5926,7 +6410,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
if (SourceMgr.isInSystemHeader(RBracketLoc)) {
SourceLocation IndexLoc = SourceMgr.getSpellingLoc(
IndexExpr->getLocStart());
- if (SourceMgr.isFromSameFile(RBracketLoc, IndexLoc))
+ if (SourceMgr.isWrittenInSameFile(RBracketLoc, IndexLoc))
return;
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
index fd2ce1749fe8..7a1b36b2d7ee 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
@@ -464,9 +464,8 @@ getRequiredQualification(ASTContext &Context,
NestedNameSpecifier *Result = 0;
while (!TargetParents.empty()) {
- const DeclContext *Parent = TargetParents.back();
- TargetParents.pop_back();
-
+ const DeclContext *Parent = TargetParents.pop_back_val();
+
if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
if (!Namespace->getIdentifier())
continue;
@@ -716,8 +715,8 @@ unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
return CCP_Unlikely;
// Context-based decisions.
- const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
- if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) {
+ const DeclContext *LexicalDC = ND->getLexicalDeclContext();
+ if (LexicalDC->isFunctionOrMethod()) {
// _cmd is relatively rare
if (const ImplicitParamDecl *ImplicitParam =
dyn_cast<ImplicitParamDecl>(ND))
@@ -727,6 +726,8 @@ unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
return CCP_LocalDeclaration;
}
+
+ const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
return CCP_MemberDeclaration;
@@ -877,8 +878,8 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
for (; I != IEnd; ++I) {
// A tag declaration does not hide a non-tag declaration.
if (I->first->hasTagIdentifierNamespace() &&
- (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
- Decl::IDNS_ObjCProtocol)))
+ (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
+ Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
continue;
// Protocols are in distinct namespaces from everything else.
@@ -1039,7 +1040,9 @@ void ResultBuilder::ExitScope() {
bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
ND = cast<NamedDecl>(ND->getUnderlyingDecl());
- unsigned IDNS = Decl::IDNS_Ordinary;
+ // If name lookup finds a local extern declaration, then we are in a
+ // context where it behaves like an ordinary name.
+ unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
if (SemaRef.getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
else if (SemaRef.getLangOpts().ObjC1) {
@@ -1057,7 +1060,7 @@ bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
return false;
- unsigned IDNS = Decl::IDNS_Ordinary;
+ unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
if (SemaRef.getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
else if (SemaRef.getLangOpts().ObjC1) {
@@ -1084,7 +1087,7 @@ bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
ND = cast<NamedDecl>(ND->getUnderlyingDecl());
- unsigned IDNS = Decl::IDNS_Ordinary;
+ unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
if (SemaRef.getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
@@ -3183,12 +3186,12 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Builder.getAllocator().CopyString(Modules[I]->Name));
Results.AddResult(Result(Builder.TakeString(),
CCP_Declaration,
- CXCursor_NotImplemented,
+ CXCursor_ModuleImportDecl,
Modules[I]->isAvailable()
? CXAvailability_Available
: CXAvailability_NotAvailable));
}
- } else {
+ } else if (getLangOpts().Modules) {
// Load the named module.
Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
Module::AllVisible,
@@ -3203,7 +3206,7 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Builder.getAllocator().CopyString((*Sub)->Name));
Results.AddResult(Result(Builder.TakeString(),
CCP_Declaration,
- CXCursor_NotImplemented,
+ CXCursor_ModuleImportDecl,
(*Sub)->isAvailable()
? CXAvailability_Available
: CXAvailability_NotAvailable));
@@ -3303,8 +3306,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
ParsedType Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
+ ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
bool IsSuper,
ResultBuilder &Results);
@@ -3360,7 +3362,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
Scope::AtCatchScope)) == 0) {
ParsedType T = DS.getRepAsType();
if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
- AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
+ AddClassMessageCompletions(*this, S, T, None, false, false, Results);
}
// Note that we intentionally suppress macro results here, since we do not
@@ -3436,7 +3438,7 @@ void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
if (E.isInvalid())
CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
else if (getLangOpts().ObjC1)
- CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
+ CodeCompleteObjCInstanceMessage(S, E.take(), None, false);
}
/// \brief The set of properties that have already been added, referenced by
@@ -3611,7 +3613,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
bool IsDependent = BaseType->isDependentType();
if (!IsDependent) {
for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
- if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
+ if (DeclContext *Ctx = DepScope->getEntity()) {
IsDependent = Ctx->isDependentContext();
break;
}
@@ -3847,7 +3849,7 @@ namespace {
};
}
-static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
+static bool anyNullArguments(ArrayRef<Expr *> Args) {
if (Args.size() && !Args.data())
return true;
@@ -3858,8 +3860,7 @@ static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
return false;
}
-void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
- llvm::ArrayRef<Expr *> Args) {
+void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) {
if (!CodeCompleter)
return;
@@ -4150,7 +4151,7 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
if (!CodeCompleter)
return;
- DeclContext *Ctx = (DeclContext *)S->getEntity();
+ DeclContext *Ctx = S->getEntity();
if (!S->getParent())
Ctx = Context.getTranslationUnitDecl();
@@ -4242,9 +4243,9 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
Results.data(),Results.size());
}
-void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
- CXXCtorInitializer** Initializers,
- unsigned NumInitializers) {
+void Sema::CodeCompleteConstructorInitializer(
+ Decl *ConstructorD,
+ ArrayRef <CXXCtorInitializer *> Initializers) {
PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
CXXConstructorDecl *Constructor
= static_cast<CXXConstructorDecl *>(ConstructorD);
@@ -4259,7 +4260,7 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
// Fill in any already-initialized fields or base classes.
llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
- for (unsigned I = 0; I != NumInitializers; ++I) {
+ for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
if (Initializers[I]->isBaseInitializer())
InitializedBases.insert(
Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
@@ -4271,17 +4272,17 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
// Add completions for base classes.
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
- bool SawLastInitializer = (NumInitializers == 0);
+ bool SawLastInitializer = Initializers.empty();
CXXRecordDecl *ClassDecl = Constructor->getParent();
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
BaseEnd = ClassDecl->bases_end();
Base != BaseEnd; ++Base) {
if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
SawLastInitializer
- = NumInitializers > 0 &&
- Initializers[NumInitializers - 1]->isBaseInitializer() &&
+ = !Initializers.empty() &&
+ Initializers.back()->isBaseInitializer() &&
Context.hasSameUnqualifiedType(Base->getType(),
- QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
+ QualType(Initializers.back()->getBaseClass(), 0));
continue;
}
@@ -4303,10 +4304,10 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Base != BaseEnd; ++Base) {
if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
SawLastInitializer
- = NumInitializers > 0 &&
- Initializers[NumInitializers - 1]->isBaseInitializer() &&
+ = !Initializers.empty() &&
+ Initializers.back()->isBaseInitializer() &&
Context.hasSameUnqualifiedType(Base->getType(),
- QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
+ QualType(Initializers.back()->getBaseClass(), 0));
continue;
}
@@ -4328,9 +4329,9 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Field != FieldEnd; ++Field) {
if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
SawLastInitializer
- = NumInitializers > 0 &&
- Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
- Initializers[NumInitializers - 1]->getAnyMember() == *Field;
+ = !Initializers.empty() &&
+ Initializers.back()->isAnyMemberInitializer() &&
+ Initializers.back()->getAnyMember() == *Field;
continue;
}
@@ -4358,7 +4359,7 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
/// \brief Determine whether this scope denotes a namespace.
static bool isNamespaceScope(Scope *S) {
- DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
+ DeclContext *DC = S->getEntity();
if (!DC)
return false;
@@ -4786,9 +4787,9 @@ enum ObjCMethodKind {
static bool isAcceptableObjCSelector(Selector Sel,
ObjCMethodKind WantKind,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
+ ArrayRef<IdentifierInfo *> SelIdents,
bool AllowSameLength = true) {
+ unsigned NumSelIdents = SelIdents.size();
if (NumSelIdents > Sel.getNumArgs())
return false;
@@ -4810,11 +4811,10 @@ static bool isAcceptableObjCSelector(Selector Sel,
static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
ObjCMethodKind WantKind,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
+ ArrayRef<IdentifierInfo *> SelIdents,
bool AllowSameLength = true) {
return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
- NumSelIdents, AllowSameLength);
+ AllowSameLength);
}
namespace {
@@ -4846,8 +4846,7 @@ namespace {
static void AddObjCMethods(ObjCContainerDecl *Container,
bool WantInstanceMethods,
ObjCMethodKind WantKind,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
+ ArrayRef<IdentifierInfo *> SelIdents,
DeclContext *CurContext,
VisitedSelectorSet &Selectors,
bool AllowSameLength,
@@ -4866,15 +4865,14 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
(isRootClass && !WantInstanceMethods)) {
// Check whether the selector identifiers we've been given are a
// subset of the identifiers for this particular method.
- if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
- AllowSameLength))
+ if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, AllowSameLength))
continue;
if (!Selectors.insert(M->getSelector()))
continue;
Result R = Result(*M, Results.getBasePriority(*M), 0);
- R.StartParameter = NumSelIdents;
+ R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = (WantKind != MK_Any);
if (!InOriginalClass)
R.Priority += CCD_InBaseClass;
@@ -4891,8 +4889,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
E = Protocols.end();
I != E; ++I)
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
- NumSelIdents, CurContext, Selectors, AllowSameLength,
- Results, false);
+ CurContext, Selectors, AllowSameLength, Results, false);
}
}
@@ -4903,7 +4900,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
E = IFace->protocol_end();
I != E; ++I)
- AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
+ AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
CurContext, Selectors, AllowSameLength, Results, false);
// Add methods in categories.
@@ -4914,7 +4911,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
ObjCCategoryDecl *CatDecl = *Cat;
AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
- NumSelIdents, CurContext, Selectors, AllowSameLength,
+ CurContext, Selectors, AllowSameLength,
Results, InOriginalClass);
// Add a categories protocol methods.
@@ -4924,26 +4921,26 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
E = Protocols.end();
I != E; ++I)
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
- NumSelIdents, CurContext, Selectors, AllowSameLength,
+ CurContext, Selectors, AllowSameLength,
Results, false);
// Add methods in category implementations.
if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
- NumSelIdents, CurContext, Selectors, AllowSameLength,
+ CurContext, Selectors, AllowSameLength,
Results, InOriginalClass);
}
// Add methods in superclass.
if (IFace->getSuperClass())
AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
- SelIdents, NumSelIdents, CurContext, Selectors,
+ SelIdents, CurContext, Selectors,
AllowSameLength, Results, false);
// Add methods in our implementation, if any.
if (ObjCImplementationDecl *Impl = IFace->getImplementation())
AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
- NumSelIdents, CurContext, Selectors, AllowSameLength,
+ CurContext, Selectors, AllowSameLength,
Results, InOriginalClass);
}
@@ -4967,7 +4964,7 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Results.EnterNewScope();
VisitedSelectorSet Selectors;
- AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
+ AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
/*AllowSameLength=*/true, Results);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter,
@@ -4995,7 +4992,7 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Results.EnterNewScope();
VisitedSelectorSet Selectors;
- AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
+ AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
Selectors, /*AllowSameLength=*/true, Results);
Results.ExitScope();
@@ -5159,16 +5156,14 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
/// \param SelIdents The identifiers in the selector that have already been
/// provided as arguments for a send to "super".
///
-/// \param NumSelIdents The number of identifiers in \p SelIdents.
-///
/// \param Results The set of results to augment.
///
/// \returns the Objective-C method declaration that would be invoked by
/// this "super" completion. If NULL, no completion was added.
-static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
- ResultBuilder &Results) {
+static ObjCMethodDecl *AddSuperSendCompletion(
+ Sema &S, bool NeedSuperKeyword,
+ ArrayRef<IdentifierInfo *> SelIdents,
+ ResultBuilder &Results) {
ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
if (!CurMethod)
return 0;
@@ -5244,14 +5239,14 @@ static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
} else {
ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
- if (I > NumSelIdents)
+ if (I > SelIdents.size())
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
- if (I < NumSelIdents)
+ if (I < SelIdents.size())
Builder.AddInformativeChunk(
Builder.getAllocator().CopyString(
Sel.getNameForSlot(I) + ":"));
- else if (NeedSuperKeyword || I > NumSelIdents) {
+ else if (NeedSuperKeyword || I > SelIdents.size()) {
Builder.AddTextChunk(
Builder.getAllocator().CopyString(
Sel.getNameForSlot(I) + ":"));
@@ -5293,7 +5288,7 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
if (Iface->getSuperClass()) {
Results.AddResult(Result("super"));
- AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
+ AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
}
if (getLangOpts().CPlusPlus11)
@@ -5309,8 +5304,7 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
}
void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
+ ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression) {
ObjCInterfaceDecl *CDecl = 0;
if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
@@ -5328,8 +5322,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
// We are inside an instance method, which means that the message
// send [super ...] is actually calling an instance method on the
// current object.
- return CodeCompleteObjCInstanceMessage(S, 0,
- SelIdents, NumSelIdents,
+ return CodeCompleteObjCInstanceMessage(S, 0, SelIdents,
AtArgumentExpression,
CDecl);
}
@@ -5358,7 +5351,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
false, false);
return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
- SelIdents, NumSelIdents,
+ SelIdents,
AtArgumentExpression);
}
@@ -5369,7 +5362,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
if (CDecl)
Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
- NumSelIdents, AtArgumentExpression,
+ AtArgumentExpression,
/*IsSuper=*/true);
}
@@ -5409,8 +5402,7 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
ParsedType Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
+ ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
bool IsSuper,
ResultBuilder &Results) {
@@ -5434,8 +5426,7 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
// completion.
if (IsSuper) {
if (ObjCMethodDecl *SuperMethod
- = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
- Results))
+ = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Results.Ignore(SuperMethod);
}
@@ -5446,7 +5437,7 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
VisitedSelectorSet Selectors;
if (CDecl)
- AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
+ AddObjCMethods(CDecl, false, MK_Any, SelIdents,
SemaRef.CurContext, Selectors, AtArgumentExpression,
Results);
else {
@@ -5472,12 +5463,11 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
for (ObjCMethodList *MethList = &M->second.second;
MethList && MethList->Method;
MethList = MethList->getNext()) {
- if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
- NumSelIdents))
+ if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents))
continue;
Result R(MethList->Method, Results.getBasePriority(MethList->Method),0);
- R.StartParameter = NumSelIdents;
+ R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, SemaRef.CurContext);
}
@@ -5488,8 +5478,7 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
}
void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
+ ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
bool IsSuper) {
@@ -5498,9 +5487,9 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
- T, SelIdents, NumSelIdents));
+ T, SelIdents));
- AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
+ AddClassMessageCompletions(*this, S, Receiver, SelIdents,
AtArgumentExpression, IsSuper, Results);
// If we're actually at the argument expression (rather than prior to the
@@ -5510,7 +5499,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
// our preferred type, improving completion results.
if (AtArgumentExpression) {
QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
- NumSelIdents);
+ SelIdents.size());
if (PreferredType.isNull())
CodeCompleteOrdinaryName(S, PCC_Expression);
else
@@ -5524,8 +5513,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
}
void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
+ ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
ObjCInterfaceDecl *Super) {
typedef CodeCompletionResult Result;
@@ -5553,7 +5541,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
if (ReceiverType->isObjCClassType())
return CodeCompleteObjCClassMessage(S,
ParsedType::make(Context.getObjCInterfaceType(IFace)),
- SelIdents, NumSelIdents,
+ SelIdents,
AtArgumentExpression, Super);
ReceiverType = Context.getObjCObjectPointerType(
@@ -5564,7 +5552,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
- ReceiverType, SelIdents, NumSelIdents));
+ ReceiverType, SelIdents));
Results.EnterNewScope();
@@ -5572,8 +5560,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
// completion.
if (Super) {
if (ObjCMethodDecl *SuperMethod
- = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
- Results))
+ = AddSuperSendCompletion(*this, false, SelIdents, Results))
Results.Ignore(SuperMethod);
}
@@ -5592,7 +5579,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
ReceiverType->isObjCQualifiedClassType()) {
if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
- AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
+ AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
CurContext, Selectors, AtArgumentExpression, Results);
}
}
@@ -5603,7 +5590,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
E = QualID->qual_end();
I != E; ++I)
- AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
+ AddObjCMethods(*I, true, MK_Any, SelIdents, CurContext,
Selectors, AtArgumentExpression, Results);
}
// Handle messages to a pointer to interface type.
@@ -5611,14 +5598,14 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
= ReceiverType->getAsObjCInterfacePointerType()) {
// Search the class, its superclasses, etc., for instance methods.
AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
- NumSelIdents, CurContext, Selectors, AtArgumentExpression,
+ CurContext, Selectors, AtArgumentExpression,
Results);
// Search protocols for instance methods.
for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
E = IFacePtr->qual_end();
I != E; ++I)
- AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
+ AddObjCMethods(*I, true, MK_Any, SelIdents, CurContext,
Selectors, AtArgumentExpression, Results);
}
// Handle messages to "id".
@@ -5645,15 +5632,14 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
for (ObjCMethodList *MethList = &M->second.first;
MethList && MethList->Method;
MethList = MethList->getNext()) {
- if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
- NumSelIdents))
+ if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents))
continue;
if (!Selectors.insert(MethList->Method->getSelector()))
continue;
Result R(MethList->Method, Results.getBasePriority(MethList->Method),0);
- R.StartParameter = NumSelIdents;
+ R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, CurContext);
}
@@ -5669,7 +5655,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
// our preferred type, improving completion results.
if (AtArgumentExpression) {
QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
- NumSelIdents);
+ SelIdents.size());
if (PreferredType.isNull())
CodeCompleteOrdinaryName(S, PCC_Expression);
else
@@ -5688,7 +5674,7 @@ void Sema::CodeCompleteObjCForCollection(Scope *S,
Data.ObjCCollection = true;
if (IterationVar.getAsOpaquePtr()) {
- DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
+ DeclGroupRef DG = IterationVar.get();
for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
if (*I)
Data.IgnoreDecls.push_back(*I);
@@ -5698,8 +5684,8 @@ void Sema::CodeCompleteObjCForCollection(Scope *S,
CodeCompleteExpression(S, Data);
}
-void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
- unsigned NumSelIdents) {
+void Sema::CodeCompleteObjCSelector(Scope *S,
+ ArrayRef<IdentifierInfo *> SelIdents) {
// If we have an external source, load the entire class method
// pool from the AST file.
if (ExternalSource) {
@@ -5722,7 +5708,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
M != MEnd; ++M) {
Selector Sel = M->first;
- if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
+ if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
continue;
CodeCompletionBuilder Builder(Results.getAllocator(),
@@ -5736,7 +5722,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
std::string Accumulator;
for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
- if (I == NumSelIdents) {
+ if (I == SelIdents.size()) {
if (!Accumulator.empty()) {
Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Accumulator));
@@ -6128,8 +6114,8 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
// Mapping from selectors to the methods that implement that selector, along
// with the "in original class" flag.
-typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
- KnownMethodsMap;
+typedef llvm::DenseMap<
+ Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
/// \brief Find all of the methods that reside in the given container
/// (and its superclasses, protocols, etc.) that meet the given
@@ -6218,7 +6204,8 @@ static void FindImplementableMethods(ASTContext &Context,
!Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
continue;
- KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass);
+ KnownMethods[M->getSelector()] =
+ KnownMethodsMap::mapped_type(*M, InOriginalClass);
}
}
}
@@ -6906,7 +6893,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
}
if (!SearchDecl && S) {
- if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
+ if (DeclContext *DC = S->getEntity())
SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
}
@@ -6932,7 +6919,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
for (KnownMethodsMap::iterator M = KnownMethods.begin(),
MEnd = KnownMethods.end();
M != MEnd; ++M) {
- ObjCMethodDecl *Method = M->second.first;
+ ObjCMethodDecl *Method = M->second.getPointer();
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
@@ -7000,7 +6987,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
}
unsigned Priority = CCP_CodePattern;
- if (!M->second.second)
+ if (!M->second.getInt())
Priority += CCD_InBaseClass;
Results.AddResult(Result(Builder.TakeString(), Method, Priority));
@@ -7054,8 +7041,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
bool IsInstanceMethod,
bool AtParameterName,
ParsedType ReturnTy,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents) {
+ ArrayRef<IdentifierInfo *> SelIdents) {
// If we have an external source, load the entire class method
// pool from the AST file.
if (ExternalSource) {
@@ -7086,12 +7072,12 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
&M->second.second;
MethList && MethList->Method;
MethList = MethList->getNext()) {
- if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
- NumSelIdents))
+ if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents))
continue;
if (AtParameterName) {
// Suggest parameter names we've seen before.
+ unsigned NumSelIdents = SelIdents.size();
if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
if (Param->getIdentifier()) {
@@ -7107,7 +7093,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
}
Result R(MethList->Method, Results.getBasePriority(MethList->Method), 0);
- R.StartParameter = NumSelIdents;
+ R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
R.DeclaringEntity = true;
Results.MaybeAddResult(R, CurContext);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
index fd7cfeb6f0da..328ce7059631 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
@@ -15,6 +15,7 @@
#include "TypeLocBuilder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/CommentDiagnostic.h"
@@ -39,6 +40,7 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Template.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Triple.h"
#include <algorithm>
@@ -108,6 +110,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
case tok::kw_char16_t:
case tok::kw_char32_t:
case tok::kw_typeof:
+ case tok::annot_decltype:
case tok::kw_decltype:
return getLangOpts().CPlusPlus;
@@ -126,9 +129,6 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
/// determine whether the name refers to a type. If so, returns an
/// opaque pointer (actually a QualType) corresponding to that
/// type. Otherwise, returns NULL.
-///
-/// If name lookup results in an ambiguity, this routine will complain
-/// and then return NULL.
ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, CXXScopeSpec *SS,
bool isClassName, bool HasTrailingDot,
@@ -237,17 +237,9 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
IsCtorOrDtorName,
WantNontrivialTypeSourceInfo);
if (Ty) {
- std::string CorrectedStr(Correction.getAsString(getLangOpts()));
- std::string CorrectedQuotedStr(
- Correction.getQuoted(getLangOpts()));
- Diag(NameLoc, diag::err_unknown_type_or_class_name_suggest)
- << Result.getLookupName() << CorrectedQuotedStr << isClassName
- << FixItHint::CreateReplacement(SourceRange(NameLoc),
- CorrectedStr);
- if (NamedDecl *FirstDecl = Correction.getCorrectionDecl())
- Diag(FirstDecl->getLocation(), diag::note_previous_decl)
- << CorrectedQuotedStr;
-
+ diagnoseTypo(Correction,
+ PDiag(diag::err_unknown_type_or_class_name_suggest)
+ << Result.getLookupName() << isClassName);
if (SS && NNS)
SS->MakeTrivial(Context, NNS, SourceRange(NameLoc));
*CorrectedII = NewII;
@@ -412,38 +404,33 @@ bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(II, IILoc),
LookupOrdinaryName, S, SS,
Validator)) {
- std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
- std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
-
if (Corrected.isKeyword()) {
// We corrected to a keyword.
- IdentifierInfo *NewII = Corrected.getCorrectionAsIdentifierInfo();
- if (!isSimpleTypeSpecifier(NewII->getTokenID()))
- CorrectedQuotedStr = "the keyword " + CorrectedQuotedStr;
- Diag(IILoc, diag::err_unknown_typename_suggest)
- << II << CorrectedQuotedStr
- << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
- II = NewII;
+ diagnoseTypo(Corrected, PDiag(diag::err_unknown_typename_suggest) << II);
+ II = Corrected.getCorrectionAsIdentifierInfo();
} else {
- NamedDecl *Result = Corrected.getCorrectionDecl();
// We found a similarly-named type or interface; suggest that.
- if (!SS || !SS->isSet())
- Diag(IILoc, diag::err_unknown_typename_suggest)
- << II << CorrectedQuotedStr
- << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
- else if (DeclContext *DC = computeDeclContext(*SS, false))
- Diag(IILoc, diag::err_unknown_nested_typename_suggest)
- << II << DC << CorrectedQuotedStr << SS->getRange()
- << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
- CorrectedStr);
- else
+ if (!SS || !SS->isSet()) {
+ diagnoseTypo(Corrected,
+ PDiag(diag::err_unknown_typename_suggest) << II);
+ } else if (DeclContext *DC = computeDeclContext(*SS, false)) {
+ std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
+ bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
+ II->getName().equals(CorrectedStr);
+ diagnoseTypo(Corrected,
+ PDiag(diag::err_unknown_nested_typename_suggest)
+ << II << DC << DroppedSpecifier << SS->getRange());
+ } else {
llvm_unreachable("could not have corrected a typo here");
+ }
- Diag(Result->getLocation(), diag::note_previous_decl)
- << CorrectedQuotedStr;
-
- SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS,
- false, false, ParsedType(),
+ CXXScopeSpec tmpSS;
+ if (Corrected.getCorrectionSpecifier())
+ tmpSS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(),
+ SourceRange(IILoc));
+ SuggestedType = getTypeName(*Corrected.getCorrectionAsIdentifierInfo(),
+ IILoc, S, tmpSS.isSet() ? &tmpSS : SS, false,
+ false, ParsedType(),
/*IsCtorOrDtorName=*/false,
/*NonTrivialTypeSourceInfo=*/true);
}
@@ -460,7 +447,7 @@ bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
if (isTemplateName(S, SS ? *SS : EmptySS, /*hasTemplateKeyword=*/false,
Name, ParsedType(), true, TemplateResult,
MemberOfUnknownSpecialization) == TNK_Type_template) {
- TemplateName TplName = TemplateResult.getAsVal<TemplateName>();
+ TemplateName TplName = TemplateResult.get();
Diag(IILoc, diag::err_template_missing_args) << TplName;
if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) {
Diag(TplDecl->getLocation(), diag::note_template_decl_here)
@@ -662,9 +649,7 @@ Corrected:
&SS, *CCC)) {
unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
unsigned QualifiedDiag = diag::err_no_member_suggest;
- std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
- std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
-
+
NamedDecl *FirstDecl = Corrected.getCorrectionDecl();
NamedDecl *UnderlyingFirstDecl
= FirstDecl? FirstDecl->getUnderlyingDecl() : 0;
@@ -680,33 +665,30 @@ Corrected:
QualifiedDiag = diag::err_unknown_nested_typename_suggest;
}
- if (SS.isEmpty())
- Diag(NameLoc, UnqualifiedDiag)
- << Name << CorrectedQuotedStr
- << FixItHint::CreateReplacement(NameLoc, CorrectedStr);
- else // FIXME: is this even reachable? Test it.
- Diag(NameLoc, QualifiedDiag)
- << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
- << SS.getRange()
- << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
- CorrectedStr);
+ if (SS.isEmpty()) {
+ diagnoseTypo(Corrected, PDiag(UnqualifiedDiag) << Name);
+ } else {// FIXME: is this even reachable? Test it.
+ std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
+ bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
+ Name->getName().equals(CorrectedStr);
+ diagnoseTypo(Corrected, PDiag(QualifiedDiag)
+ << Name << computeDeclContext(SS, false)
+ << DroppedSpecifier << SS.getRange());
+ }
// Update the name, so that the caller has the new name.
Name = Corrected.getCorrectionAsIdentifierInfo();
-
+
// Typo correction corrected to a keyword.
if (Corrected.isKeyword())
- return Corrected.getCorrectionAsIdentifierInfo();
+ return Name;
// Also update the LookupResult...
// FIXME: This should probably go away at some point
Result.clear();
Result.setLookupName(Corrected.getCorrection());
- if (FirstDecl) {
+ if (FirstDecl)
Result.addDecl(FirstDecl);
- Diag(FirstDecl->getLocation(), diag::note_previous_decl)
- << CorrectedQuotedStr;
- }
// If we found an Objective-C instance variable, let
// LookupInObjCMethod build the appropriate expression to
@@ -789,6 +771,7 @@ Corrected:
if (!Result.empty()) {
bool IsFunctionTemplate;
+ bool IsVarTemplate;
TemplateName Template;
if (Result.end() - Result.begin() > 1) {
IsFunctionTemplate = true;
@@ -798,7 +781,8 @@ Corrected:
TemplateDecl *TD
= cast<TemplateDecl>((*Result.begin())->getUnderlyingDecl());
IsFunctionTemplate = isa<FunctionTemplateDecl>(TD);
-
+ IsVarTemplate = isa<VarTemplateDecl>(TD);
+
if (SS.isSet() && !SS.isInvalid())
Template = Context.getQualifiedTemplateName(SS.getScopeRep(),
/*TemplateKeyword=*/false,
@@ -815,8 +799,9 @@ Corrected:
return NameClassification::FunctionTemplate(Template);
}
-
- return NameClassification::TypeTemplate(Template);
+
+ return IsVarTemplate ? NameClassification::VarTemplate(Template)
+ : NameClassification::TypeTemplate(Template);
}
}
@@ -858,18 +843,16 @@ Corrected:
// Check for a tag type hidden by a non-type decl in a few cases where it
// seems likely a type is wanted instead of the non-type that was found.
- if (!getLangOpts().ObjC1) {
- bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star);
- if ((NextToken.is(tok::identifier) ||
- (NextIsOp && FirstDecl->isFunctionOrFunctionTemplate())) &&
- isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) {
- TypeDecl *Type = Result.getAsSingle<TypeDecl>();
- DiagnoseUseOfDecl(Type, NameLoc);
- QualType T = Context.getTypeDeclType(Type);
- if (SS.isNotEmpty())
- return buildNestedType(*this, SS, T, NameLoc);
- return ParsedType::make(T);
- }
+ bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star);
+ if ((NextToken.is(tok::identifier) ||
+ (NextIsOp && FirstDecl->isFunctionOrFunctionTemplate())) &&
+ isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) {
+ TypeDecl *Type = Result.getAsSingle<TypeDecl>();
+ DiagnoseUseOfDecl(Type, NameLoc);
+ QualType T = Context.getTypeDeclType(Type);
+ if (SS.isNotEmpty())
+ return buildNestedType(*this, SS, T, NameLoc);
+ return ParsedType::make(T);
}
if (FirstDecl->isCXXClassMember())
@@ -887,7 +870,16 @@ DeclContext *Sema::getContainingDC(DeclContext *DC) {
// Functions defined inline within classes aren't parsed until we've
// finished parsing the top-level class, so the top-level class is
// the context we'll need to return to.
- if (isa<FunctionDecl>(DC)) {
+ // A Lambda call operator whose parent is a class must not be treated
+ // as an inline member function. A Lambda can be used legally
+ // either as an in-class member initializer or a default argument. These
+ // are parsed once the class has been marked complete and so the containing
+ // context would be the nested class (when the lambda is defined in one);
+ // If the class is not complete, then the lambda is being used in an
+ // ill-formed fashion (such as to specify the width of a bit-field, or
+ // in an array-bound) - in which case we still want to return the
+ // lexically containing DC (which could be a nested class).
+ if (isa<FunctionDecl>(DC) && !isLambdaCallOperator(DC)) {
DC = DC->getLexicalParent();
// A function not defined within a class will always return to its
@@ -962,7 +954,7 @@ void Sema::ExitDeclaratorContext(Scope *S) {
// enforced by an assert in EnterDeclaratorContext.
Scope *Ancestor = S->getParent();
while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
- CurContext = (DeclContext*) Ancestor->getEntity();
+ CurContext = Ancestor->getEntity();
// We don't need to do anything with the scope, which is going to
// disappear.
@@ -1032,8 +1024,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
// Move up the scope chain until we find the nearest enclosing
// non-transparent context. The declaration will be introduced into this
// scope.
- while (S->getEntity() &&
- ((DeclContext *)S->getEntity())->isTransparentContext())
+ while (S->getEntity() && S->getEntity()->isTransparentContext())
S = S->getParent();
// Add scoped declarations into their context, so that they can be
@@ -1042,12 +1033,12 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
if (AddToContext)
CurContext->addDecl(D);
- // Out-of-line definitions shouldn't be pushed into scope in C++.
- // Out-of-line variable and function definitions shouldn't even in C.
- if ((getLangOpts().CPlusPlus || isa<VarDecl>(D) || isa<FunctionDecl>(D)) &&
- D->isOutOfLine() &&
+ // Out-of-line definitions shouldn't be pushed into scope in C++, unless they
+ // are function-local declarations.
+ if (getLangOpts().CPlusPlus && D->isOutOfLine() &&
!D->getDeclContext()->getRedeclContext()->Equals(
- D->getLexicalDeclContext()->getRedeclContext()))
+ D->getLexicalDeclContext()->getRedeclContext()) &&
+ !D->getLexicalDeclContext()->isFunctionOrMethod())
return;
// Template instantiations should also not be pushed into scope.
@@ -1094,7 +1085,7 @@ void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
TUScope->AddDecl(D);
}
-bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S,
+bool Sema::isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S,
bool ExplicitInstantiationOrSpecialization) {
return IdResolver.isDeclInScope(D, Ctx, S,
ExplicitInstantiationOrSpecialization);
@@ -1103,7 +1094,7 @@ bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S,
Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) {
DeclContext *TargetDC = DC->getPrimaryContext();
do {
- if (DeclContext *ScopeDC = (DeclContext*) S->getEntity())
+ if (DeclContext *ScopeDC = S->getEntity())
if (ScopeDC->getPrimaryContext() == TargetDC)
return S;
} while ((S = S->getParent()));
@@ -1196,7 +1187,15 @@ bool Sema::mightHaveNonExternalLinkage(const DeclaratorDecl *D) {
DC = DC->getParent();
}
- return !D->hasExternalLinkage();
+ return !D->isExternallyVisible();
+}
+
+// FIXME: This needs to be refactored; some other isInMainFile users want
+// these semantics.
+static bool isMainFileLoc(const Sema &S, SourceLocation Loc) {
+ if (S.TUKind != TU_Complete)
+ return false;
+ return S.SourceMgr.isInMainFile(Loc);
}
bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
@@ -1218,12 +1217,9 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD))
return false;
} else {
- // 'static inline' functions are used in headers; don't warn.
- // Make sure we get the storage class from the canonical declaration,
- // since otherwise we will get spurious warnings on specialized
- // static template functions.
- if (FD->getCanonicalDecl()->getStorageClass() == SC_Static &&
- FD->isInlineSpecified())
+ // 'static inline' functions are defined in headers; don't warn.
+ if (FD->isInlineSpecified() &&
+ !isMainFileLoc(*this, FD->getLocation()))
return false;
}
@@ -1231,21 +1227,18 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
Context.DeclMustBeEmitted(FD))
return false;
} else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- // Don't warn on variables of const-qualified or reference type, since their
- // values can be used even if though they're not odr-used, and because const
- // qualified variables can appear in headers in contexts where they're not
- // intended to be used.
- // FIXME: Use more principled rules for these exemptions.
- if (!VD->isFileVarDecl() ||
- VD->getType().isConstQualified() ||
- VD->getType()->isReferenceType() ||
- Context.DeclMustBeEmitted(VD))
+ // Constants and utility variables are defined in headers with internal
+ // linkage; don't warn. (Unlike functions, there isn't a convenient marker
+ // like "inline".)
+ if (!isMainFileLoc(*this, VD->getLocation()))
+ return false;
+
+ if (Context.DeclMustBeEmitted(VD))
return false;
if (VD->isStaticDataMember() &&
VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
return false;
-
} else {
return false;
}
@@ -1259,13 +1252,13 @@ void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) {
return;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- const FunctionDecl *First = FD->getFirstDeclaration();
+ const FunctionDecl *First = FD->getFirstDecl();
if (FD != First && ShouldWarnIfUnusedFileScopedDecl(First))
return; // First should already be in the vector.
}
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- const VarDecl *First = VD->getFirstDeclaration();
+ const VarDecl *First = VD->getFirstDecl();
if (VD != First && ShouldWarnIfUnusedFileScopedDecl(First))
return; // First should already be in the vector.
}
@@ -1312,7 +1305,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
return false;
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) {
- if (!RD->hasTrivialDestructor())
+ if (!RD->hasTrivialDestructor() && !RD->hasAttr<WarnUnusedAttr>())
return false;
if (const Expr *Init = VD->getInit()) {
@@ -1322,7 +1315,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
dyn_cast<CXXConstructExpr>(Init);
if (Construct && !Construct->isElidable()) {
CXXConstructorDecl *CD = Construct->getConstructor();
- if (!CD->isTrivial())
+ if (!CD->isTrivial() && !RD->hasAttr<WarnUnusedAttr>())
return false;
}
}
@@ -1402,6 +1395,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
// Remove this name from our lexical scope.
IdResolver.RemoveDecl(D);
}
+ DiagnoseUnusedBackingIvarInAccessor(S);
}
void Sema::ActOnStartFunctionDeclarator() {
@@ -1440,13 +1434,8 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
if (TypoCorrection C = CorrectTypo(DeclarationNameInfo(Id, IdLoc),
LookupOrdinaryName, TUScope, NULL,
Validator)) {
+ diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id);
IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>();
- Diag(IdLoc, diag::err_undef_interface_suggest)
- << Id << IDecl->getDeclName()
- << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString());
- Diag(IDecl->getLocation(), diag::note_previous_decl)
- << IDecl->getDeclName();
-
Id = IDecl->getIdentifier();
}
}
@@ -1482,8 +1471,7 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
/// contain non-field names.
Scope *Sema::getNonFieldDeclScope(Scope *S) {
while (((S->getFlags() & Scope::DeclScope) == 0) ||
- (S->getEntity() &&
- ((DeclContext *)S->getEntity())->isTransparentContext()) ||
+ (S->getEntity() && S->getEntity()->isTransparentContext()) ||
(S->isClassScope() && !getLangOpts().CPlusPlus))
S = S->getParent();
return S;
@@ -1556,8 +1544,17 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
<< Context.BuiltinInfo.GetName(BID);
}
+ DeclContext *Parent = Context.getTranslationUnitDecl();
+ if (getLangOpts().CPlusPlus) {
+ LinkageSpecDecl *CLinkageDecl =
+ LinkageSpecDecl::Create(Context, Parent, Loc, Loc,
+ LinkageSpecDecl::lang_c, false);
+ Parent->addDecl(CLinkageDecl);
+ Parent = CLinkageDecl;
+ }
+
FunctionDecl *New = FunctionDecl::Create(Context,
- Context.getTranslationUnitDecl(),
+ Parent,
Loc, Loc, II, R, /*TInfo=*/0,
SC_Extern,
false,
@@ -1581,13 +1578,14 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
}
AddKnownFunctionAttributes(New);
+ RegisterLocallyScopedExternCDecl(New, S);
// TUScope is the translation-unit scope to insert this function into.
// FIXME: This is hideous. We need to teach PushOnScopeChains to
// relate Scopes to DeclContexts, and probably eliminate CurContext
// entirely, but we're not there yet.
DeclContext *SavedContext = CurContext;
- CurContext = Context.getTranslationUnitDecl();
+ CurContext = Parent;
PushOnScopeChains(New, TUScope);
CurContext = SavedContext;
return New;
@@ -1616,7 +1614,7 @@ static void filterNonConflictingPreviousDecls(ASTContext &context,
if (!old->isHidden())
continue;
- if (old->getLinkage() != ExternalLinkage)
+ if (!old->isExternallyVisible())
filter.erase();
}
@@ -1730,10 +1728,12 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
if (isIncompatibleTypedef(Old, New))
return;
- // The types match. Link up the redeclaration chain if the old
- // declaration was a typedef.
- if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old))
- New->setPreviousDeclaration(Typedef);
+ // The types match. Link up the redeclaration chain and merge attributes if
+ // the old declaration was a typedef.
+ if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old)) {
+ New->setPreviousDecl(Typedef);
+ mergeDeclAttributes(New, Old);
+ }
if (getLangOpts().MicrosoftExt)
return;
@@ -2014,11 +2014,15 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, InheritableAttr *Attr,
static const Decl *getDefinition(const Decl *D) {
if (const TagDecl *TD = dyn_cast<TagDecl>(D))
return TD->getDefinition();
- if (const VarDecl *VD = dyn_cast<VarDecl>(D))
- return VD->getDefinition();
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ const VarDecl *Def = VD->getDefinition();
+ if (Def)
+ return Def;
+ return VD->getActingDefinition();
+ }
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
const FunctionDecl* Def;
- if (FD->hasBody(Def))
+ if (FD->isDefined(Def))
return Def;
}
return NULL;
@@ -2047,6 +2051,32 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
AttrVec &NewAttributes = New->getAttrs();
for (unsigned I = 0, E = NewAttributes.size(); I != E;) {
const Attr *NewAttribute = NewAttributes[I];
+
+ if (isa<AliasAttr>(NewAttribute)) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New))
+ S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def));
+ else {
+ VarDecl *VD = cast<VarDecl>(New);
+ unsigned Diag = cast<VarDecl>(Def)->isThisDeclarationADefinition() ==
+ VarDecl::TentativeDefinition
+ ? diag::err_alias_after_tentative
+ : diag::err_redefinition;
+ S.Diag(VD->getLocation(), Diag) << VD->getDeclName();
+ S.Diag(Def->getLocation(), diag::note_previous_definition);
+ VD->setInvalidDecl();
+ }
+ ++I;
+ continue;
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(Def)) {
+ // Tentative definitions are only interesting for the alias check above.
+ if (VD->isThisDeclarationADefinition() != VarDecl::Definition) {
+ ++I;
+ continue;
+ }
+ }
+
if (hasAttribute(Def, NewAttribute->getKind())) {
++I;
continue; // regular attr merging will take care of validating this.
@@ -2087,6 +2117,12 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
/// mergeDeclAttributes - Copy attributes from the Old decl to the New one.
void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
AvailabilityMergeKind AMK) {
+ if (UsedAttr *OldAttr = Old->getMostRecentDecl()->getAttr<UsedAttr>()) {
+ UsedAttr *NewAttr = OldAttr->clone(Context);
+ NewAttr->setInherited(true);
+ New->addAttr(NewAttr);
+ }
+
if (!Old->hasAttrs() && !New->hasAttrs())
return;
@@ -2124,6 +2160,10 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
}
}
+ // Already handled.
+ if (isa<UsedAttr>(*i))
+ continue;
+
if (mergeDeclAttribute(*this, New, *i, Override))
foundAny = true;
}
@@ -2150,7 +2190,7 @@ static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
// Find the first declaration of the parameter.
// FIXME: Should we build redeclaration chains for function parameters?
const FunctionDecl *FirstFD =
- cast<FunctionDecl>(oldDecl->getDeclContext())->getFirstDeclaration();
+ cast<FunctionDecl>(oldDecl->getDeclContext())->getFirstDecl();
const ParmVarDecl *FirstVD =
FirstFD->getParamDecl(oldDecl->getFunctionScopeIndex());
S.Diag(FirstVD->getLocation(),
@@ -2226,17 +2266,11 @@ static bool canRedefineFunction(const FunctionDecl *FD,
FD->getStorageClass() == SC_Extern);
}
-/// Is the given calling convention the ABI default for the given
-/// declaration?
-static bool isABIDefaultCC(Sema &S, CallingConv CC, FunctionDecl *D) {
- CallingConv ABIDefaultCC;
- if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) {
- ABIDefaultCC = S.Context.getDefaultCXXMethodCallConv(D->isVariadic());
- } else {
- // Free C function or a static method.
- ABIDefaultCC = (S.Context.getLangOpts().MRTD ? CC_X86StdCall : CC_C);
- }
- return ABIDefaultCC == CC;
+const AttributedType *Sema::getCallingConvAttributedType(QualType T) const {
+ const AttributedType *AT = T->getAs<AttributedType>();
+ while (AT && !AT->isCallingConv())
+ AT = AT->getModifiedType()->getAs<AttributedType>();
+ return AT;
}
template <typename T>
@@ -2264,7 +2298,8 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
/// merged with.
///
/// Returns true if there was an error, false otherwise.
-bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
+bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
+ bool MergeTypeWithOld) {
// Verify the old decl was also a function.
FunctionDecl *Old = 0;
if (FunctionTemplateDecl *OldFunctionTemplate
@@ -2297,6 +2332,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
return true;
}
+ // If the old declaration is invalid, just give up here.
+ if (Old->isInvalidDecl())
+ return true;
+
// Determine whether the previous declaration was a definition,
// implicit declaration, or a declaration.
diag::kind PrevDiag;
@@ -2307,16 +2346,13 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
else
PrevDiag = diag::note_previous_declaration;
- QualType OldQType = Context.getCanonicalType(Old->getType());
- QualType NewQType = Context.getCanonicalType(New->getType());
-
// Don't complain about this if we're in GNU89 mode and the old function
// is an extern inline function.
// Don't complain about specializations. They are not supposed to have
// storage classes.
if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) &&
New->getStorageClass() == SC_Static &&
- isExternalLinkage(Old->getLinkage()) &&
+ Old->hasExternalFormalLinkage() &&
!New->getTemplateSpecializationInfo() &&
!canRedefineFunction(Old, getLangOpts())) {
if (getLangOpts().MicrosoftExt) {
@@ -2329,53 +2365,52 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
}
}
- // If a function is first declared with a calling convention, but is
- // later declared or defined without one, the second decl assumes the
- // calling convention of the first.
+
+ // If a function is first declared with a calling convention, but is later
+ // declared or defined without one, all following decls assume the calling
+ // convention of the first.
//
// It's OK if a function is first declared without a calling convention,
// but is later declared or defined with the default calling convention.
//
- // For the new decl, we have to look at the NON-canonical type to tell the
- // difference between a function that really doesn't have a calling
- // convention and one that is declared cdecl. That's because in
- // canonicalization (see ASTContext.cpp), cdecl is canonicalized away
- // because it is the default calling convention.
+ // To test if either decl has an explicit calling convention, we look for
+ // AttributedType sugar nodes on the type as written. If they are missing or
+ // were canonicalized away, we assume the calling convention was implicit.
//
// Note also that we DO NOT return at this point, because we still have
// other tests to run.
+ QualType OldQType = Context.getCanonicalType(Old->getType());
+ QualType NewQType = Context.getCanonicalType(New->getType());
const FunctionType *OldType = cast<FunctionType>(OldQType);
- const FunctionType *NewType = New->getType()->getAs<FunctionType>();
+ const FunctionType *NewType = cast<FunctionType>(NewQType);
FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo();
FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
bool RequiresAdjustment = false;
- if (OldTypeInfo.getCC() == NewTypeInfo.getCC()) {
- // Fast path: nothing to do.
-
- // Inherit the CC from the previous declaration if it was specified
- // there but not here.
- } else if (NewTypeInfo.getCC() == CC_Default) {
- NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
- RequiresAdjustment = true;
- // Don't complain about mismatches when the default CC is
- // effectively the same as the explict one. Only Old decl contains correct
- // information about storage class of CXXMethod.
- } else if (OldTypeInfo.getCC() == CC_Default &&
- isABIDefaultCC(*this, NewTypeInfo.getCC(), Old)) {
- NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
- RequiresAdjustment = true;
-
- } else if (!Context.isSameCallConv(OldTypeInfo.getCC(),
- NewTypeInfo.getCC())) {
- // Calling conventions really aren't compatible, so complain.
- Diag(New->getLocation(), diag::err_cconv_change)
- << FunctionType::getNameForCallConv(NewTypeInfo.getCC())
- << (OldTypeInfo.getCC() == CC_Default)
- << (OldTypeInfo.getCC() == CC_Default ? "" :
- FunctionType::getNameForCallConv(OldTypeInfo.getCC()));
- Diag(Old->getLocation(), diag::note_previous_declaration);
- return true;
+ if (OldTypeInfo.getCC() != NewTypeInfo.getCC()) {
+ FunctionDecl *First = Old->getFirstDecl();
+ const FunctionType *FT =
+ First->getType().getCanonicalType()->castAs<FunctionType>();
+ FunctionType::ExtInfo FI = FT->getExtInfo();
+ bool NewCCExplicit = getCallingConvAttributedType(New->getType());
+ if (!NewCCExplicit) {
+ // Inherit the CC from the previous declaration if it was specified
+ // there but not here.
+ NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
+ RequiresAdjustment = true;
+ } else {
+ // Calling conventions aren't compatible, so complain.
+ bool FirstCCExplicit = getCallingConvAttributedType(First->getType());
+ Diag(New->getLocation(), diag::err_cconv_change)
+ << FunctionType::getNameForCallConv(NewTypeInfo.getCC())
+ << !FirstCCExplicit
+ << (!FirstCCExplicit ? "" :
+ FunctionType::getNameForCallConv(FI.getCC()));
+
+ // Put the note on the first decl, since it is the one that matters.
+ Diag(First->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
}
// FIXME: diagnose the other way around?
@@ -2412,9 +2447,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
}
if (RequiresAdjustment) {
- NewType = Context.adjustFunctionType(NewType, NewTypeInfo);
- New->setType(QualType(NewType, 0));
+ const FunctionType *AdjustedType = New->getType()->getAs<FunctionType>();
+ AdjustedType = Context.adjustFunctionType(AdjustedType, NewTypeInfo);
+ New->setType(QualType(AdjustedType, 0));
NewQType = Context.getCanonicalType(New->getType());
+ NewType = cast<FunctionType>(NewQType);
}
// If this redeclaration makes the function inline, we may need to add it to
@@ -2441,7 +2478,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
// cannot be overloaded.
// Go back to the type source info to compare the declared return types,
- // per C++1y [dcl.type.auto]p??:
+ // per C++1y [dcl.type.auto]p13:
// Redeclarations or specializations of a function or function template
// with a declared return type that uses a placeholder type shall also
// use that placeholder, not a deduced type.
@@ -2452,7 +2489,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
? New->getTypeSourceInfo()->getType()->castAs<FunctionType>()
: NewType)->getResultType();
QualType ResQT;
- if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType)) {
+ if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType) &&
+ !((NewQType->isDependentType() || OldQType->isDependentType()) &&
+ New->isLocalExternDecl())) {
if (NewDeclaredReturnType->isObjCObjectPointerType() &&
OldDeclaredReturnType->isObjCObjectPointerType())
ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType);
@@ -2476,9 +2515,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
// defined, copy the deduced value from the old declaration.
AutoType *OldAT = Old->getResultType()->getContainedAutoType();
if (OldAT && OldAT->isDeduced()) {
- New->setType(SubstAutoType(New->getType(), OldAT->getDeducedType()));
+ New->setType(
+ SubstAutoType(New->getType(),
+ OldAT->isDependentType() ? Context.DependentTy
+ : OldAT->getDeducedType()));
NewQType = Context.getCanonicalType(
- SubstAutoType(NewQType, OldAT->getDeducedType()));
+ SubstAutoType(NewQType,
+ OldAT->isDependentType() ? Context.DependentTy
+ : OldAT->getDeducedType()));
}
}
@@ -2501,7 +2545,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
// -- Member function declarations with the same name and the
// same parameter types cannot be overloaded if any of them
// is a static member function declaration.
- if (OldMethod->isStatic() || NewMethod->isStatic()) {
+ if (OldMethod->isStatic() != NewMethod->isStatic()) {
Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
return true;
@@ -2559,7 +2603,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
!Old->hasAttr<CXX11NoReturnAttr>()) {
Diag(New->getAttr<CXX11NoReturnAttr>()->getLocation(),
diag::err_noreturn_missing_on_first_decl);
- Diag(Old->getFirstDeclaration()->getLocation(),
+ Diag(Old->getFirstDecl()->getLocation(),
diag::note_noreturn_missing_first_decl);
}
@@ -2571,7 +2615,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
!Old->hasAttr<CarriesDependencyAttr>()) {
Diag(New->getAttr<CarriesDependencyAttr>()->getLocation(),
diag::err_carries_dependency_missing_on_first_decl) << 0/*Function*/;
- Diag(Old->getFirstDeclaration()->getLocation(),
+ Diag(Old->getFirstDecl()->getLocation(),
diag::note_carries_dependency_missing_first_decl) << 0/*Function*/;
}
@@ -2591,13 +2635,34 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
}
if (haveIncompatibleLanguageLinkages(Old, New)) {
- Diag(New->getLocation(), diag::err_different_language_linkage) << New;
- Diag(Old->getLocation(), PrevDiag);
- return true;
+ // As a special case, retain the language linkage from previous
+ // declarations of a friend function as an extension.
+ //
+ // This liberal interpretation of C++ [class.friend]p3 matches GCC/MSVC
+ // and is useful because there's otherwise no way to specify language
+ // linkage within class scope.
+ //
+ // Check cautiously as the friend object kind isn't yet complete.
+ if (New->getFriendObjectKind() != Decl::FOK_None) {
+ Diag(New->getLocation(), diag::ext_retained_language_linkage) << New;
+ Diag(Old->getLocation(), PrevDiag);
+ } else {
+ Diag(New->getLocation(), diag::err_different_language_linkage) << New;
+ Diag(Old->getLocation(), PrevDiag);
+ return true;
+ }
}
if (OldQTypeForComparison == NewQType)
- return MergeCompatibleFunctionDecls(New, Old, S);
+ return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld);
+
+ if ((NewQType->isDependentType() || OldQType->isDependentType()) &&
+ New->isLocalExternDecl()) {
+ // It's OK if we couldn't merge types for a local function declaraton
+ // if either the old or new type is dependent. We'll merge the types
+ // when we instantiate the function.
+ return false;
+ }
// Fall through for conflicting redeclarations and redefinitions.
}
@@ -2609,7 +2674,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
const FunctionType *OldFuncType = OldQType->getAs<FunctionType>();
const FunctionType *NewFuncType = NewQType->getAs<FunctionType>();
const FunctionProtoType *OldProto = 0;
- if (isa<FunctionNoProtoType>(NewFuncType) &&
+ if (MergeTypeWithOld && isa<FunctionNoProtoType>(NewFuncType) &&
(OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) {
// The old declaration provided a function prototype, but the
// new declaration does not. Merge in the prototype.
@@ -2642,7 +2707,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
New->setParams(Params);
}
- return MergeCompatibleFunctionDecls(New, Old, S);
+ return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld);
}
// GNU C permits a K&R definition to follow a prototype declaration
@@ -2700,9 +2765,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
diag::note_previous_declaration);
}
- New->setType(Context.getFunctionType(MergedReturn, ArgTypes,
- OldProto->getExtProtoInfo()));
- return MergeCompatibleFunctionDecls(New, Old, S);
+ if (MergeTypeWithOld)
+ New->setType(Context.getFunctionType(MergedReturn, ArgTypes,
+ OldProto->getExtProtoInfo()));
+ return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld);
}
// Fall through to diagnose conflicting types.
@@ -2730,7 +2796,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
// local declaration will produce a hard error; if it doesn't
// remain visible, a single bogus local redeclaration (which is
// actually only a warning) could break all the downstream code.
- if (!New->getDeclContext()->isFunctionOrMethod())
+ if (!New->getLexicalDeclContext()->isFunctionOrMethod())
New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin);
return false;
@@ -2748,13 +2814,13 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
/// known to be compatible.
///
/// This routine handles the merging of attributes and other
-/// properties of function declarations form the old declaration to
+/// properties of function declarations from the old declaration to
/// the new declaration, once we know that New is in fact a
/// redeclaration of Old.
///
/// \returns false
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
- Scope *S) {
+ Scope *S, bool MergeTypeWithOld) {
// Merge the attributes
mergeDeclAttributes(New, Old);
@@ -2763,8 +2829,8 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
New->setPure();
// Merge "used" flag.
- if (Old->isUsed(false))
- New->setUsed();
+ if (Old->getMostRecentDecl()->isUsed(false))
+ New->setIsUsed();
// Merge attributes from the parameters. These can mismatch with K&R
// declarations.
@@ -2777,9 +2843,10 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
return MergeCXXFunctionDecl(New, Old, S);
// Merge the function types so the we get the composite types for the return
- // and argument types.
+ // and argument types. Per C11 6.2.7/4, only update the type if the old decl
+ // was visible.
QualType Merged = Context.mergeTypes(Old->getType(), New->getType());
- if (!Merged.isNull())
+ if (!Merged.isNull() && MergeTypeWithOld)
New->setType(Merged);
return false;
@@ -2813,7 +2880,8 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
/// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back
/// to here in AddInitializerToDecl. We can't check them before the initializer
/// is attached.
-void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) {
+void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old,
+ bool MergeTypeWithOld) {
if (New->isInvalidDecl() || Old->isInvalidDecl())
return;
@@ -2839,21 +2907,48 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) {
NewArray->getElementType()))
MergedT = New->getType();
} else if (Old->getType()->isArrayType() &&
- New->getType()->isIncompleteArrayType()) {
+ New->getType()->isIncompleteArrayType()) {
const ArrayType *OldArray = Context.getAsArrayType(Old->getType());
const ArrayType *NewArray = Context.getAsArrayType(New->getType());
if (Context.hasSameType(OldArray->getElementType(),
NewArray->getElementType()))
MergedT = Old->getType();
- } else if (New->getType()->isObjCObjectPointerType()
- && Old->getType()->isObjCObjectPointerType()) {
- MergedT = Context.mergeObjCGCQualifiers(New->getType(),
- Old->getType());
+ } else if (New->getType()->isObjCObjectPointerType() &&
+ Old->getType()->isObjCObjectPointerType()) {
+ MergedT = Context.mergeObjCGCQualifiers(New->getType(),
+ Old->getType());
}
} else {
+ // C 6.2.7p2:
+ // All declarations that refer to the same object or function shall have
+ // compatible type.
MergedT = Context.mergeTypes(New->getType(), Old->getType());
}
if (MergedT.isNull()) {
+ // It's OK if we couldn't merge types if either type is dependent, for a
+ // block-scope variable. In other cases (static data members of class
+ // templates, variable templates, ...), we require the types to be
+ // equivalent.
+ // FIXME: The C++ standard doesn't say anything about this.
+ if ((New->getType()->isDependentType() ||
+ Old->getType()->isDependentType()) && New->isLocalVarDecl()) {
+ // If the old type was dependent, we can't merge with it, so the new type
+ // becomes dependent for now. We'll reproduce the original type when we
+ // instantiate the TypeSourceInfo for the variable.
+ if (!New->getType()->isDependentType() && MergeTypeWithOld)
+ New->setType(Context.DependentTy);
+ return;
+ }
+
+ // FIXME: Even if this merging succeeds, some other non-visible declaration
+ // of this variable might have an incompatible type. For instance:
+ //
+ // extern int arr[];
+ // void f() { extern int arr[2]; }
+ // void g() { extern int arr[3]; }
+ //
+ // Neither C nor C++ requires a diagnostic for this, but we should still try
+ // to diagnose it.
Diag(New->getLocation(), diag::err_redefinition_different_type)
<< New->getDeclName() << New->getType() << Old->getType();
Diag(Old->getLocation(), diag::note_previous_definition);
@@ -2861,11 +2956,40 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) {
}
// Don't actually update the type on the new declaration if the old
- // declaration was a extern declaration in a different scope.
- if (!OldWasHidden)
+ // declaration was an extern declaration in a different scope.
+ if (MergeTypeWithOld)
New->setType(MergedT);
}
+static bool mergeTypeWithPrevious(Sema &S, VarDecl *NewVD, VarDecl *OldVD,
+ LookupResult &Previous) {
+ // C11 6.2.7p4:
+ // For an identifier with internal or external linkage declared
+ // in a scope in which a prior declaration of that identifier is
+ // visible, if the prior declaration specifies internal or
+ // external linkage, the type of the identifier at the later
+ // declaration becomes the composite type.
+ //
+ // If the variable isn't visible, we do not merge with its type.
+ if (Previous.isShadowed())
+ return false;
+
+ if (S.getLangOpts().CPlusPlus) {
+ // C++11 [dcl.array]p3:
+ // If there is a preceding declaration of the entity in the same
+ // scope in which the bound was specified, an omitted array bound
+ // is taken to be the same as in that earlier declaration.
+ return NewVD->isPreviousDeclInSameBlockScope() ||
+ (!OldVD->getLexicalDeclContext()->isFunctionOrMethod() &&
+ !NewVD->getLexicalDeclContext()->isFunctionOrMethod());
+ } else {
+ // If the old declaration was function-local, don't merge with its
+ // type unless we're in the same function.
+ return !OldVD->getLexicalDeclContext()->isFunctionOrMethod() ||
+ OldVD->getLexicalDeclContext() == NewVD->getLexicalDeclContext();
+ }
+}
+
/// MergeVarDecl - We just parsed a variable '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.
@@ -2874,16 +2998,21 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) {
/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
/// definitions here, since the initializer hasn't been attached.
///
-void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous,
- bool PreviousWasHidden) {
+void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
// If the new decl is already invalid, don't do any other checking.
if (New->isInvalidDecl())
return;
- // Verify the old decl was also a variable.
+ // Verify the old decl was also a variable or variable template.
VarDecl *Old = 0;
- if (!Previous.isSingleResult() ||
- !(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
+ if (Previous.isSingleResult() &&
+ (Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
+ if (New->getDescribedVarTemplate())
+ Old = Old->getDescribedVarTemplate() ? Old : 0;
+ else
+ Old = Old->getDescribedVarTemplate() ? 0 : Old;
+ }
+ if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
Diag(Previous.getRepresentativeDecl()->getLocation(),
@@ -2918,14 +3047,15 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous,
}
// Merge the types.
- MergeVarDeclTypes(New, Old, PreviousWasHidden);
+ MergeVarDeclTypes(New, Old, mergeTypeWithPrevious(*this, New, Old, Previous));
+
if (New->isInvalidDecl())
return;
// [dcl.stc]p8: Check if we have a non-static decl followed by a static.
if (New->getStorageClass() == SC_Static &&
!New->isStaticDataMember() &&
- isExternalLinkage(Old->getLinkage())) {
+ Old->hasExternalFormalLinkage()) {
Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
@@ -2999,8 +3129,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous,
if (getLangOpts().CPlusPlus &&
New->isThisDeclarationADefinition() == VarDecl::Definition &&
(Def = Old->getDefinition())) {
- Diag(New->getLocation(), diag::err_redefinition)
- << New->getDeclName();
+ Diag(New->getLocation(), diag::err_redefinition) << New;
Diag(Def->getLocation(), diag::note_previous_definition);
New->setInvalidDecl();
return;
@@ -3014,14 +3143,19 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous,
}
// Merge "used" flag.
- if (Old->isUsed(false))
- New->setUsed();
+ if (Old->getMostRecentDecl()->isUsed(false))
+ New->setIsUsed();
// Keep a chain of previous declarations.
- New->setPreviousDeclaration(Old);
+ New->setPreviousDecl(Old);
// Inherit access appropriately.
New->setAccess(Old->getAccess());
+
+ if (VarTemplateDecl *VTD = New->getDescribedVarTemplate()) {
+ if (New->isStaticDataMember() && New->isOutOfLine())
+ VTD->setAccess(New->getAccess());
+ }
}
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
@@ -3031,6 +3165,30 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg());
}
+static void HandleTagNumbering(Sema &S, const TagDecl *Tag) {
+ if (!S.Context.getLangOpts().CPlusPlus)
+ return;
+
+ if (isa<CXXRecordDecl>(Tag->getParent())) {
+ // If this tag is the direct child of a class, number it if
+ // it is anonymous.
+ if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl())
+ return;
+ MangleNumberingContext &MCtx =
+ S.Context.getManglingNumberContext(Tag->getParent());
+ S.Context.setManglingNumber(Tag, MCtx.getManglingNumber(Tag));
+ return;
+ }
+
+ // If this tag isn't a direct child of a class, number it if it is local.
+ Decl *ManglingContextDecl;
+ if (MangleNumberingContext *MCtx =
+ S.getCurrentMangleNumberContext(Tag->getDeclContext(),
+ ManglingContextDecl)) {
+ S.Context.setManglingNumber(Tag, MCtx->getManglingNumber(Tag));
+ }
+}
+
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
/// no declarator (e.g. "struct foo;") is parsed. It also accepts template
/// parameters to cope with template friend declarations.
@@ -3060,7 +3218,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
}
if (Tag) {
- getASTContext().addUnnamedTag(Tag);
+ HandleTagNumbering(*this, Tag);
Tag->setFreeStanding();
if (Tag->isInvalidDecl())
return Tag;
@@ -3301,11 +3459,11 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
/// This routine is recursive, injecting the names of nested anonymous
/// structs/unions into the owning context and scope as well.
static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
- DeclContext *Owner,
- RecordDecl *AnonRecord,
- AccessSpecifier AS,
- SmallVector<NamedDecl*, 2> &Chaining,
- bool MSAnonStruct) {
+ DeclContext *Owner,
+ RecordDecl *AnonRecord,
+ AccessSpecifier AS,
+ SmallVectorImpl<NamedDecl *> &Chaining,
+ bool MSAnonStruct) {
unsigned diagKind
= AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl
: diag::err_anonymous_struct_member_redecl;
@@ -3961,7 +4119,7 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
DeclarationName Name,
SourceLocation Loc) {
DeclContext *Cur = CurContext;
- while (isa<LinkageSpecDecl>(Cur))
+ while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur))
Cur = Cur->getParent();
// C++ [dcl.meaning]p1:
@@ -3999,6 +4157,9 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
else if (isa<FunctionDecl>(Cur))
Diag(Loc, diag::err_invalid_declarator_in_function)
<< Name << SS.getRange();
+ else if (isa<BlockDecl>(Cur))
+ Diag(Loc, diag::err_invalid_declarator_in_block)
+ << Name << SS.getRange();
else
Diag(Loc, diag::err_invalid_declarator_scope)
<< Name << cast<NamedDecl>(Cur) << cast<NamedDecl>(DC) << SS.getRange();
@@ -4071,7 +4232,7 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
bool EnteringContext = !D.getDeclSpec().isFriendSpecified();
DC = computeDeclContext(D.getCXXScopeSpec(), EnteringContext);
- if (!DC) {
+ if (!DC || isa<EnumDecl>(DC)) {
// If we could not compute the declaration context, it's because the
// declaration context is dependent but does not refer to a class,
// class template, or class template partial specialization. Complain
@@ -4132,26 +4293,31 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
// See if this is a redefinition of a variable in the same scope.
if (!D.getCXXScopeSpec().isSet()) {
bool IsLinkageLookup = false;
+ bool CreateBuiltins = false;
// If the declaration we're planning to build will be a function
// or object with linkage, then look for another declaration with
// linkage (C99 6.2.2p4-5 and C++ [basic.link]p6).
+ //
+ // If the declaration we're planning to build will be declared with
+ // external linkage in the translation unit, create any builtin with
+ // the same name.
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
/* Do nothing*/;
- else if (R->isFunctionType()) {
- if (CurContext->isFunctionOrMethod() ||
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
- IsLinkageLookup = true;
- } else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern)
- IsLinkageLookup = true;
- else if (CurContext->getRedeclContext()->isTranslationUnit() &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
+ else if (CurContext->isFunctionOrMethod() &&
+ (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern ||
+ R->isFunctionType())) {
IsLinkageLookup = true;
+ CreateBuiltins =
+ CurContext->getEnclosingNamespaceContext()->isTranslationUnit();
+ } else if (CurContext->getRedeclContext()->isTranslationUnit() &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
+ CreateBuiltins = true;
if (IsLinkageLookup)
Previous.clear(LookupRedeclarationWithLinkage);
- LookupName(Previous, S, /* CreateBuiltins = */ IsLinkageLookup);
+ LookupName(Previous, S, CreateBuiltins);
} else { // Something like "int foo::x;"
LookupQualifiedName(Previous, DC);
@@ -4223,8 +4389,8 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
TemplateParamLists,
AddToScope);
} else {
- New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous,
- TemplateParamLists);
+ New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, TemplateParamLists,
+ AddToScope);
}
if (New == 0)
@@ -4233,8 +4399,15 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
// If this has an identifier and is not an invalid redeclaration or
// function template specialization, add it to the scope stack.
if (New->getDeclName() && AddToScope &&
- !(D.isRedeclaration() && New->isInvalidDecl()))
- PushOnScopeChains(New, S);
+ !(D.isRedeclaration() && New->isInvalidDecl())) {
+ // Only make a locally-scoped extern declaration visible if it is the first
+ // declaration of this entity. Qualified lookup for such an entity should
+ // only find this declaration if there is no visible declaration of it.
+ bool AddToContext = !D.isRedeclaration() || !New->isLocalExternDecl();
+ PushOnScopeChains(New, S, AddToContext);
+ if (!AddToContext)
+ CurContext->addHiddenDecl(New);
+ }
return New;
}
@@ -4356,21 +4529,26 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo,
}
/// \brief Register the given locally-scoped extern "C" declaration so
-/// that it can be found later for redeclarations
+/// that it can be found later for redeclarations. We include any extern "C"
+/// declaration that is not visible in the translation unit here, not just
+/// function-scope declarations.
void
-Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND,
- const LookupResult &Previous,
- Scope *S) {
- assert(ND->getLexicalDeclContext()->isFunctionOrMethod() &&
- "Decl is not a locally-scoped decl!");
+Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S) {
+ if (!getLangOpts().CPlusPlus &&
+ ND->getLexicalDeclContext()->getRedeclContext()->isTranslationUnit())
+ // Don't need to track declarations in the TU in C.
+ return;
+
// Note that we have a locally-scoped external with this name.
+ // FIXME: There can be multiple such declarations if they are functions marked
+ // __attribute__((overloadable)) declared in function scope in C.
LocallyScopedExternCDecls[ND->getDeclName()] = ND;
}
-llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
-Sema::findLocallyScopedExternCDecl(DeclarationName Name) {
+NamedDecl *Sema::findLocallyScopedExternCDecl(DeclarationName Name) {
if (ExternalSource) {
// Load locally-scoped external decls from the external source.
+ // FIXME: This is inefficient. Maybe add a DeclContext for extern "C" decls?
SmallVector<NamedDecl *, 4> Decls;
ExternalSource->ReadLocallyScopedExternCDecls(Decls);
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
@@ -4380,8 +4558,9 @@ Sema::findLocallyScopedExternCDecl(DeclarationName Name) {
LocallyScopedExternCDecls[Decls[I]->getDeclName()] = Decls[I];
}
}
-
- return LocallyScopedExternCDecls.find(Name);
+
+ NamedDecl *D = LocallyScopedExternCDecls.lookup(Name);
+ return D ? D->getMostRecentDecl() : 0;
}
/// \brief Diagnose function specifiers on a declaration of an identifier that
@@ -4627,17 +4806,26 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
// 'weak' only applies to declarations with external linkage.
if (WeakAttr *Attr = ND.getAttr<WeakAttr>()) {
- if (ND.getLinkage() != ExternalLinkage) {
+ if (!ND.isExternallyVisible()) {
S.Diag(Attr->getLocation(), diag::err_attribute_weak_static);
ND.dropAttr<WeakAttr>();
}
}
if (WeakRefAttr *Attr = ND.getAttr<WeakRefAttr>()) {
- if (ND.hasExternalLinkage()) {
+ if (ND.isExternallyVisible()) {
S.Diag(Attr->getLocation(), diag::err_attribute_weakref_not_static);
ND.dropAttr<WeakRefAttr>();
}
}
+
+ // 'selectany' only applies to externally visible varable declarations.
+ // It does not apply to functions.
+ if (SelectAnyAttr *Attr = ND.getAttr<SelectAnyAttr>()) {
+ if (isa<FunctionDecl>(ND) || !ND.isExternallyVisible()) {
+ S.Diag(Attr->getLocation(), diag::err_attribute_selectany_non_extern_data);
+ ND.dropAttr<SelectAnyAttr>();
+ }
+ }
}
/// Given that we are within the definition of the given function,
@@ -4672,6 +4860,32 @@ static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) {
return isC99Inline;
}
+/// Determine whether a variable is extern "C" prior to attaching
+/// an initializer. We can't just call isExternC() here, because that
+/// will also compute and cache whether the declaration is externally
+/// visible, which might change when we attach the initializer.
+///
+/// This can only be used if the declaration is known to not be a
+/// redeclaration of an internal linkage declaration.
+///
+/// For instance:
+///
+/// auto x = []{};
+///
+/// Attaching the initializer here makes this declaration not externally
+/// visible, because its type has internal linkage.
+///
+/// FIXME: This is a hack.
+template<typename T>
+static bool isIncompleteDeclExternC(Sema &S, const T *D) {
+ if (S.getLangOpts().CPlusPlus) {
+ // In C++, the overloadable attribute negates the effects of extern "C".
+ if (!D->isInExternCContext() || D->template hasAttr<OverloadableAttr>())
+ return false;
+ }
+ return D->isExternC();
+}
+
static bool shouldConsiderLinkage(const VarDecl *VD) {
const DeclContext *DC = VD->getDeclContext()->getRedeclContext();
if (DC->isFunctionOrMethod())
@@ -4692,10 +4906,35 @@ static bool shouldConsiderLinkage(const FunctionDecl *FD) {
llvm_unreachable("Unexpected context");
}
-NamedDecl*
+/// Adjust the \c DeclContext for a function or variable that might be a
+/// function-local external declaration.
+bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) {
+ if (!DC->isFunctionOrMethod())
+ return false;
+
+ // If this is a local extern function or variable declared within a function
+ // template, don't add it into the enclosing namespace scope until it is
+ // instantiated; it might have a dependent type right now.
+ if (DC->isDependentContext())
+ return true;
+
+ // C++11 [basic.link]p7:
+ // When a block scope declaration of an entity with linkage is not found to
+ // refer to some other declaration, then that entity is a member of the
+ // innermost enclosing namespace.
+ //
+ // Per C++11 [namespace.def]p6, the innermost enclosing namespace is a
+ // semantically-enclosing namespace, not a lexically-enclosing one.
+ while (!DC->isFileContext() && !isa<LinkageSpecDecl>(DC))
+ DC = DC->getParent();
+ return true;
+}
+
+NamedDecl *
Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo, LookupResult &Previous,
- MultiTemplateParamsArg TemplateParamLists) {
+ MultiTemplateParamsArg TemplateParamLists,
+ bool &AddToScope) {
QualType R = TInfo->getType();
DeclarationName Name = GetNameForDeclarator(D).getName();
@@ -4703,6 +4942,10 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
VarDecl::StorageClass SC =
StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
+ DeclContext *OriginalDC = DC;
+ bool IsLocalExternDecl = SC == SC_Extern &&
+ adjustContextForLocalExternDecl(DC);
+
if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16) {
// OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
// half array type (unless the cl_khr_fp16 extension is enabled).
@@ -4720,15 +4963,16 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
SC = SC_None;
}
- // C++11 [dcl.stc]p4:
- // When thread_local is applied to a variable of block scope the
- // storage-class-specifier static is implied if it does not appear
- // explicitly.
- // Core issue: 'static' is not implied if the variable is declared 'extern'.
- if (SCSpec == DeclSpec::SCS_unspecified &&
- D.getDeclSpec().getThreadStorageClassSpec() ==
- DeclSpec::TSCS_thread_local && DC->isFunctionOrMethod())
- SC = SC_Static;
+ if (getLangOpts().CPlusPlus11 && SCSpec == DeclSpec::SCS_register &&
+ !D.getAsmLabel() && !getSourceManager().isInSystemMacro(
+ D.getDeclSpec().getStorageClassSpecLoc())) {
+ // In C++11, the 'register' storage class specifier is deprecated.
+ // Suppress the warning in system macros, it's used in macros in some
+ // popular C system headers, such as in glibc's htonl() macro.
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ diag::warn_deprecated_register)
+ << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+ }
IdentifierInfo *II = Name.getAsIdentifierInfo();
if (!II) {
@@ -4743,7 +4987,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// C99 6.9p2: The storage-class specifiers auto and register shall not
// appear in the declaration specifiers in an external declaration.
if (SC == SC_Auto || SC == SC_Register) {
-
// If this is a register variable with an asm label specified, then this
// is a GNU extension.
if (SC == SC_Register && D.getAsmLabel())
@@ -4753,7 +4996,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
D.setInvalidType();
}
}
-
+
if (getLangOpts().OpenCL) {
// Set up the special work-group-local storage class for variables in the
// OpenCL __local address space.
@@ -4786,8 +5029,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
- bool isExplicitSpecialization = false;
- VarDecl *NewVD;
+ bool IsExplicitSpecialization = false;
+ bool IsVariableTemplateSpecialization = false;
+ bool IsPartialSpecialization = false;
+ bool IsVariableTemplate = false;
+ VarTemplateDecl *PrevVarTemplate = 0;
+ VarDecl *NewVD = 0;
+ VarTemplateDecl *NewTemplate = 0;
if (!getLangOpts().CPlusPlus) {
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II,
@@ -4796,14 +5044,37 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (D.isInvalidType())
NewVD->setInvalidDecl();
} else {
+ bool Invalid = false;
+
if (DC->isRecord() && !CurContext->isRecord()) {
// This is an out-of-line definition of a static data member.
- if (SC == SC_Static) {
+ switch (SC) {
+ case SC_None:
+ break;
+ case SC_Static:
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_static_out_of_line)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+ break;
+ case SC_Auto:
+ case SC_Register:
+ case SC_Extern:
+ // [dcl.stc] p2: The auto or register specifiers shall be applied only
+ // to names of variables declared in a block or to function parameters.
+ // [dcl.stc] p6: The extern specifier cannot be used in the declaration
+ // of class members
+
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ diag::err_storage_class_for_static_member)
+ << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+ break;
+ case SC_PrivateExtern:
+ llvm_unreachable("C storage class in c++!");
+ case SC_OpenCLWorkGroupLocal:
+ llvm_unreachable("OpenCL storage class in c++!");
}
- }
+ }
+
if (SC == SC_Static && CurContext->isRecord()) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
if (RD->isLocalClass())
@@ -4826,28 +5097,21 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
+ NamedDecl *PrevDecl = 0;
+ if (Previous.begin() != Previous.end())
+ PrevDecl = (*Previous.begin())->getUnderlyingDecl();
+ PrevVarTemplate = dyn_cast_or_null<VarTemplateDecl>(PrevDecl);
+
// Match up the template parameter lists with the scope specifier, then
// determine whether we have a template or a template specialization.
- isExplicitSpecialization = false;
- bool Invalid = false;
- if (TemplateParameterList *TemplateParams
- = MatchTemplateParametersToScopeSpecifier(
- D.getDeclSpec().getLocStart(),
- D.getIdentifierLoc(),
- D.getCXXScopeSpec(),
- TemplateParamLists.data(),
- TemplateParamLists.size(),
- /*never a friend*/ false,
- isExplicitSpecialization,
- Invalid)) {
- if (TemplateParams->size() > 0) {
- // There is no such thing as a variable template.
- Diag(D.getIdentifierLoc(), diag::err_template_variable)
- << II
- << SourceRange(TemplateParams->getTemplateLoc(),
- TemplateParams->getRAngleLoc());
- return 0;
- } else {
+ TemplateParameterList *TemplateParams =
+ MatchTemplateParametersToScopeSpecifier(
+ D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
+ D.getCXXScopeSpec(), TemplateParamLists,
+ /*never a friend*/ false, IsExplicitSpecialization, Invalid);
+ if (TemplateParams) {
+ if (!TemplateParams->size() &&
+ D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
// There is an extraneous 'template<>' for this variable. Complain
// about it, but allow the declaration of the variable.
Diag(TemplateParams->getTemplateLoc(),
@@ -4855,24 +5119,148 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
<< II
<< SourceRange(TemplateParams->getTemplateLoc(),
TemplateParams->getRAngleLoc());
+ } else {
+ // Only C++1y supports variable templates (N3651).
+ Diag(D.getIdentifierLoc(),
+ getLangOpts().CPlusPlus1y
+ ? diag::warn_cxx11_compat_variable_template
+ : diag::ext_variable_template);
+
+ if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+ // This is an explicit specialization or a partial specialization.
+ // Check that we can declare a specialization here
+
+ IsVariableTemplateSpecialization = true;
+ IsPartialSpecialization = TemplateParams->size() > 0;
+
+ } else { // if (TemplateParams->size() > 0)
+ // This is a template declaration.
+ IsVariableTemplate = true;
+
+ // Check that we can declare a template here.
+ if (CheckTemplateDeclScope(S, TemplateParams))
+ return 0;
+
+ // If there is a previous declaration with the same name, check
+ // whether this is a valid redeclaration.
+ if (PrevDecl && !isDeclInScope(PrevDecl, DC, S))
+ PrevDecl = PrevVarTemplate = 0;
+
+ if (PrevVarTemplate) {
+ // Ensure that the template parameter lists are compatible.
+ if (!TemplateParameterListsAreEqual(
+ TemplateParams, PrevVarTemplate->getTemplateParameters(),
+ /*Complain=*/true, TPL_TemplateMatch))
+ return 0;
+ } else if (PrevDecl && PrevDecl->isTemplateParameter()) {
+ // Maybe we will complain about the shadowed template parameter.
+ DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+
+ // Just pretend that we didn't see the previous declaration.
+ PrevDecl = 0;
+ } else if (PrevDecl) {
+ // C++ [temp]p5:
+ // ... a template name declared in namespace scope or in class
+ // scope shall be unique in that scope.
+ Diag(D.getIdentifierLoc(), diag::err_redefinition_different_kind)
+ << Name;
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ return 0;
+ }
+
+ // Check the template parameter list of this declaration, possibly
+ // merging in the template parameter list from the previous variable
+ // template declaration.
+ if (CheckTemplateParameterList(
+ TemplateParams,
+ PrevVarTemplate ? PrevVarTemplate->getTemplateParameters()
+ : 0,
+ (D.getCXXScopeSpec().isSet() && DC && DC->isRecord() &&
+ DC->isDependentContext())
+ ? TPC_ClassTemplateMember
+ : TPC_VarTemplate))
+ Invalid = true;
+
+ if (D.getCXXScopeSpec().isSet()) {
+ // If the name of the template was qualified, we must be defining
+ // the template out-of-line.
+ if (!D.getCXXScopeSpec().isInvalid() && !Invalid &&
+ !PrevVarTemplate) {
+ Diag(D.getIdentifierLoc(), diag::err_member_decl_does_not_match)
+ << Name << DC << /*IsDefinition*/true
+ << D.getCXXScopeSpec().getRange();
+ Invalid = true;
+ }
+ }
+ }
}
+ } else if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+ TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+
+ // We have encountered something that the user meant to be a
+ // specialization (because it has explicitly-specified template
+ // arguments) but that was not introduced with a "template<>" (or had
+ // too few of them).
+ // FIXME: Differentiate between attempts for explicit instantiations
+ // (starting with "template") and the rest.
+ Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
+ << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
+ << FixItHint::CreateInsertion(D.getDeclSpec().getLocStart(),
+ "template<> ");
+ IsVariableTemplateSpecialization = true;
}
- NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
- D.getIdentifierLoc(), II,
- R, TInfo, SC);
+ if (IsVariableTemplateSpecialization) {
+ if (!PrevVarTemplate) {
+ Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template)
+ << IsPartialSpecialization;
+ return 0;
+ }
+
+ SourceLocation TemplateKWLoc =
+ TemplateParamLists.size() > 0
+ ? TemplateParamLists[0]->getTemplateLoc()
+ : SourceLocation();
+ DeclResult Res = ActOnVarTemplateSpecialization(
+ S, PrevVarTemplate, D, TInfo, TemplateKWLoc, TemplateParams, SC,
+ IsPartialSpecialization);
+ if (Res.isInvalid())
+ return 0;
+ NewVD = cast<VarDecl>(Res.get());
+ AddToScope = false;
+ } else
+ NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
+ D.getIdentifierLoc(), II, R, TInfo, SC);
+
+ // If this is supposed to be a variable template, create it as such.
+ if (IsVariableTemplate) {
+ NewTemplate =
+ VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name,
+ TemplateParams, NewVD, PrevVarTemplate);
+ NewVD->setDescribedVarTemplate(NewTemplate);
+ }
// 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.
if (D.getDeclSpec().containsPlaceholderType() && R->getContainedAutoType())
ParsingInitForAutoVars.insert(NewVD);
- if (D.isInvalidType() || Invalid)
+ if (D.isInvalidType() || Invalid) {
NewVD->setInvalidDecl();
+ if (NewTemplate)
+ NewTemplate->setInvalidDecl();
+ }
SetNestedNameSpecifier(NewVD, D);
- if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) {
+ // FIXME: Do we need D.getCXXScopeSpec().isSet()?
+ if (TemplateParams && TemplateParamLists.size() > 1 &&
+ (!IsVariableTemplateSpecialization || D.getCXXScopeSpec().isSet())) {
+ NewVD->setTemplateParameterListsInfo(
+ Context, TemplateParamLists.size() - 1, TemplateParamLists.data());
+ } else if (IsVariableTemplateSpecialization ||
+ (!TemplateParams && TemplateParamLists.size() > 0 &&
+ (D.getCXXScopeSpec().isSet()))) {
NewVD->setTemplateParameterListsInfo(Context,
TemplateParamLists.size(),
TemplateParamLists.data());
@@ -4885,13 +5273,29 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Set the lexical context. If the declarator has a C++ scope specifier, the
// lexical context will be different from the semantic context.
NewVD->setLexicalDeclContext(CurContext);
+ if (NewTemplate)
+ NewTemplate->setLexicalDeclContext(CurContext);
+
+ if (IsLocalExternDecl)
+ NewVD->setLocalExternDecl();
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) {
- if (NewVD->hasLocalStorage())
- Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
- diag::err_thread_non_global)
- << DeclSpec::getSpecifierName(TSCS);
- else if (!Context.getTargetInfo().isTLSSupported())
+ if (NewVD->hasLocalStorage()) {
+ // C++11 [dcl.stc]p4:
+ // When thread_local is applied to a variable of block scope the
+ // storage-class-specifier static is implied if it does not appear
+ // explicitly.
+ // Core issue: 'static' is not implied if the variable is declared
+ // 'extern'.
+ if (SCSpec == DeclSpec::SCS_unspecified &&
+ TSCS == DeclSpec::TSCS_thread_local &&
+ DC->isFunctionOrMethod())
+ NewVD->setTSCSpec(TSCS);
+ else
+ Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+ diag::err_thread_non_global)
+ << DeclSpec::getSpecifierName(TSCS);
+ } else if (!Context.getTargetInfo().isTLSSupported())
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_unsupported);
else
@@ -4918,7 +5322,12 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
if (D.getDeclSpec().isModulePrivateSpecified()) {
- if (isExplicitSpecialization)
+ if (IsVariableTemplateSpecialization)
+ Diag(NewVD->getLocation(), diag::err_module_private_specialization)
+ << (IsPartialSpecialization ? 1 : 0)
+ << FixItHint::CreateRemoval(
+ D.getDeclSpec().getModulePrivateSpecLoc());
+ else if (IsExplicitSpecialization)
Diag(NewVD->getLocation(), diag::err_module_private_specialization)
<< 2
<< FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
@@ -4927,8 +5336,11 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
<< 0 << NewVD->getDeclName()
<< SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
<< FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
- else
+ else {
NewVD->setModulePrivate();
+ if (NewTemplate)
+ NewTemplate->setModulePrivate();
+ }
}
// Handle attributes prior to checking for duplicates in MergeVarDecl
@@ -4993,9 +5405,18 @@ 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(Previous, DC, S, shouldConsiderLinkage(NewVD),
- isExplicitSpecialization);
-
+ FilterLookupForScope(
+ Previous, OriginalDC, S, shouldConsiderLinkage(NewVD),
+ IsExplicitSpecialization || IsVariableTemplateSpecialization);
+
+ // Check whether the previous declaration is in the same block scope. This
+ // affects whether we merge types with it, per C++11 [dcl.array]p3.
+ if (getLangOpts().CPlusPlus &&
+ NewVD->isLocalVarDecl() && NewVD->hasExternalStorage())
+ NewVD->setPreviousDeclInSameBlockScope(
+ Previous.isSingleResult() && !Previous.isShadowed() &&
+ isDeclInScope(Previous.getFoundDecl(), OriginalDC, S, false));
+
if (!getLangOpts().CPlusPlus) {
D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
} else {
@@ -5019,10 +5440,18 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD->setInvalidDecl();
}
- D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
+ if (!IsVariableTemplateSpecialization) {
+ if (PrevVarTemplate) {
+ LookupResult PrevDecl(*this, GetNameForDeclarator(D),
+ LookupOrdinaryName, ForRedeclaration);
+ PrevDecl.addDecl(PrevVarTemplate->getTemplatedDecl());
+ D.setRedeclaration(CheckVariableDeclaration(NewVD, PrevDecl));
+ } else
+ D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
+ }
// This is an explicit specialization of a static data member. Check it.
- if (isExplicitSpecialization && !NewVD->isInvalidDecl() &&
+ if (IsExplicitSpecialization && !NewVD->isInvalidDecl() &&
CheckMemberSpecialization(NewVD, Previous))
NewVD->setInvalidDecl();
}
@@ -5030,11 +5459,30 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
ProcessPragmaWeak(S, NewVD);
checkAttributesAfterMerging(*this, *NewVD);
- // If this is a locally-scoped extern C variable, update the map of
- // such variables.
- if (CurContext->isFunctionOrMethod() && NewVD->isExternC() &&
- !NewVD->isInvalidDecl())
- RegisterLocallyScopedExternCDecl(NewVD, Previous, S);
+ // If this is the first declaration of an extern C variable, update
+ // the map of such variables.
+ if (NewVD->isFirstDecl() && !NewVD->isInvalidDecl() &&
+ isIncompleteDeclExternC(*this, NewVD))
+ RegisterLocallyScopedExternCDecl(NewVD, S);
+
+ if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) {
+ Decl *ManglingContextDecl;
+ if (MangleNumberingContext *MCtx =
+ getCurrentMangleNumberContext(NewVD->getDeclContext(),
+ ManglingContextDecl)) {
+ Context.setManglingNumber(NewVD, MCtx->getManglingNumber(NewVD));
+ }
+ }
+
+ // If we are providing an explicit specialization of a static variable
+ // template, make a note of that.
+ if (PrevVarTemplate && PrevVarTemplate->getInstantiatedFromMemberTemplate())
+ PrevVarTemplate->setMemberSpecialization();
+
+ if (NewTemplate) {
+ ActOnDocumentableDecl(NewTemplate);
+ return NewTemplate;
+ }
return NewVD;
}
@@ -5134,30 +5582,121 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) {
CheckShadow(S, D, R);
}
+/// Check for conflict between this global or extern "C" declaration and
+/// previous global or extern "C" declarations. This is only used in C++.
template<typename T>
-static bool mayConflictWithNonVisibleExternC(const T *ND) {
- const DeclContext *DC = ND->getDeclContext();
- if (DC->getRedeclContext()->isTranslationUnit())
- return true;
+static bool checkGlobalOrExternCConflict(
+ Sema &S, const T *ND, bool IsGlobal, LookupResult &Previous) {
+ assert(S.getLangOpts().CPlusPlus && "only C++ has extern \"C\"");
+ NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName());
+
+ if (!Prev && IsGlobal && !isIncompleteDeclExternC(S, ND)) {
+ // The common case: this global doesn't conflict with any extern "C"
+ // declaration.
+ return false;
+ }
- // We know that is the first decl we see, other than function local
- // extern C ones. If this is C++ and the decl is not in a extern C context
- // it cannot have C language linkage. Avoid calling isExternC in that case.
- // We need to this because of code like
- //
- // namespace { struct bar {}; }
- // auto foo = bar();
- //
- // This code runs before the init of foo is set, and therefore before
- // the type of foo is known. Not knowing the type we cannot know its linkage
- // unless it is in an extern C block.
- if (!ND->isInExternCContext()) {
- const ASTContext &Context = ND->getASTContext();
- if (Context.getLangOpts().CPlusPlus)
+ if (Prev) {
+ if (!IsGlobal || isIncompleteDeclExternC(S, ND)) {
+ // Both the old and new declarations have C language linkage. This is a
+ // redeclaration.
+ Previous.clear();
+ Previous.addDecl(Prev);
+ return true;
+ }
+
+ // This is a global, non-extern "C" declaration, and there is a previous
+ // non-global extern "C" declaration. Diagnose if this is a variable
+ // declaration.
+ if (!isa<VarDecl>(ND))
return false;
+ } else {
+ // The declaration is extern "C". Check for any declaration in the
+ // translation unit which might conflict.
+ if (IsGlobal) {
+ // We have already performed the lookup into the translation unit.
+ IsGlobal = false;
+ for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+ I != E; ++I) {
+ if (isa<VarDecl>(*I)) {
+ Prev = *I;
+ break;
+ }
+ }
+ } else {
+ DeclContext::lookup_result R =
+ S.Context.getTranslationUnitDecl()->lookup(ND->getDeclName());
+ for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end();
+ I != E; ++I) {
+ if (isa<VarDecl>(*I)) {
+ Prev = *I;
+ break;
+ }
+ // FIXME: If we have any other entity with this name in global scope,
+ // the declaration is ill-formed, but that is a defect: it breaks the
+ // 'stat' hack, for instance. Only variables can have mangled name
+ // clashes with extern "C" declarations, so only they deserve a
+ // diagnostic.
+ }
+ }
+
+ if (!Prev)
+ return false;
+ }
+
+ // Use the first declaration's location to ensure we point at something which
+ // is lexically inside an extern "C" linkage-spec.
+ assert(Prev && "should have found a previous declaration to diagnose");
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Prev))
+ Prev = FD->getFirstDecl();
+ else
+ Prev = cast<VarDecl>(Prev)->getFirstDecl();
+
+ S.Diag(ND->getLocation(), diag::err_extern_c_global_conflict)
+ << IsGlobal << ND;
+ S.Diag(Prev->getLocation(), diag::note_extern_c_global_conflict)
+ << IsGlobal;
+ return false;
+}
+
+/// Apply special rules for handling extern "C" declarations. Returns \c true
+/// if we have found that this is a redeclaration of some prior entity.
+///
+/// Per C++ [dcl.link]p6:
+/// Two declarations [for a function or variable] with C language linkage
+/// with the same name that appear in different scopes refer to the same
+/// [entity]. An entity with C language linkage shall not be declared with
+/// the same name as an entity in global scope.
+template<typename T>
+static bool checkForConflictWithNonVisibleExternC(Sema &S, const T *ND,
+ LookupResult &Previous) {
+ if (!S.getLangOpts().CPlusPlus) {
+ // In C, when declaring a global variable, look for a corresponding 'extern'
+ // variable declared in function scope. We don't need this in C++, because
+ // we find local extern decls in the surrounding file-scope DeclContext.
+ if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
+ if (NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName())) {
+ Previous.clear();
+ Previous.addDecl(Prev);
+ return true;
+ }
+ }
+ return false;
}
- return ND->isExternC();
+ // A declaration in the translation unit can conflict with an extern "C"
+ // declaration.
+ if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit())
+ return checkGlobalOrExternCConflict(S, ND, /*IsGlobal*/true, Previous);
+
+ // An extern "C" declaration can conflict with a declaration in the
+ // translation unit or can be a redeclaration of an extern "C" declaration
+ // in another scope.
+ if (isIncompleteDeclExternC(S,ND))
+ return checkGlobalOrExternCConflict(S, ND, /*IsGlobal*/false, Previous);
+
+ // Neither global nor extern "C": nothing to do.
+ return false;
}
void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
@@ -5239,7 +5778,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
if (NewVD->isFileVarDecl())
Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope)
<< SizeRange;
- else if (NewVD->getStorageClass() == SC_Static)
+ else if (NewVD->isStaticLocal())
Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage)
<< SizeRange;
else
@@ -5263,11 +5802,15 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
NewVD->setTypeSourceInfo(FixedTInfo);
}
- if (T->isVoidType() && NewVD->isThisDeclarationADefinition()) {
- Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
- << T;
- NewVD->setInvalidDecl();
- return;
+ if (T->isVoidType()) {
+ // C++98 [dcl.stc]p5: The extern specifier can be applied only to the names
+ // of objects and functions.
+ if (NewVD->isThisDeclarationADefinition() || getLangOpts().CPlusPlus) {
+ Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
+ << T;
+ NewVD->setInvalidDecl();
+ return;
+ }
}
if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) {
@@ -5303,8 +5846,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
/// Sets NewVD->isInvalidDecl() if an error was encountered.
///
/// Returns true if the variable declaration is a redeclaration.
-bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
- LookupResult &Previous) {
+bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) {
CheckVariableDeclarationType(NewVD);
// If the decl is already known invalid, don't check it.
@@ -5313,44 +5855,15 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
// If we did not find anything by this name, look for a non-visible
// extern "C" declaration with the same name.
- //
- // Clang has a lot of problems with extern local declarations.
- // The actual standards text here is:
- //
- // C++11 [basic.link]p6:
- // The name of a function declared in block scope and the name
- // of a variable declared by a block scope extern declaration
- // have linkage. If there is a visible declaration of an entity
- // with linkage having the same name and type, ignoring entities
- // declared outside the innermost enclosing namespace scope, the
- // block scope declaration declares that same entity and
- // receives the linkage of the previous declaration.
- //
- // C11 6.2.7p4:
- // For an identifier with internal or external linkage declared
- // in a scope in which a prior declaration of that identifier is
- // visible, if the prior declaration specifies internal or
- // external linkage, the type of the identifier at the later
- // declaration becomes the composite type.
- //
- // The most important point here is that we're not allowed to
- // update our understanding of the type according to declarations
- // not in scope.
- bool PreviousWasHidden = false;
- if (Previous.empty() && mayConflictWithNonVisibleExternC(NewVD)) {
- llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
- = findLocallyScopedExternCDecl(NewVD->getDeclName());
- if (Pos != LocallyScopedExternCDecls.end()) {
- Previous.addDecl(Pos->second);
- PreviousWasHidden = true;
- }
- }
+ if (Previous.empty() &&
+ checkForConflictWithNonVisibleExternC(*this, NewVD, Previous))
+ Previous.setShadowed();
// Filter out any non-conflicting previous declarations.
filterNonConflictingPreviousDecls(Context, NewVD, Previous);
if (!Previous.empty()) {
- MergeVarDecl(NewVD, Previous, PreviousWasHidden);
+ MergeVarDecl(NewVD, Previous);
return true;
}
return false;
@@ -5524,24 +6037,27 @@ class DifferentNameValidatorCCC : public CorrectionCandidateCallback {
///
/// Returns a NamedDecl iff typo correction was performed and substituting in
/// the new declaration name does not cause new errors.
-static NamedDecl* DiagnoseInvalidRedeclaration(
+static NamedDecl *DiagnoseInvalidRedeclaration(
Sema &SemaRef, LookupResult &Previous, FunctionDecl *NewFD,
- ActOnFDArgs &ExtraArgs) {
- NamedDecl *Result = NULL;
+ ActOnFDArgs &ExtraArgs, bool IsLocalFriend, Scope *S) {
DeclarationName Name = NewFD->getDeclName();
DeclContext *NewDC = NewFD->getDeclContext();
- LookupResult Prev(SemaRef, Name, NewFD->getLocation(),
- Sema::LookupOrdinaryName, Sema::ForRedeclaration);
SmallVector<unsigned, 1> MismatchedParams;
SmallVector<std::pair<FunctionDecl *, unsigned>, 1> NearMatches;
TypoCorrection Correction;
- bool isFriendDecl = (SemaRef.getLangOpts().CPlusPlus &&
- ExtraArgs.D.getDeclSpec().isFriendSpecified());
- unsigned DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend
- : diag::err_member_def_does_not_match;
+ bool IsDefinition = ExtraArgs.D.isFunctionDefinition();
+ unsigned DiagMsg = IsLocalFriend ? diag::err_no_matching_local_friend
+ : diag::err_member_decl_does_not_match;
+ LookupResult Prev(SemaRef, Name, NewFD->getLocation(),
+ IsLocalFriend ? Sema::LookupLocalFriendName
+ : Sema::LookupOrdinaryName,
+ Sema::ForRedeclaration);
NewFD->setInvalidDecl();
- SemaRef.LookupQualifiedName(Prev, NewDC);
+ if (IsLocalFriend)
+ SemaRef.LookupName(Prev, S);
+ else
+ SemaRef.LookupQualifiedName(Prev, NewDC);
assert(!Prev.isAmbiguous() &&
"Cannot have an ambiguity in previous-declaration lookup");
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
@@ -5561,12 +6077,10 @@ static NamedDecl* DiagnoseInvalidRedeclaration(
}
}
// If the qualified name lookup yielded nothing, try typo correction
- } else if ((Correction = SemaRef.CorrectTypo(Prev.getLookupNameInfo(),
- Prev.getLookupKind(), 0, 0,
- Validator, NewDC))) {
- // Trap errors.
- Sema::SFINAETrap Trap(SemaRef);
-
+ } else if ((Correction = SemaRef.CorrectTypo(
+ Prev.getLookupNameInfo(), Prev.getLookupKind(), S,
+ &ExtraArgs.D.getCXXScopeSpec(), Validator,
+ IsLocalFriend ? 0 : NewDC))) {
// Set up everything for the call to ActOnFunctionDeclarator
ExtraArgs.D.SetIdentifier(Correction.getCorrectionAsIdentifierInfo(),
ExtraArgs.D.getIdentifierLoc());
@@ -5582,85 +6096,85 @@ static NamedDecl* DiagnoseInvalidRedeclaration(
}
}
bool wasRedeclaration = ExtraArgs.D.isRedeclaration();
- // TODO: Refactor ActOnFunctionDeclarator so that we can call only the
- // pieces need to verify the typo-corrected C++ declaraction and hopefully
- // eliminate the need for the parameter pack ExtraArgs.
- Result = SemaRef.ActOnFunctionDeclarator(
- ExtraArgs.S, ExtraArgs.D,
- Correction.getCorrectionDecl()->getDeclContext(),
- NewFD->getTypeSourceInfo(), Previous, ExtraArgs.TemplateParamLists,
- ExtraArgs.AddToScope);
- if (Trap.hasErrorOccurred()) {
- // Pretend the typo correction never occurred
- ExtraArgs.D.SetIdentifier(Name.getAsIdentifierInfo(),
- ExtraArgs.D.getIdentifierLoc());
- ExtraArgs.D.setRedeclaration(wasRedeclaration);
- Previous.clear();
- Previous.setLookupName(Name);
- Result = NULL;
- } else {
- for (LookupResult::iterator Func = Previous.begin(),
- FuncEnd = Previous.end();
- Func != FuncEnd; ++Func) {
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func))
- NearMatches.push_back(std::make_pair(FD, 0));
- }
+
+ NamedDecl *Result;
+ // Retry building the function declaration with the new previous
+ // declarations, and with errors suppressed.
+ {
+ // Trap errors.
+ Sema::SFINAETrap Trap(SemaRef);
+
+ // TODO: Refactor ActOnFunctionDeclarator so that we can call only the
+ // pieces need to verify the typo-corrected C++ declaration and hopefully
+ // eliminate the need for the parameter pack ExtraArgs.
+ Result = SemaRef.ActOnFunctionDeclarator(
+ ExtraArgs.S, ExtraArgs.D,
+ Correction.getCorrectionDecl()->getDeclContext(),
+ NewFD->getTypeSourceInfo(), Previous, ExtraArgs.TemplateParamLists,
+ ExtraArgs.AddToScope);
+
+ if (Trap.hasErrorOccurred())
+ Result = 0;
+ }
+
+ if (Result) {
+ // Determine which correction we picked.
+ Decl *Canonical = Result->getCanonicalDecl();
+ for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+ I != E; ++I)
+ if ((*I)->getCanonicalDecl() == Canonical)
+ Correction.setCorrectionDecl(*I);
+
+ SemaRef.diagnoseTypo(
+ Correction,
+ SemaRef.PDiag(IsLocalFriend
+ ? diag::err_no_matching_local_friend_suggest
+ : diag::err_member_decl_does_not_match_suggest)
+ << Name << NewDC << IsDefinition);
+ return Result;
}
- if (NearMatches.empty()) {
- // Ignore the correction if it didn't yield any close FunctionDecl matches
- Correction = TypoCorrection();
- } else {
- DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend_suggest
- : diag::err_member_def_does_not_match_suggest;
- }
- }
-
- if (Correction) {
- // FIXME: use Correction.getCorrectionRange() instead of computing the range
- // here. This requires passing in the CXXScopeSpec to CorrectTypo which in
- // turn causes the correction to fully qualify the name. If we fix
- // CorrectTypo to minimally qualify then this change should be good.
- SourceRange FixItLoc(NewFD->getLocation());
- CXXScopeSpec &SS = ExtraArgs.D.getCXXScopeSpec();
- if (Correction.getCorrectionSpecifier() && SS.isValid())
- FixItLoc.setBegin(SS.getBeginLoc());
- SemaRef.Diag(NewFD->getLocStart(), DiagMsg)
- << Name << NewDC << Correction.getQuoted(SemaRef.getLangOpts())
- << FixItHint::CreateReplacement(
- FixItLoc, Correction.getAsString(SemaRef.getLangOpts()));
- } else {
- SemaRef.Diag(NewFD->getLocation(), DiagMsg)
- << Name << NewDC << NewFD->getLocation();
+
+ // Pretend the typo correction never occurred
+ ExtraArgs.D.SetIdentifier(Name.getAsIdentifierInfo(),
+ ExtraArgs.D.getIdentifierLoc());
+ ExtraArgs.D.setRedeclaration(wasRedeclaration);
+ Previous.clear();
+ Previous.setLookupName(Name);
}
+ SemaRef.Diag(NewFD->getLocation(), DiagMsg)
+ << Name << NewDC << IsDefinition << NewFD->getLocation();
+
bool NewFDisConst = false;
if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD))
NewFDisConst = NewMD->isConst();
- for (SmallVector<std::pair<FunctionDecl *, unsigned>, 1>::iterator
+ for (SmallVectorImpl<std::pair<FunctionDecl *, unsigned> >::iterator
NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end();
NearMatch != NearMatchEnd; ++NearMatch) {
FunctionDecl *FD = NearMatch->first;
- bool FDisConst = false;
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
- FDisConst = MD->isConst();
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
+ bool FDisConst = MD && MD->isConst();
+ bool IsMember = MD || !IsLocalFriend;
+ // FIXME: These notes are poorly worded for the local friend case.
if (unsigned Idx = NearMatch->second) {
ParmVarDecl *FDParam = FD->getParamDecl(Idx-1);
SourceLocation Loc = FDParam->getTypeSpecStartLoc();
if (Loc.isInvalid()) Loc = FD->getLocation();
- SemaRef.Diag(Loc, diag::note_member_def_close_param_match)
- << Idx << FDParam->getType() << NewFD->getParamDecl(Idx-1)->getType();
- } else if (Correction) {
- SemaRef.Diag(FD->getLocation(), diag::note_previous_decl)
- << Correction.getQuoted(SemaRef.getLangOpts());
+ SemaRef.Diag(Loc, IsMember ? diag::note_member_def_close_param_match
+ : diag::note_local_decl_close_param_match)
+ << Idx << FDParam->getType()
+ << NewFD->getParamDecl(Idx - 1)->getType();
} else if (FDisConst != NewFDisConst) {
SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match)
<< NewFDisConst << FD->getSourceRange().getEnd();
} else
- SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_match);
+ SemaRef.Diag(FD->getLocation(),
+ IsMember ? diag::note_member_def_close_match
+ : diag::note_local_decl_close_match);
}
- return Result;
+ return 0;
}
static FunctionDecl::StorageClass getFunctionStorageClass(Sema &SemaRef,
@@ -5778,6 +6292,15 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
SemaRef.AdjustDestructorExceptionSpec(Record, NewDD);
}
+ // The Microsoft ABI requires that we perform the destructor body
+ // checks (i.e. operator delete() lookup) at every declaration, as
+ // any translation unit may need to emit a deleting destructor.
+ if (SemaRef.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ !Record->isDependentType() && Record->getDefinition() &&
+ !Record->isBeingDefined()) {
+ SemaRef.CheckDestructor(NewDD);
+ }
+
IsVirtualOkay = true;
return NewDD;
@@ -5856,6 +6379,173 @@ void Sema::checkVoidParamDecl(ParmVarDecl *Param) {
}
}
+enum OpenCLParamType {
+ ValidKernelParam,
+ PtrPtrKernelParam,
+ PtrKernelParam,
+ InvalidKernelParam,
+ RecordKernelParam
+};
+
+static OpenCLParamType getOpenCLKernelParameterType(QualType PT) {
+ if (PT->isPointerType()) {
+ QualType PointeeType = PT->getPointeeType();
+ return PointeeType->isPointerType() ? PtrPtrKernelParam : PtrKernelParam;
+ }
+
+ // TODO: Forbid the other integer types (size_t, ptrdiff_t...) when they can
+ // be used as builtin types.
+
+ if (PT->isImageType())
+ return PtrKernelParam;
+
+ if (PT->isBooleanType())
+ return InvalidKernelParam;
+
+ if (PT->isEventT())
+ return InvalidKernelParam;
+
+ if (PT->isHalfType())
+ return InvalidKernelParam;
+
+ if (PT->isRecordType())
+ return RecordKernelParam;
+
+ return ValidKernelParam;
+}
+
+static void checkIsValidOpenCLKernelParameter(
+ Sema &S,
+ Declarator &D,
+ ParmVarDecl *Param,
+ llvm::SmallPtrSet<const Type *, 16> &ValidTypes) {
+ QualType PT = Param->getType();
+
+ // Cache the valid types we encounter to avoid rechecking structs that are
+ // used again
+ if (ValidTypes.count(PT.getTypePtr()))
+ return;
+
+ switch (getOpenCLKernelParameterType(PT)) {
+ case PtrPtrKernelParam:
+ // OpenCL v1.2 s6.9.a:
+ // A kernel function argument cannot be declared as a
+ // pointer to a pointer type.
+ S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param);
+ D.setInvalidType();
+ return;
+
+ // OpenCL v1.2 s6.9.k:
+ // Arguments to kernel functions in a program cannot be declared with the
+ // built-in scalar types bool, half, size_t, ptrdiff_t, intptr_t, and
+ // uintptr_t or a struct and/or union that contain fields declared to be
+ // one of these built-in scalar types.
+
+ case InvalidKernelParam:
+ // OpenCL v1.2 s6.8 n:
+ // A kernel function argument cannot be declared
+ // of event_t type.
+ S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT;
+ D.setInvalidType();
+ return;
+
+ case PtrKernelParam:
+ case ValidKernelParam:
+ ValidTypes.insert(PT.getTypePtr());
+ return;
+
+ case RecordKernelParam:
+ break;
+ }
+
+ // Track nested structs we will inspect
+ SmallVector<const Decl *, 4> VisitStack;
+
+ // Track where we are in the nested structs. Items will migrate from
+ // VisitStack to HistoryStack as we do the DFS for bad field.
+ SmallVector<const FieldDecl *, 4> HistoryStack;
+ HistoryStack.push_back((const FieldDecl *) 0);
+
+ const RecordDecl *PD = PT->castAs<RecordType>()->getDecl();
+ VisitStack.push_back(PD);
+
+ assert(VisitStack.back() && "First decl null?");
+
+ do {
+ const Decl *Next = VisitStack.pop_back_val();
+ if (!Next) {
+ assert(!HistoryStack.empty());
+ // Found a marker, we have gone up a level
+ if (const FieldDecl *Hist = HistoryStack.pop_back_val())
+ ValidTypes.insert(Hist->getType().getTypePtr());
+
+ continue;
+ }
+
+ // Adds everything except the original parameter declaration (which is not a
+ // field itself) to the history stack.
+ const RecordDecl *RD;
+ if (const FieldDecl *Field = dyn_cast<FieldDecl>(Next)) {
+ HistoryStack.push_back(Field);
+ RD = Field->getType()->castAs<RecordType>()->getDecl();
+ } else {
+ RD = cast<RecordDecl>(Next);
+ }
+
+ // Add a null marker so we know when we've gone back up a level
+ VisitStack.push_back((const Decl *) 0);
+
+ for (RecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end(); I != E; ++I) {
+ const FieldDecl *FD = *I;
+ QualType QT = FD->getType();
+
+ if (ValidTypes.count(QT.getTypePtr()))
+ continue;
+
+ OpenCLParamType ParamType = getOpenCLKernelParameterType(QT);
+ if (ParamType == ValidKernelParam)
+ continue;
+
+ if (ParamType == RecordKernelParam) {
+ VisitStack.push_back(FD);
+ continue;
+ }
+
+ // OpenCL v1.2 s6.9.p:
+ // Arguments to kernel functions that are declared to be a struct or union
+ // do not allow OpenCL objects to be passed as elements of the struct or
+ // union.
+ if (ParamType == PtrKernelParam || ParamType == PtrPtrKernelParam) {
+ S.Diag(Param->getLocation(),
+ diag::err_record_with_pointers_kernel_param)
+ << PT->isUnionType()
+ << PT;
+ } else {
+ S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT;
+ }
+
+ S.Diag(PD->getLocation(), diag::note_within_field_of_type)
+ << PD->getDeclName();
+
+ // We have an error, now let's go back up through history and show where
+ // the offending field came from
+ for (ArrayRef<const FieldDecl *>::const_iterator I = HistoryStack.begin() + 1,
+ E = HistoryStack.end(); I != E; ++I) {
+ const FieldDecl *OuterField = *I;
+ S.Diag(OuterField->getLocation(), diag::note_within_field_of_type)
+ << OuterField->getType();
+ }
+
+ S.Diag(FD->getLocation(), diag::note_illegal_field_declared_here)
+ << QT->isPointerType()
+ << QT;
+ D.setInvalidType();
+ return;
+ }
+ } while (!VisitStack.empty());
+}
+
NamedDecl*
Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo, LookupResult &Previous,
@@ -5875,25 +6565,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
diag::err_invalid_thread)
<< DeclSpec::getSpecifierName(TSCS);
- // Do not allow returning a objc interface by-value.
- if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) {
- Diag(D.getIdentifierLoc(),
- diag::err_object_cannot_be_passed_returned_by_value) << 0
- << R->getAs<FunctionType>()->getResultType()
- << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*");
-
- QualType T = R->getAs<FunctionType>()->getResultType();
- T = Context.getObjCObjectPointerType(T);
- if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(R)) {
- FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- R = Context.getFunctionType(T,
- ArrayRef<QualType>(FPT->arg_type_begin(),
- FPT->getNumArgs()),
- EPI);
- }
- else if (isa<FunctionNoProtoType>(R))
- R = Context.getFunctionNoProtoType(T);
- }
+ if (D.isFirstDeclarationOfMember())
+ adjustMemberFunctionCC(R, D.isStaticMember());
bool isFriend = false;
FunctionTemplateDecl *FunctionTemplate = 0;
@@ -5906,6 +6579,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
bool isVirtualOkay = false;
+ DeclContext *OriginalDC = DC;
+ bool IsLocalExternDecl = adjustContextForLocalExternDecl(DC);
+
FunctionDecl *NewFD = CreateNewFunctionDecl(*this, D, DC, R, TInfo, SC,
isVirtualOkay);
if (!NewFD) return 0;
@@ -5913,6 +6589,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer())
NewFD->setTopLevelDeclInObjCContainer();
+ // Set the lexical context. If this is a function-scope declaration, or has a
+ // C++ scope specifier, or is the object of a friend declaration, the lexical
+ // context will be different from the semantic context.
+ NewFD->setLexicalDeclContext(CurContext);
+
+ if (IsLocalExternDecl)
+ NewFD->setLocalExternDecl();
+
if (getLangOpts().CPlusPlus) {
bool isInline = D.getDeclSpec().isInlineSpecified();
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
@@ -5940,25 +6624,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
isFunctionTemplateSpecialization = false;
if (D.isInvalidType())
NewFD->setInvalidDecl();
-
- // Set the lexical context. If the declarator has a C++
- // scope specifier, or is the object of a friend declaration, the
- // lexical context will be different from the semantic context.
- NewFD->setLexicalDeclContext(CurContext);
-
+
// Match up the template parameter lists with the scope specifier, then
// determine whether we have a template or a template specialization.
bool Invalid = false;
- if (TemplateParameterList *TemplateParams
- = MatchTemplateParametersToScopeSpecifier(
- D.getDeclSpec().getLocStart(),
- D.getIdentifierLoc(),
- D.getCXXScopeSpec(),
- TemplateParamLists.data(),
- TemplateParamLists.size(),
- isFriend,
- isExplicitSpecialization,
- Invalid)) {
+ if (TemplateParameterList *TemplateParams =
+ MatchTemplateParametersToScopeSpecifier(
+ D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
+ D.getCXXScopeSpec(), TemplateParamLists, isFriend,
+ isExplicitSpecialization, Invalid)) {
if (TemplateParams->size() > 0) {
// This is a function template
@@ -6072,6 +6746,24 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual);
}
+ if (getLangOpts().CPlusPlus1y &&
+ (NewFD->isDependentContext() ||
+ (isFriend && CurContext->isDependentContext())) &&
+ NewFD->getResultType()->isUndeducedType()) {
+ // If the function template is referenced directly (for instance, as a
+ // member of the current instantiation), pretend it has a dependent type.
+ // This is not really justified by the standard, but is the only sane
+ // thing to do.
+ // FIXME: For a friend function, we have not marked the function as being
+ // a friend yet, so 'isDependentContext' on the FD doesn't work.
+ const FunctionProtoType *FPT =
+ NewFD->getType()->castAs<FunctionProtoType>();
+ QualType Result = SubstAutoType(FPT->getResultType(),
+ Context.DependentTy);
+ NewFD->setType(Context.getFunctionType(Result, FPT->getArgTypes(),
+ FPT->getExtProtoInfo()));
+ }
+
// C++ [dcl.fct.spec]p3:
// The inline specifier shall not appear on a block scope function
// declaration.
@@ -6132,12 +6824,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
if (isFriend) {
- // For now, claim that the objects have no previous declaration.
if (FunctionTemplate) {
- FunctionTemplate->setObjectOfFriendDecl(false);
+ FunctionTemplate->setObjectOfFriendDecl();
FunctionTemplate->setAccess(AS_public);
}
- NewFD->setObjectOfFriendDecl(false);
+ NewFD->setObjectOfFriendDecl();
NewFD->setAccess(AS_public);
}
@@ -6188,17 +6879,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.ExceptionSpecType = EST_BasicNoexcept;
NewFD->setType(Context.getFunctionType(FPT->getResultType(),
- ArrayRef<QualType>(FPT->arg_type_begin(),
- FPT->getNumArgs()),
- EPI));
+ FPT->getArgTypes(), EPI));
}
}
// Filter out previous declarations that don't match the scope.
- FilterLookupForScope(Previous, DC, S, shouldConsiderLinkage(NewFD),
+ FilterLookupForScope(Previous, OriginalDC, S, shouldConsiderLinkage(NewFD),
isExplicitSpecialization ||
isFunctionTemplateSpecialization);
-
+
// Handle GNU asm-label extension (encoded as an attribute).
if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string.
@@ -6282,10 +6971,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(),
Context));
- // Process the non-inheritable attributes on this declaration.
- ProcessDeclAttributes(S, NewFD, D,
- /*NonInheritable=*/true, /*Inheritable=*/false);
-
// Functions returning a variably modified type violate C99 6.7.5.2p2
// because all functions have linkage.
if (!NewFD->isInvalidDecl() &&
@@ -6295,8 +6980,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
// Handle attributes.
- ProcessDeclAttributes(S, NewFD, D,
- /*NonInheritable=*/false, /*Inheritable=*/true);
+ ProcessDeclAttributes(S, NewFD, D);
QualType RetType = NewFD->getResultType();
const CXXRecordDecl *Ret = RetType->isRecordType() ?
@@ -6304,7 +6988,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (!NewFD->isInvalidDecl() && !NewFD->hasAttr<WarnUnusedResultAttr>() &&
Ret && Ret->hasAttr<WarnUnusedResultAttr>()) {
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
- if (!(MD && MD->getCorrespondingMethodInClass(Ret, true))) {
+ // Attach the attribute to the new decl. Don't apply the attribute if it
+ // returns an instance of the class (e.g. assignment operators).
+ if (!MD || MD->getParent() != Ret) {
NewFD->addAttr(new (Context) WarnUnusedResultAttr(SourceRange(),
Context));
}
@@ -6313,19 +6999,36 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (!getLangOpts().CPlusPlus) {
// Perform semantic checking on the function declaration.
bool isExplicitSpecialization=false;
- if (!NewFD->isInvalidDecl()) {
- if (NewFD->isMain())
- CheckMain(NewFD, D.getDeclSpec());
+ if (!NewFD->isInvalidDecl() && NewFD->isMain())
+ CheckMain(NewFD, D.getDeclSpec());
+
+ if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint())
+ CheckMSVCRTEntryPoint(NewFD);
+
+ if (!NewFD->isInvalidDecl())
D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
isExplicitSpecialization));
- }
- // Make graceful recovery from an invalid redeclaration.
else if (!Previous.empty())
- D.setRedeclaration(true);
+ // Make graceful recovery from an invalid redeclaration.
+ D.setRedeclaration(true);
assert((NewFD->isInvalidDecl() || !D.isRedeclaration() ||
Previous.getResultKind() != LookupResult::FoundOverloaded) &&
"previous declaration set still overloaded");
} else {
+ // C++11 [replacement.functions]p3:
+ // The program's definitions shall not be specified as inline.
+ //
+ // N.B. We diagnose declarations instead of definitions per LWG issue 2340.
+ //
+ // Suppress the diagnostic if the function is __attribute__((used)), since
+ // that forces an external definition to be emitted.
+ if (D.getDeclSpec().isInlineSpecified() &&
+ NewFD->isReplaceableGlobalAllocationFunction() &&
+ !NewFD->hasAttr<UsedAttr>())
+ Diag(D.getDeclSpec().getInlineSpecLoc(),
+ diag::ext_operator_new_delete_declared_inline)
+ << NewFD->getDeclName();
+
// If the declarator is a template-id, translate the parser's template
// argument list into our AST format.
if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
@@ -6353,6 +7056,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// specialization (because it has explicitly-specified template
// arguments) but that was not introduced with a "template<>" (or had
// too few of them).
+ // FIXME: Differentiate between attempts for explicit instantiations
+ // (starting with "template") and the rest.
Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
<< FixItHint::CreateInsertion(
@@ -6406,8 +7111,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// C++ [dcl.stc]p1:
// A storage-class-specifier shall not be specified in an explicit
// specialization (14.7.3)
- if (SC != SC_None) {
- if (SC != NewFD->getTemplateSpecializationInfo()->getTemplate()->getTemplatedDecl()->getStorageClass())
+ FunctionTemplateSpecializationInfo *Info =
+ NewFD->getTemplateSpecializationInfo();
+ if (Info && SC != SC_None) {
+ if (SC != Info->getTemplate()->getTemplatedDecl()->getStorageClass())
Diag(NewFD->getLocation(),
diag::err_explicit_specialization_inconsistent_storage_class)
<< SC
@@ -6428,17 +7135,20 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Perform semantic checking on the function declaration.
if (!isDependentClassScopeExplicitSpecialization) {
+ if (!NewFD->isInvalidDecl() && NewFD->isMain())
+ CheckMain(NewFD, D.getDeclSpec());
+
+ if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint())
+ CheckMSVCRTEntryPoint(NewFD);
+
if (NewFD->isInvalidDecl()) {
// If this is a class member, mark the class invalid immediately.
// This avoids some consistency errors later.
if (CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(NewFD))
methodDecl->getParent()->setInvalidDecl();
- } else {
- if (NewFD->isMain())
- CheckMain(NewFD, D.getDeclSpec());
+ } else
D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
isExplicitSpecialization));
- }
}
assert((NewFD->isInvalidDecl() || !D.isRedeclaration() ||
@@ -6456,8 +7166,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD->setAccess(Access);
if (FunctionTemplate) FunctionTemplate->setAccess(Access);
-
- PrincipalDecl->setObjectOfFriendDecl(true);
}
if (NewFD->isOverloadedOperator() && !DC->isRecord() &&
@@ -6523,9 +7231,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// matches (e.g., those that differ only in cv-qualifiers and
// whether the parameter types are references).
- if (NamedDecl *Result = DiagnoseInvalidRedeclaration(*this, Previous,
- NewFD,
- ExtraArgs)) {
+ if (NamedDecl *Result = DiagnoseInvalidRedeclaration(
+ *this, Previous, NewFD, ExtraArgs, false, 0)) {
AddToScope = ExtraArgs.AddToScope;
return Result;
}
@@ -6534,9 +7241,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Unqualified local friend declarations are required to resolve
// to something.
} else if (isFriend && cast<CXXRecordDecl>(CurContext)->isLocalClass()) {
- if (NamedDecl *Result = DiagnoseInvalidRedeclaration(*this, Previous,
- NewFD,
- ExtraArgs)) {
+ if (NamedDecl *Result = DiagnoseInvalidRedeclaration(
+ *this, Previous, NewFD, ExtraArgs, true, S)) {
AddToScope = ExtraArgs.AddToScope;
return Result;
}
@@ -6570,7 +7276,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Turn this into a variadic function with no parameters.
const FunctionType *FT = NewFD->getType()->getAs<FunctionType>();
- FunctionProtoType::ExtProtoInfo EPI;
+ FunctionProtoType::ExtProtoInfo EPI(
+ Context.getDefaultCallingConvention(true, false));
EPI.Variadic = true;
EPI.ExtInfo = FT->getExtInfo();
@@ -6580,18 +7287,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// If there's a #pragma GCC visibility in scope, and this isn't a class
// member, set the visibility of this function.
- if (!DC->isRecord() && NewFD->hasExternalLinkage())
+ if (!DC->isRecord() && NewFD->isExternallyVisible())
AddPushedVisibilityAttribute(NewFD);
// If there's a #pragma clang arc_cf_code_audited in scope, consider
// marking the function.
AddCFAuditedAttribute(NewFD);
- // If this is a locally-scoped extern C function, update the
- // map of such names.
- if (CurContext->isFunctionOrMethod() && NewFD->isExternC()
- && !NewFD->isInvalidDecl())
- RegisterLocallyScopedExternCDecl(NewFD, Previous, S);
+ // If this is the first declaration of an extern C variable, update
+ // the map of such variables.
+ if (NewFD->isFirstDecl() && !NewFD->isInvalidDecl() &&
+ isIncompleteDeclExternC(*this, NewFD))
+ RegisterLocallyScopedExternCDecl(NewFD, S);
// Set this FunctionDecl's range up to the right paren.
NewFD->setRangeEnd(D.getSourceRange().getEnd());
@@ -6618,27 +7325,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
diag::err_expected_kernel_void_return_type);
D.setInvalidType();
}
-
+
+ llvm::SmallPtrSet<const Type *, 16> ValidTypes;
for (FunctionDecl::param_iterator PI = NewFD->param_begin(),
PE = NewFD->param_end(); PI != PE; ++PI) {
ParmVarDecl *Param = *PI;
- QualType PT = Param->getType();
-
- // OpenCL v1.2 s6.9.a:
- // A kernel function argument cannot be declared as a
- // pointer to a pointer type.
- if (PT->isPointerType() && PT->getPointeeType()->isPointerType()) {
- Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_arg);
- D.setInvalidType();
- }
-
- // OpenCL v1.2 s6.8 n:
- // A kernel function argument cannot be declared
- // of event_t type.
- if (PT->isEventT()) {
- Diag(Param->getLocation(), diag::err_event_t_kernel_arg);
- D.setInvalidType();
- }
+ checkIsValidOpenCLKernelParameter(*this, D, Param, ValidTypes);
}
}
@@ -6694,15 +7386,11 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
assert(!NewFD->getResultType()->isVariablyModifiedType()
&& "Variably modified return types are not handled here");
- // Check for a previous declaration of this name.
- if (Previous.empty() && mayConflictWithNonVisibleExternC(NewFD)) {
- // Since we did not find anything by this name, look for a non-visible
- // extern "C" declaration with the same name.
- llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
- = findLocallyScopedExternCDecl(NewFD->getDeclName());
- if (Pos != LocallyScopedExternCDecls.end())
- Previous.addDecl(Pos->second);
- }
+ // Determine whether the type of this function should be merged with
+ // a previous visible declaration. This never happens for functions in C++,
+ // and always happens in C if the previous declaration was visible.
+ bool MergeTypeWithPrevious = !getLangOpts().CPlusPlus &&
+ !Previous.isShadowed();
// Filter out any non-conflicting previous declarations.
filterNonConflictingPreviousDecls(Context, NewFD, Previous);
@@ -6758,6 +7446,35 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}
}
+ // Check for a previous extern "C" declaration with this name.
+ if (!Redeclaration &&
+ checkForConflictWithNonVisibleExternC(*this, NewFD, Previous)) {
+ filterNonConflictingPreviousDecls(Context, NewFD, Previous);
+ if (!Previous.empty()) {
+ // This is an extern "C" declaration with the same name as a previous
+ // declaration, and thus redeclares that entity...
+ Redeclaration = true;
+ OldDecl = Previous.getFoundDecl();
+ MergeTypeWithPrevious = false;
+
+ // ... except in the presence of __attribute__((overloadable)).
+ if (OldDecl->hasAttr<OverloadableAttr>()) {
+ if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) {
+ Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
+ << Redeclaration << NewFD;
+ Diag(Previous.getFoundDecl()->getLocation(),
+ diag::note_attribute_overloadable_prev_overload);
+ NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(),
+ Context));
+ }
+ if (IsOverload(NewFD, cast<FunctionDecl>(OldDecl), false)) {
+ Redeclaration = false;
+ OldDecl = 0;
+ }
+ }
+ }
+ }
+
// C++11 [dcl.constexpr]p8:
// A constexpr specifier for a non-static member function that is not
// a constructor declares that member function to be const.
@@ -6781,9 +7498,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals |= Qualifiers::Const;
MD->setType(Context.getFunctionType(FPT->getResultType(),
- ArrayRef<QualType>(FPT->arg_type_begin(),
- FPT->getNumArgs()),
- EPI));
+ FPT->getArgTypes(), EPI));
// Warn that we did this, if we're not performing template instantiation.
// In that case, we'll have warned already when the template was defined.
@@ -6802,7 +7517,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
if (Redeclaration) {
// NewFD and OldDecl represent declarations that need to be
// merged.
- if (MergeFunctionDecl(NewFD, OldDecl, S)) {
+ if (MergeFunctionDecl(NewFD, OldDecl, S, MergeTypeWithPrevious)) {
NewFD->setInvalidDecl();
return Redeclaration;
}
@@ -6850,7 +7565,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// setNonKeyFunction needs to work with the original
// declaration from the class definition, and isVirtual() is
// just faster in that case, so map back to that now.
- oldMethod = cast<CXXMethodDecl>(oldMethod->getFirstDeclaration());
+ oldMethod = cast<CXXMethodDecl>(oldMethod->getFirstDecl());
if (oldMethod->isVirtual()) {
Context.setNonKeyFunction(oldMethod);
}
@@ -6922,7 +7637,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// during delayed parsing anyway.
if (!CurContext->isRecord())
CheckCXXDefaultArguments(NewFD);
-
+
// If this function declares a builtin function, check the type of this
// declaration against the expected type for the builtin.
if (unsigned BuiltinID = NewFD->getBuiltinID()) {
@@ -6935,7 +7650,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
Context.BuiltinInfo.ForgetBuiltin(BuiltinID, Context.Idents);
}
}
-
+
// If this function is declared as being extern "C", then check to see if
// the function returns a UDT (class, struct, or union type) that is not C
// compatible, and if it does, warn the user.
@@ -6998,6 +7713,13 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
FD->setConstexpr(false);
}
+ if (getLangOpts().OpenCL) {
+ Diag(FD->getLocation(), diag::err_opencl_no_main)
+ << FD->hasAttr<OpenCLKernelAttr>();
+ FD->setInvalidDecl();
+ return;
+ }
+
QualType T = FD->getType();
assert(T->isFunctionType() && "function decl is not of function type");
const FunctionType* FT = T->castAs<FunctionType>();
@@ -7096,7 +7818,27 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
}
if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) {
- Diag(FD->getLocation(), diag::err_main_template_decl);
+ Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD->getName();
+ FD->setInvalidDecl();
+ }
+}
+
+void Sema::CheckMSVCRTEntryPoint(FunctionDecl *FD) {
+ QualType T = FD->getType();
+ assert(T->isFunctionType() && "function decl is not of function type");
+ const FunctionType *FT = T->castAs<FunctionType>();
+
+ // Set an implicit return of 'zero' if the function can return some integral,
+ // enumeration, pointer or nullptr type.
+ if (FT->getResultType()->isIntegralOrEnumerationType() ||
+ FT->getResultType()->isAnyPointerType() ||
+ FT->getResultType()->isNullPtrType())
+ // DllMain is exempt because a return value of zero means it failed.
+ if (FD->getName() != "DllMain")
+ FD->setHasImplicitReturnZero(true);
+
+ if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) {
+ Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD->getName();
FD->setInvalidDecl();
}
}
@@ -7313,7 +8055,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
RealDecl->setInvalidDecl();
return;
}
-
ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
// C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
@@ -7326,14 +8067,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// It isn't possible to write this directly, but it is possible to
// end up in this situation with "auto x(some_pack...);"
Diag(CXXDirectInit->getLocStart(),
- diag::err_auto_var_init_no_expression)
+ VDecl->isInitCapture() ? diag::err_init_capture_no_expression
+ : diag::err_auto_var_init_no_expression)
<< VDecl->getDeclName() << VDecl->getType()
<< VDecl->getSourceRange();
RealDecl->setInvalidDecl();
return;
} else if (CXXDirectInit->getNumExprs() > 1) {
Diag(CXXDirectInit->getExpr(1)->getLocStart(),
- diag::err_auto_var_init_multiple_expressions)
+ VDecl->isInitCapture()
+ ? diag::err_init_capture_multiple_expressions
+ : diag::err_auto_var_init_multiple_expressions)
<< VDecl->getDeclName() << VDecl->getType()
<< VDecl->getSourceRange();
RealDecl->setInvalidDecl();
@@ -7385,8 +8129,11 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// If this is a redeclaration, check that the type we just deduced matches
// the previously declared type.
- if (VarDecl *Old = VDecl->getPreviousDecl())
- MergeVarDeclTypes(VDecl, Old, /*OldWasHidden*/ false);
+ if (VarDecl *Old = VDecl->getPreviousDecl()) {
+ // We never need to merge the type, because we cannot form an incomplete
+ // array of auto, nor deduce such a type.
+ MergeVarDeclTypes(VDecl, Old, /*MergeTypeWithPrevious*/false);
+ }
// Check the deduced type is valid for a variable declaration.
CheckVariableDeclarationType(VDecl);
@@ -7576,9 +8323,20 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// C99 6.7.8p4: All the expressions in an initializer for an object that has
// static storage duration shall be constant expressions or string literals.
// C++ does not have this restriction.
- if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl() &&
- VDecl->getStorageClass() == SC_Static)
- CheckForConstantInitializer(Init, DclT);
+ if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl()) {
+ if (VDecl->getStorageClass() == SC_Static)
+ CheckForConstantInitializer(Init, DclT);
+ // C89 is stricter than C99 for non-static aggregate types.
+ // C89 6.5.7p3: All the expressions [...] in an initializer list
+ // for an object that has aggregate or union type shall be
+ // constant expressions.
+ else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() &&
+ isa<InitListExpr>(Init) &&
+ !Init->isConstantInitializer(Context, false))
+ Diag(Init->getExprLoc(),
+ diag::ext_aggregate_init_not_constant)
+ << Init->getSourceRange();
+ }
} else if (VDecl->isStaticDataMember() &&
VDecl->getLexicalDeclContext()->isRecord()) {
// This is an in-class initialization for a static data member, e.g.,
@@ -7679,7 +8437,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
if (VDecl->getStorageClass() == SC_Extern &&
(!getLangOpts().CPlusPlus ||
!(Context.getBaseElementType(VDecl->getType()).isConstQualified() ||
- VDecl->isExternC())))
+ VDecl->isExternC())) &&
+ !isTemplateInstantiation(VDecl->getTemplateSpecializationKind()))
Diag(VDecl->getLocation(), diag::warn_extern_init);
// C99 6.7.8p4. All file scoped initializers need to be constant.
@@ -7817,7 +8576,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
// declared with no linkage (C99 6.2.2p6), the type for the
// object shall be complete.
if (!Type->isDependentType() && Var->isLocalVarDecl() &&
- !Var->getLinkage() && !Var->isInvalidDecl() &&
+ !Var->hasLinkage() && !Var->isInvalidDecl() &&
RequireCompleteType(Var->getLocation(), Type,
diag::err_typecheck_decl_incomplete_type))
Var->setInvalidDecl();
@@ -7859,7 +8618,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
// is accepted by gcc. Hence here we issue a warning instead of
// an error and we do not invalidate the static declaration.
// NOTE: to avoid multiple warnings, only check the first declaration.
- if (Var->getPreviousDecl() == 0)
+ if (Var->isFirstDecl())
RequireCompleteType(Var->getLocation(), Type,
diag::ext_typecheck_decl_incomplete_type);
}
@@ -8030,7 +8789,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
}
if (var->isThisDeclarationADefinition() &&
- var->hasExternalLinkage() &&
+ var->isExternallyVisible() && var->hasLinkage() &&
getDiagnostics().getDiagnosticLevel(
diag::warn_missing_variable_declarations,
var->getLocation())) {
@@ -8091,10 +8850,16 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
if (IsGlobal && !var->isConstexpr() &&
getDiagnostics().getDiagnosticLevel(diag::warn_global_constructor,
var->getLocation())
- != DiagnosticsEngine::Ignored &&
- !Init->isConstantInitializer(Context, baseType->isReferenceType()))
- Diag(var->getLocation(), diag::warn_global_constructor)
- << Init->getSourceRange();
+ != DiagnosticsEngine::Ignored) {
+ // Warn about globals which don't have a constant initializer. Don't
+ // warn about globals with a non-trivial destructor because we already
+ // warned about them.
+ CXXRecordDecl *RD = baseType->getAsCXXRecordDecl();
+ if (!(RD && !RD->hasTrivialDestructor()) &&
+ !Init->isConstantInitializer(Context, baseType->isReferenceType()))
+ Diag(var->getLocation(), diag::warn_global_constructor)
+ << Init->getSourceRange();
+ }
if (var->isConstexpr()) {
SmallVector<PartialDiagnosticAt, 8> Notes;
@@ -8136,10 +8901,29 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
if (!VD)
return;
+ if (UsedAttr *Attr = VD->getAttr<UsedAttr>()) {
+ if (!Attr->isInherited() && !VD->isThisDeclarationADefinition()) {
+ Diag(Attr->getLocation(), diag::warn_attribute_ignored) << "used";
+ VD->dropAttr<UsedAttr>();
+ }
+ }
+
+ if (!VD->isInvalidDecl() &&
+ VD->isThisDeclarationADefinition() == VarDecl::TentativeDefinition) {
+ if (const VarDecl *Def = VD->getDefinition()) {
+ if (Def->hasAttr<AliasAttr>()) {
+ Diag(VD->getLocation(), diag::err_tentative_after_alias)
+ << VD->getDeclName();
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ VD->setInvalidDecl();
+ }
+ }
+ }
+
const DeclContext *DC = VD->getDeclContext();
// If there's a #pragma GCC visibility in scope, and this isn't a class
// member, set the visibility of this variable.
- if (!DC->isRecord() && VD->hasExternalLinkage())
+ if (!DC->isRecord() && VD->isExternallyVisible())
AddPushedVisibilityAttribute(VD);
if (VD->isFileVarDecl())
@@ -8181,30 +8965,37 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
}
}
-Sema::DeclGroupPtrTy
-Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
- Decl **Group, unsigned NumDecls) {
+Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
+ ArrayRef<Decl *> Group) {
SmallVector<Decl*, 8> Decls;
if (DS.isTypeSpecOwned())
Decls.push_back(DS.getRepAsDecl());
- for (unsigned i = 0; i != NumDecls; ++i)
- if (Decl *D = Group[i])
+ DeclaratorDecl *FirstDeclaratorInGroup = 0;
+ for (unsigned i = 0, e = Group.size(); i != e; ++i)
+ if (Decl *D = Group[i]) {
+ if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
+ if (!FirstDeclaratorInGroup)
+ FirstDeclaratorInGroup = DD;
Decls.push_back(D);
+ }
- if (DeclSpec::isDeclRep(DS.getTypeSpecType()))
- if (const TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl()))
- getASTContext().addUnnamedTag(Tag);
+ if (DeclSpec::isDeclRep(DS.getTypeSpecType())) {
+ if (TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) {
+ HandleTagNumbering(*this, Tag);
+ if (!Tag->hasNameForLinkage() && !Tag->hasDeclaratorForAnonDecl())
+ Tag->setDeclaratorForAnonDecl(FirstDeclaratorInGroup);
+ }
+ }
- return BuildDeclaratorGroup(Decls.data(), Decls.size(),
- DS.containsPlaceholderType());
+ return BuildDeclaratorGroup(Decls, DS.containsPlaceholderType());
}
/// BuildDeclaratorGroup - convert a list of declarations into a declaration
/// group, performing any necessary semantic checking.
Sema::DeclGroupPtrTy
-Sema::BuildDeclaratorGroup(Decl **Group, unsigned NumDecls,
+Sema::BuildDeclaratorGroup(llvm::MutableArrayRef<Decl *> Group,
bool TypeMayContainAuto) {
// C++0x [dcl.spec.auto]p7:
// If the type deduced for the template parameter U is not the same in each
@@ -8213,11 +9004,11 @@ Sema::BuildDeclaratorGroup(Decl **Group, unsigned NumDecls,
// between the deduced type U and the deduced type which 'auto' stands for.
// auto a = 0, b = { 1, 2, 3 };
// is legal because the deduced type U is 'int' in both cases.
- if (TypeMayContainAuto && NumDecls > 1) {
+ if (TypeMayContainAuto && Group.size() > 1) {
QualType Deduced;
CanQualType DeducedCanon;
VarDecl *DeducedDecl = 0;
- for (unsigned i = 0; i != NumDecls; ++i) {
+ for (unsigned i = 0, e = Group.size(); i != e; ++i) {
if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) {
AutoType *AT = D->getType()->getContainedAutoType();
// Don't reissue diagnostics when instantiating a template.
@@ -8246,18 +9037,19 @@ Sema::BuildDeclaratorGroup(Decl **Group, unsigned NumDecls,
}
}
- ActOnDocumentableDecls(Group, NumDecls);
+ ActOnDocumentableDecls(Group);
- return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, NumDecls));
+ return DeclGroupPtrTy::make(
+ DeclGroupRef::Create(Context, Group.data(), Group.size()));
}
void Sema::ActOnDocumentableDecl(Decl *D) {
- ActOnDocumentableDecls(&D, 1);
+ ActOnDocumentableDecls(D);
}
-void Sema::ActOnDocumentableDecls(Decl **Group, unsigned NumDecls) {
+void Sema::ActOnDocumentableDecls(ArrayRef<Decl *> Group) {
// Don't parse the comment if Doxygen diagnostics are ignored.
- if (NumDecls == 0 || !Group[0])
+ if (Group.empty() || !Group[0])
return;
if (Diags.getDiagnosticLevel(diag::warn_doc_param_not_found,
@@ -8265,9 +9057,9 @@ void Sema::ActOnDocumentableDecls(Decl **Group, unsigned NumDecls) {
== DiagnosticsEngine::Ignored)
return;
- if (NumDecls >= 2) {
+ if (Group.size() >= 2) {
// This is a decl group. Normally it will contain only declarations
- // procuded from declarator list. But in case we have any definitions or
+ // produced from declarator list. But in case we have any definitions or
// additional declaration references:
// 'typedef struct S {} S;'
// 'typedef struct S *S;'
@@ -8275,8 +9067,7 @@ void Sema::ActOnDocumentableDecls(Decl **Group, unsigned NumDecls) {
// FinalizeDeclaratorGroup adds these as separate declarations.
Decl *MaybeTagDecl = Group[0];
if (MaybeTagDecl && isa<TagDecl>(MaybeTagDecl)) {
- Group++;
- NumDecls--;
+ Group = Group.slice(1);
}
}
@@ -8291,7 +9082,7 @@ void Sema::ActOnDocumentableDecls(Decl **Group, unsigned NumDecls) {
// declaration, but also comments that *follow* the declaration -- thanks to
// the lookahead in the lexer: we've consumed the semicolon and looked
// ahead through comments.
- for (unsigned i = 0; i != NumDecls; ++i)
+ for (unsigned i = 0, e = Group.size(); i != e; ++i)
Context.getCommentForDecl(Group[i], &PP);
}
}
@@ -8302,6 +9093,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
const DeclSpec &DS = D.getDeclSpec();
// Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
+
// C++03 [dcl.stc]p2 also permits 'auto'.
VarDecl::StorageClass StorageClass = SC_None;
if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
@@ -8614,38 +9406,90 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
// Don't warn for OpenCL kernels.
if (FD->hasAttr<OpenCLKernelAttr>())
return false;
-
+
bool MissingPrototype = true;
for (const FunctionDecl *Prev = FD->getPreviousDecl();
Prev; Prev = Prev->getPreviousDecl()) {
// Ignore any declarations that occur in function or method
// scope, because they aren't visible from the header.
- if (Prev->getDeclContext()->isFunctionOrMethod())
+ if (Prev->getLexicalDeclContext()->isFunctionOrMethod())
continue;
-
+
MissingPrototype = !Prev->getType()->isFunctionProtoType();
if (FD->getNumParams() == 0)
PossibleZeroParamPrototype = Prev;
break;
}
-
+
return MissingPrototype;
}
-void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) {
+void
+Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
+ const FunctionDecl *EffectiveDefinition) {
// Don't complain if we're in GNU89 mode and the previous definition
// was an extern inline function.
- const FunctionDecl *Definition;
- if (FD->isDefined(Definition) &&
- !canRedefineFunction(Definition, getLangOpts())) {
- if (getLangOpts().GNUMode && Definition->isInlineSpecified() &&
- Definition->getStorageClass() == SC_Extern)
- Diag(FD->getLocation(), diag::err_redefinition_extern_inline)
+ const FunctionDecl *Definition = EffectiveDefinition;
+ if (!Definition)
+ if (!FD->isDefined(Definition))
+ return;
+
+ if (canRedefineFunction(Definition, getLangOpts()))
+ return;
+
+ if (getLangOpts().GNUMode && Definition->isInlineSpecified() &&
+ Definition->getStorageClass() == SC_Extern)
+ Diag(FD->getLocation(), diag::err_redefinition_extern_inline)
<< FD->getDeclName() << getLangOpts().CPlusPlus;
- else
- Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
- Diag(Definition->getLocation(), diag::note_previous_definition);
- FD->setInvalidDecl();
+ else
+ Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
+
+ Diag(Definition->getLocation(), diag::note_previous_definition);
+ FD->setInvalidDecl();
+}
+
+
+static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
+ Sema &S) {
+ CXXRecordDecl *const LambdaClass = CallOperator->getParent();
+
+ LambdaScopeInfo *LSI = S.PushLambdaScope();
+ LSI->CallOperator = CallOperator;
+ LSI->Lambda = LambdaClass;
+ LSI->ReturnType = CallOperator->getResultType();
+ const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault();
+
+ if (LCD == LCD_None)
+ LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None;
+ else if (LCD == LCD_ByCopy)
+ LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval;
+ else if (LCD == LCD_ByRef)
+ LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref;
+ DeclarationNameInfo DNI = CallOperator->getNameInfo();
+
+ LSI->IntroducerRange = DNI.getCXXOperatorNameRange();
+ LSI->Mutable = !CallOperator->isConst();
+
+ // Add the captures to the LSI so they can be noted as already
+ // captured within tryCaptureVar.
+ for (LambdaExpr::capture_iterator C = LambdaClass->captures_begin(),
+ CEnd = LambdaClass->captures_end(); C != CEnd; ++C) {
+ if (C->capturesVariable()) {
+ VarDecl *VD = C->getCapturedVar();
+ if (VD->isInitCapture())
+ S.CurrentInstantiationScope->InstantiatedLocal(VD, VD);
+ QualType CaptureType = VD->getType();
+ const bool ByRef = C->getCaptureKind() == LCK_ByRef;
+ LSI->addCapture(VD, /*IsBlock*/false, ByRef,
+ /*RefersToEnclosingLocal*/true, C->getLocation(),
+ /*EllipsisLoc*/C->isPackExpansion()
+ ? C->getEllipsisLoc() : SourceLocation(),
+ CaptureType, /*Expr*/ 0);
+
+ } else if (C->capturesThis()) {
+ LSI->addThisCapture(/*Nested*/ false, C->getLocation(),
+ S.getCurrentThisType(), /*Expr*/ 0);
+ }
}
}
@@ -8661,9 +9505,24 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
FD = FunTmpl->getTemplatedDecl();
else
FD = cast<FunctionDecl>(D);
-
- // Enter a new function scope
- PushFunctionScope();
+ // If we are instantiating a generic lambda call operator, push
+ // a LambdaScopeInfo onto the function stack. But use the information
+ // that's already been calculated (ActOnLambdaExpr) to prime the current
+ // LambdaScopeInfo.
+ // When the template operator is being specialized, the LambdaScopeInfo,
+ // has to be properly restored so that tryCaptureVariable doesn't try
+ // and capture any new variables. In addition when calculating potential
+ // captures during transformation of nested lambdas, it is necessary to
+ // have the LSI properly restored.
+ if (isGenericLambdaCallOperatorSpecialization(FD)) {
+ assert(ActiveTemplateInstantiations.size() &&
+ "There should be an active template instantiation on the stack "
+ "when instantiating a generic lambda!");
+ RebuildLambdaScopeInfo(cast<CXXMethodDecl>(D), *this);
+ }
+ else
+ // Enter a new function scope
+ PushFunctionScope();
// See if this is a redefinition.
if (!FD->isLateTemplateParsed())
@@ -8695,17 +9554,19 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
const FunctionDecl *PossibleZeroParamPrototype = 0;
if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) {
Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
-
+
if (PossibleZeroParamPrototype) {
- // We found a declaration that is not a prototype,
+ // We found a declaration that is not a prototype,
// but that could be a zero-parameter prototype
- TypeSourceInfo* TI = PossibleZeroParamPrototype->getTypeSourceInfo();
- TypeLoc TL = TI->getTypeLoc();
- if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>())
- Diag(PossibleZeroParamPrototype->getLocation(),
- diag::note_declaration_not_a_prototype)
- << PossibleZeroParamPrototype
- << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
+ if (TypeSourceInfo *TI =
+ PossibleZeroParamPrototype->getTypeSourceInfo()) {
+ TypeLoc TL = TI->getTypeLoc();
+ if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>())
+ Diag(PossibleZeroParamPrototype->getLocation(),
+ diag::note_declaration_not_a_prototype)
+ << PossibleZeroParamPrototype
+ << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
+ }
}
}
@@ -8732,8 +9593,10 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// If we had any tags defined in the function prototype,
// introduce them into the function scope.
if (FnBodyScope) {
- for (llvm::ArrayRef<NamedDecl*>::iterator I = FD->getDeclsInPrototypeScope().begin(),
- E = FD->getDeclsInPrototypeScope().end(); I != E; ++I) {
+ for (ArrayRef<NamedDecl *>::iterator
+ I = FD->getDeclsInPrototypeScope().begin(),
+ E = FD->getDeclsInPrototypeScope().end();
+ I != E; ++I) {
NamedDecl *D = *I;
// Some of these decls (like enums) may have been pinned to the translation unit
@@ -8852,7 +9715,9 @@ bool Sema::canSkipFunctionBody(Decl *D) {
// We cannot skip the body of a function (or function template) which is
// constexpr, since we may need to evaluate its body in order to parse the
// rest of the file.
- return !FD->isConstexpr();
+ // We cannot skip the body of a function with an undeduced return type,
+ // because any callers of that function need to know the type.
+ return !FD->isConstexpr() && !FD->getResultType()->isUndeducedType();
}
Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) {
@@ -8882,26 +9747,29 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (FD) {
FD->setBody(Body);
- if (getLangOpts().CPlusPlus1y && !FD->isInvalidDecl() &&
- !FD->isDependentContext()) {
- if (FD->getResultType()->isUndeducedType()) {
- // If the function has a deduced result type but contains no 'return'
- // statements, the result type as written must be exactly 'auto', and
- // the deduced result type is 'void'.
- if (!FD->getResultType()->getAs<AutoType>()) {
- Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto)
- << FD->getResultType();
- FD->setInvalidDecl();
- }
- Context.adjustDeducedFunctionResultType(FD, Context.VoidTy);
+ if (getLangOpts().CPlusPlus1y && !FD->isInvalidDecl() && Body &&
+ !FD->isDependentContext() && FD->getResultType()->isUndeducedType()) {
+ // If the function has a deduced result type but contains no 'return'
+ // statements, the result type as written must be exactly 'auto', and
+ // the deduced result type is 'void'.
+ if (!FD->getResultType()->getAs<AutoType>()) {
+ Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto)
+ << FD->getResultType();
+ FD->setInvalidDecl();
+ } else {
+ // Substitute 'void' for the 'auto' in the type.
+ TypeLoc ResultType = FD->getTypeSourceInfo()->getTypeLoc().
+ IgnoreParens().castAs<FunctionProtoTypeLoc>().getResultLoc();
+ Context.adjustDeducedFunctionResultType(
+ FD, SubstAutoType(ResultType.getType(), Context.VoidTy));
}
}
// The only way to be included in UndefinedButUsed is if there is an
// ODR use before the definition. Avoid the expensive map lookup if this
// is the first declaration.
- if (FD->getPreviousDecl() != 0 && FD->getPreviousDecl()->isUsed()) {
- if (FD->getLinkage() != ExternalLinkage)
+ if (!FD->isFirstDecl() && FD->getPreviousDecl()->isUsed()) {
+ if (!FD->isExternallyVisible())
UndefinedButUsed.erase(FD);
else if (FD->isInlined() &&
(LangOpts.CPlusPlus || !LangOpts.GNUInline) &&
@@ -8916,7 +9784,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
// MSVC permits the use of pure specifier (=0) on function definition,
// defined at class scope, warn about this non standard construct.
- if (getLangOpts().MicrosoftExt && FD->isPure())
+ if (getLangOpts().MicrosoftExt && FD->isPure() && FD->isCanonicalDecl())
Diag(FD->getLocation(), diag::warn_pure_function_definition);
if (!FD->isInvalidDecl()) {
@@ -9014,7 +9882,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
PopDeclContext();
PopFunctionScopeInfo(ActivePolicy, dcl);
-
// 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.
@@ -9049,12 +9916,10 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
// function, see whether there was a locally-scoped declaration of
// this name as a function or variable. If so, use that
// (non-visible) declaration, and complain about it.
- llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
- = findLocallyScopedExternCDecl(&II);
- if (Pos != LocallyScopedExternCDecls.end()) {
- Diag(Loc, diag::warn_use_out_of_scope_declaration) << Pos->second;
- Diag(Pos->second->getLocation(), diag::note_previous_declaration);
- return Pos->second;
+ if (NamedDecl *ExternCPrev = findLocallyScopedExternCDecl(&II)) {
+ Diag(Loc, diag::warn_use_out_of_scope_declaration) << ExternCPrev;
+ Diag(ExternCPrev->getLocation(), diag::note_previous_declaration);
+ return ExternCPrev;
}
// Extension in C99. Legal in C90, but warn about it.
@@ -9073,19 +9938,9 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
TypoCorrection Corrected;
DeclFilterCCC<FunctionDecl> Validator;
if (S && (Corrected = CorrectTypo(DeclarationNameInfo(&II, Loc),
- LookupOrdinaryName, S, 0, Validator))) {
- std::string CorrectedStr = Corrected.getAsString(getLangOpts());
- std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts());
- FunctionDecl *Func = Corrected.getCorrectionDeclAs<FunctionDecl>();
-
- Diag(Loc, diag::note_function_suggestion) << CorrectedQuotedStr
- << FixItHint::CreateReplacement(Loc, CorrectedStr);
-
- if (Func->getLocation().isValid()
- && !II.getName().startswith("__builtin_"))
- Diag(Func->getLocation(), diag::note_previous_decl)
- << CorrectedQuotedStr;
- }
+ LookupOrdinaryName, S, 0, Validator)))
+ diagnoseTypo(Corrected, PDiag(diag::note_function_suggestion),
+ /*ErrorRecovery*/false);
}
// Set a Declarator for the implicit definition: int foo();
@@ -9164,7 +10019,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
FD->getParamDecl(FormatIdx)->getType()->isObjCObjectPointerType())
fmt = "NSString";
FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
- fmt, FormatIdx+1,
+ &Context.Idents.get(fmt),
+ FormatIdx+1,
HasVAListArg ? 0 : FormatIdx+2));
}
}
@@ -9172,7 +10028,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
HasVAListArg)) {
if (!FD->getAttr<FormatAttr>())
FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
- "scanf", FormatIdx+1,
+ &Context.Idents.get("scanf"),
+ FormatIdx+1,
HasVAListArg ? 0 : FormatIdx+2));
}
@@ -9212,7 +10069,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
// target-specific builtins, perhaps?
if (!FD->getAttr<FormatAttr>())
FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
- "printf", 2,
+ &Context.Idents.get("printf"), 2,
Name->isStr("vasprintf") ? 0 : 3));
}
@@ -9246,7 +10103,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
NewTD->setInvalidDecl();
return NewTD;
}
-
+
if (D.getDeclSpec().isModulePrivateSpecified()) {
if (CurContext->isFunctionOrMethod())
Diag(NewTD->getLocation(), diag::err_module_private_local)
@@ -9497,13 +10354,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// for non-C++ cases.
if (TemplateParameterLists.size() > 0 ||
(SS.isNotEmpty() && TUK != TUK_Reference)) {
- if (TemplateParameterList *TemplateParams
- = MatchTemplateParametersToScopeSpecifier(KWLoc, NameLoc, SS,
- TemplateParameterLists.data(),
- TemplateParameterLists.size(),
- TUK == TUK_Friend,
- isExplicitSpecialization,
- Invalid)) {
+ if (TemplateParameterList *TemplateParams =
+ MatchTemplateParametersToScopeSpecifier(
+ KWLoc, NameLoc, SS, TemplateParameterLists, TUK == TUK_Friend,
+ isExplicitSpecialization, Invalid)) {
if (Kind == TTK_Enum) {
Diag(KWLoc, diag::err_enum_template);
return 0;
@@ -9572,7 +10426,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
Redecl = NotForRedeclaration;
LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl);
-
+ bool FriendSawTagOutsideEnclosingNamespace = false;
if (Name && SS.isNotEmpty()) {
// We have a nested-name tag ('struct foo::bar').
@@ -9665,8 +10519,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
while (F.hasNext()) {
NamedDecl *ND = F.next();
DeclContext *DC = ND->getDeclContext()->getRedeclContext();
- if (DC->isFileContext() && !EnclosingNS->Encloses(ND->getDeclContext()))
+ if (DC->isFileContext() &&
+ !EnclosingNS->Encloses(ND->getDeclContext())) {
F.erase();
+ FriendSawTagOutsideEnclosingNamespace = true;
+ }
}
F.done();
}
@@ -9757,8 +10614,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
(getLangOpts().CPlusPlus &&
S->isFunctionPrototypeScope()) ||
((S->getFlags() & Scope::DeclScope) == 0) ||
- (S->getEntity() &&
- ((DeclContext *)S->getEntity())->isTransparentContext()))
+ (S->getEntity() && S->getEntity()->isTransparentContext()))
S = S->getParent();
} else {
assert(TUK == TUK_Friend);
@@ -9865,6 +10721,16 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
return TUK == TUK_Declaration ? PrevTagDecl : 0;
}
+ // C++11 [class.mem]p1:
+ // A member shall not be declared twice in the member-specification,
+ // except that a nested class or member class template can be declared
+ // and then later defined.
+ if (TUK == TUK_Declaration && PrevDecl->isCXXClassMember() &&
+ S->isDeclScope(PrevDecl)) {
+ Diag(NameLoc, diag::ext_member_redeclared);
+ Diag(PrevTagDecl->getLocation(), diag::note_previous_declaration);
+ }
+
if (!Invalid) {
// If this is a use, just return the declaration we found.
@@ -10155,7 +11021,7 @@ CreateNewDecl:
// declaration so we always pass true to setObjectOfFriendDecl to make
// the tag name visible.
if (TUK == TUK_Friend)
- New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty() ||
+ New->setObjectOfFriendDecl(!FriendSawTagOutsideEnclosingNamespace &&
getLangOpts().MicrosoftExt);
// Set the access specifier.
@@ -10239,6 +11105,7 @@ Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) {
void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
SourceLocation FinalLoc,
+ bool IsFinalSpelledSealed,
SourceLocation LBraceLoc) {
AdjustDeclIfTemplate(TagD);
CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD);
@@ -10249,8 +11116,9 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
return;
if (FinalLoc.isValid())
- Record->addAttr(new (Context) FinalAttr(FinalLoc, Context));
-
+ Record->addAttr(new (Context)
+ FinalAttr(FinalLoc, Context, IsFinalSpelledSealed));
+
// C++ [class]p2:
// [...] The class-name is also inserted into the scope of the
// class itself; this is known as the injected-class-name. For
@@ -10337,8 +11205,8 @@ void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) {
// Note that FieldName may be null for anonymous bitfields.
ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
IdentifierInfo *FieldName,
- QualType FieldTy, Expr *BitWidth,
- bool *ZeroWidth) {
+ QualType FieldTy, bool IsMsStruct,
+ Expr *BitWidth, bool *ZeroWidth) {
// Default to true; that shouldn't confuse checks for emptiness
if (ZeroWidth)
*ZeroWidth = true;
@@ -10387,7 +11255,7 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
if (!FieldTy->isDependentType()) {
uint64_t TypeSize = Context.getTypeSize(FieldTy);
if (Value.getZExtValue() > TypeSize) {
- if (!getLangOpts().CPlusPlus) {
+ if (!getLangOpts().CPlusPlus || IsMsStruct) {
if (FieldName)
return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size)
<< FieldName << (unsigned)Value.getZExtValue()
@@ -10605,7 +11473,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
bool ZeroWidth = false;
// If this is declared as a bit-field, check the bit-field.
if (!InvalidDecl && BitWidth) {
- BitWidth = VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth).take();
+ BitWidth = VerifyBitField(Loc, II, T, Record->isMsStruct(Context), BitWidth,
+ &ZeroWidth).take();
if (!BitWidth) {
InvalidDecl = true;
BitWidth = 0;
@@ -10658,11 +11527,15 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
}
// C++ [class.union]p1: If a union contains a member of reference type,
- // the program is ill-formed.
+ // the program is ill-formed, except when compiling with MSVC extensions
+ // enabled.
if (EltTy->isReferenceType()) {
- Diag(NewFD->getLocation(), diag::err_union_member_of_reference_type)
+ Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ?
+ diag::ext_union_member_of_reference_type :
+ diag::err_union_member_of_reference_type)
<< NewFD->getDeclName() << EltTy;
- NewFD->setInvalidDecl();
+ if (!getLangOpts().MicrosoftExt)
+ NewFD->setInvalidDecl();
}
}
}
@@ -10693,8 +11566,8 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
assert(FD);
assert(getLangOpts().CPlusPlus && "valid check only for C++");
- if (FD->isInvalidDecl())
- return true;
+ if (FD->isInvalidDecl() || FD->getType()->isDependentType())
+ return false;
QualType EltTy = Context.getBaseElementType(FD->getType());
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
@@ -10782,7 +11655,7 @@ Decl *Sema::ActOnIvar(Scope *S,
if (BitWidth) {
// 6.7.2.1p3, 6.7.2.1p4
- BitWidth = VerifyBitField(Loc, II, T, BitWidth).take();
+ BitWidth = VerifyBitField(Loc, II, T, /*IsMsStruct*/false, BitWidth).take();
if (!BitWidth)
D.setInvalidType();
} else {
@@ -10912,11 +11785,9 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
AllIvarDecls.push_back(Ivar);
}
-void Sema::ActOnFields(Scope* S,
- SourceLocation RecLoc, Decl *EnclosingDecl,
- llvm::ArrayRef<Decl *> Fields,
- SourceLocation LBrac, SourceLocation RBrac,
- AttributeList *Attr) {
+void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
+ ArrayRef<Decl *> Fields, SourceLocation LBrac,
+ SourceLocation RBrac, AttributeList *Attr) {
assert(EnclosingDecl && "missing record or interface decl");
// If this is an Objective-C @implementation or category and we have
@@ -10954,7 +11825,7 @@ void Sema::ActOnFields(Scope* S,
SmallVector<FieldDecl*, 32> RecFields;
bool ARCErrReported = false;
- for (llvm::ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end();
+ for (ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end();
i != end; ++i) {
FieldDecl *FD = cast<FieldDecl>(*i);
@@ -10999,34 +11870,38 @@ void Sema::ActOnFields(Scope* S,
// 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 (getLangOpts().MicrosoftExt) {
- if (Record->isUnion())
- Diag(FD->getLocation(), diag::ext_flexible_array_union_ms)
- << FD->getDeclName();
- else if (Fields.size() == 1)
- Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_ms)
- << FD->getDeclName() << Record->getTagKind();
- } else if (getLangOpts().CPlusPlus) {
- if (Record->isUnion())
- Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu)
- << FD->getDeclName();
- else if (Fields.size() == 1)
- Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_gnu)
- << FD->getDeclName() << Record->getTagKind();
- } else if (!getLangOpts().C99) {
+ unsigned DiagID = 0;
if (Record->isUnion())
- Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu)
- << FD->getDeclName();
- else
+ DiagID = getLangOpts().MicrosoftExt
+ ? diag::ext_flexible_array_union_ms
+ : getLangOpts().CPlusPlus
+ ? diag::ext_flexible_array_union_gnu
+ : diag::err_flexible_array_union;
+ else if (Fields.size() == 1)
+ DiagID = getLangOpts().MicrosoftExt
+ ? diag::ext_flexible_array_empty_aggregate_ms
+ : getLangOpts().CPlusPlus
+ ? diag::ext_flexible_array_empty_aggregate_gnu
+ : NumNamedMembers < 1
+ ? diag::err_flexible_array_empty_aggregate
+ : 0;
+
+ if (DiagID)
+ Diag(FD->getLocation(), DiagID) << FD->getDeclName()
+ << Record->getTagKind();
+ // While the layout of types that contain virtual bases is not specified
+ // by the C++ standard, both the Itanium and Microsoft C++ ABIs place
+ // virtual bases after the derived members. This would make a flexible
+ // array member declared at the end of an object not adjacent to the end
+ // of the type.
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record))
+ if (RD->getNumVBases() != 0)
+ Diag(FD->getLocation(), diag::err_flexible_array_virtual_base)
+ << FD->getDeclName() << Record->getTagKind();
+ if (!getLangOpts().C99)
Diag(FD->getLocation(), diag::ext_c99_flexible_array_member)
<< FD->getDeclName() << Record->getTagKind();
- } else if (NumNamedMembers < 1) {
- Diag(FD->getLocation(), diag::err_flexible_array_empty_struct)
- << FD->getDeclName();
- FD->setInvalidDecl();
- EnclosingDecl->setInvalidDecl();
- continue;
- }
+
if (!FD->getType()->isDependentType() &&
!Context.getBaseElementType(FD->getType()).isPODType(Context)) {
Diag(FD->getLocation(), diag::err_flexible_array_has_nonpod_type)
@@ -11141,10 +12016,18 @@ void Sema::ActOnFields(Scope* S,
I.setAccess((*I)->getAccess());
if (!CXXRecord->isDependentType()) {
- // Adjust user-defined destructor exception spec.
- if (getLangOpts().CPlusPlus11 &&
- CXXRecord->hasUserDeclaredDestructor())
- AdjustDestructorExceptionSpec(CXXRecord,CXXRecord->getDestructor());
+ if (CXXRecord->hasUserDeclaredDestructor()) {
+ // Adjust user-defined destructor exception spec.
+ if (getLangOpts().CPlusPlus11)
+ AdjustDestructorExceptionSpec(CXXRecord,
+ CXXRecord->getDestructor());
+
+ // The Microsoft ABI requires that we perform the destructor body
+ // checks (i.e. operator delete() lookup) at every declaration, as
+ // any translation unit may need to emit a deleting destructor.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ CheckDestructor(CXXRecord->getDestructor());
+ }
// Add any implicitly-declared members to this class.
AddImplicitlyDeclaredMembersToClass(CXXRecord);
@@ -11197,6 +12080,59 @@ void Sema::ActOnFields(Scope* S,
if (Record->hasAttrs())
CheckAlignasUnderalignment(Record);
+
+ // Check if the structure/union declaration is a type that can have zero
+ // size in C. For C this is a language extension, for C++ it may cause
+ // compatibility problems.
+ bool CheckForZeroSize;
+ if (!getLangOpts().CPlusPlus) {
+ CheckForZeroSize = true;
+ } else {
+ // For C++ filter out types that cannot be referenced in C code.
+ CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record);
+ CheckForZeroSize =
+ CXXRecord->getLexicalDeclContext()->isExternCContext() &&
+ !CXXRecord->isDependentType() &&
+ CXXRecord->isCLike();
+ }
+ if (CheckForZeroSize) {
+ bool ZeroSize = true;
+ bool IsEmpty = true;
+ unsigned NonBitFields = 0;
+ for (RecordDecl::field_iterator I = Record->field_begin(),
+ E = Record->field_end();
+ (NonBitFields == 0 || ZeroSize) && I != E; ++I) {
+ IsEmpty = false;
+ if (I->isUnnamedBitfield()) {
+ if (I->getBitWidthValue(Context) > 0)
+ ZeroSize = false;
+ } else {
+ ++NonBitFields;
+ QualType FieldType = I->getType();
+ if (FieldType->isIncompleteType() ||
+ !Context.getTypeSizeInChars(FieldType).isZero())
+ ZeroSize = false;
+ }
+ }
+
+ // Empty structs are an extension in C (C99 6.7.2.1p7). They are
+ // allowed in C++, but warn if its declaration is inside
+ // extern "C" block.
+ if (ZeroSize) {
+ Diag(RecLoc, getLangOpts().CPlusPlus ?
+ diag::warn_zero_size_struct_union_in_extern_c :
+ diag::warn_zero_size_struct_union_compat)
+ << IsEmpty << Record->isUnion() << (NonBitFields > 1);
+ }
+
+ // Structs without named members are extension in C (C99 6.7.2.1p7),
+ // but are accepted by GCC.
+ if (NonBitFields == 0 && !getLangOpts().CPlusPlus) {
+ Diag(RecLoc, IsEmpty ? diag::ext_empty_struct_union :
+ diag::ext_no_named_members_in_struct_union)
+ << Record->isUnion();
+ }
+ }
} else {
ObjCIvarDecl **ClsFields =
reinterpret_cast<ObjCIvarDecl**>(RecFields.data());
@@ -11991,6 +12927,12 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
return Import;
}
+void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
+ // FIXME: Should we synthesize an ImportDecl here?
+ PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc,
+ /*Complain=*/true);
+}
+
void Sema::createImplicitModuleImport(SourceLocation Loc, Module *Mod) {
// Create the implicit import declaration.
TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
index 4e5e4b20d774..3e583862092c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
@@ -23,6 +23,7 @@
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
@@ -52,7 +53,11 @@ enum AttributeDeclKind {
ExpectedTLSVar,
ExpectedVariableOrField,
ExpectedVariableFieldOrTag,
- ExpectedTypeOrNamespace
+ ExpectedTypeOrNamespace,
+ ExpectedObjectiveCInterface,
+ ExpectedMethodOrProperty,
+ ExpectedStructOrUnion,
+ ExpectedStructOrUnionOrClass
};
//===----------------------------------------------------------------------===//
@@ -204,12 +209,18 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
}
+static unsigned getNumAttributeArgs(const AttributeList &Attr) {
+ // FIXME: Include the type in the argument list.
+ return Attr.getNumArgs() + Attr.hasParsedType();
+}
+
/// \brief Check if the attribute has exactly as many args as Num. May
/// output an error.
static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr,
- unsigned int Num) {
- if (Attr.getNumArgs() != Num) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Num;
+ unsigned Num) {
+ if (getNumAttributeArgs(Attr) != Num) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << Num;
return false;
}
@@ -220,8 +231,8 @@ static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr,
/// \brief Check if the attribute has at least as many args as Num. May
/// output an error.
static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr,
- unsigned int Num) {
- if (Attr.getNumArgs() < Num) {
+ unsigned Num) {
+ if (getNumAttributeArgs(Attr) < Num) {
S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num;
return false;
}
@@ -240,24 +251,27 @@ static bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D,
const Expr *IdxExpr,
uint64_t &Idx)
{
- assert(isFunctionOrMethod(D) && hasFunctionProto(D));
+ assert(isFunctionOrMethod(D));
// In C++ the implicit 'this' function parameter also counts.
// Parameters are counted from one.
- const bool HasImplicitThisParam = isInstanceMethod(D);
- const unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
- const unsigned FirstIdx = 1;
+ bool HP = hasFunctionProto(D);
+ bool HasImplicitThisParam = isInstanceMethod(D);
+ bool IV = HP && isFunctionOrMethodVariadic(D);
+ unsigned NumArgs = (HP ? getFunctionOrMethodNumArgs(D) : 0) +
+ HasImplicitThisParam;
llvm::APSInt IdxInt;
if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
!IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) {
- S.Diag(AttrLoc, diag::err_attribute_argument_n_not_int)
- << AttrName << AttrArgNum << IdxExpr->getSourceRange();
+ std::string Name = std::string("'") + AttrName.str() + std::string("'");
+ S.Diag(AttrLoc, diag::err_attribute_argument_n_type) << Name.c_str()
+ << AttrArgNum << AANT_ArgumentIntegerConstant << IdxExpr->getSourceRange();
return false;
}
Idx = IdxInt.getLimitedValue();
- if (Idx < FirstIdx || (!isFunctionOrMethodVariadic(D) && Idx > NumArgs)) {
+ if (Idx < 1 || (!IV && Idx > NumArgs)) {
S.Diag(AttrLoc, diag::err_attribute_argument_out_of_bounds)
<< AttrName << AttrArgNum << IdxExpr->getSourceRange();
return false;
@@ -276,6 +290,42 @@ static bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D,
return true;
}
+/// \brief Check if the argument \p ArgNum of \p Attr is a ASCII string literal.
+/// If not emit an error and return false. If the argument is an identifier it
+/// will emit an error with a fixit hint and treat it as if it was a string
+/// literal.
+bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr,
+ unsigned ArgNum, StringRef &Str,
+ SourceLocation *ArgLocation) {
+ // Look for identifiers. If we have one emit a hint to fix it to a literal.
+ if (Attr.isArgIdent(ArgNum)) {
+ IdentifierLoc *Loc = Attr.getArgAsIdent(ArgNum);
+ Diag(Loc->Loc, diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentString
+ << FixItHint::CreateInsertion(Loc->Loc, "\"")
+ << FixItHint::CreateInsertion(PP.getLocForEndOfToken(Loc->Loc), "\"");
+ Str = Loc->Ident->getName();
+ if (ArgLocation)
+ *ArgLocation = Loc->Loc;
+ return true;
+ }
+
+ // Now check for an actual string literal.
+ Expr *ArgExpr = Attr.getArgAsExpr(ArgNum);
+ StringLiteral *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts());
+ if (ArgLocation)
+ *ArgLocation = ArgExpr->getLocStart();
+
+ if (!Literal || !Literal->isAscii()) {
+ Diag(ArgExpr->getLocStart(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentString;
+ return false;
+ }
+
+ Str = Literal->getString();
+ return true;
+}
+
///
/// \brief Check if passed in Decl is a field or potentially shared global var
/// \return true if the Decl is a field or potentially shared global variable
@@ -414,7 +464,7 @@ static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
int Sidx = 0,
bool ParamIdxOk = false) {
for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) {
- Expr *ArgExp = Attr.getArg(Idx);
+ Expr *ArgExp = Attr.getArgAsExpr(Idx);
if (ArgExp->isTypeDependent()) {
// FIXME -- need to check this again on template instantiation
@@ -424,7 +474,7 @@ static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
if (StringLiteral *StrLit = dyn_cast<StringLiteral>(ArgExp)) {
if (StrLit->getLength() == 0 ||
- StrLit->getString() == StringRef("*")) {
+ (StrLit->isAscii() && StrLit->getString() == StringRef("*"))) {
// Pass empty strings to the analyzer without warnings.
// Treat "*" as the universal lock.
Args.push_back(ArgExp);
@@ -492,11 +542,6 @@ enum ThreadAttributeDeclKind {
static bool checkGuardedVarAttrCommon(Sema &S, Decl *D,
const AttributeList &Attr) {
- assert(!Attr.isInvalid());
-
- if (!checkAttributeNumArgs(S, Attr, 0))
- return false;
-
// D must be either a member field or global (potentially shared) variable.
if (!mayBeSharedVariable(D)) {
S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
@@ -532,11 +577,6 @@ static void handlePtGuardedVarAttr(Sema &S, Decl *D,
static bool checkGuardedByAttrCommon(Sema &S, Decl *D,
const AttributeList &Attr,
Expr* &Arg) {
- assert(!Attr.isInvalid());
-
- if (!checkAttributeNumArgs(S, Attr, 1))
- return false;
-
// D must be either a member field or global (potentially shared) variable.
if (!mayBeSharedVariable(D)) {
S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
@@ -579,13 +619,8 @@ static void handlePtGuardedByAttr(Sema &S, Decl *D,
static bool checkLockableAttrCommon(Sema &S, Decl *D,
const AttributeList &Attr) {
- assert(!Attr.isInvalid());
-
- if (!checkAttributeNumArgs(S, Attr, 0))
- return false;
-
// FIXME: Lockable structs for C code.
- if (!isa<CXXRecordDecl>(D)) {
+ if (!isa<RecordDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
<< Attr.getName() << ThreadExpectedClassOrStruct;
return false;
@@ -613,11 +648,6 @@ static void handleScopedLockableAttr(Sema &S, Decl *D,
static void handleNoThreadSafetyAnalysis(Sema &S, Decl *D,
const AttributeList &Attr) {
- assert(!Attr.isInvalid());
-
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
<< Attr.getName() << ThreadExpectedFunctionOrMethod;
@@ -630,11 +660,6 @@ static void handleNoThreadSafetyAnalysis(Sema &S, Decl *D,
static void handleNoSanitizeAddressAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- assert(!Attr.isInvalid());
-
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
@@ -648,11 +673,6 @@ static void handleNoSanitizeAddressAttr(Sema &S, Decl *D,
static void handleNoSanitizeMemory(Sema &S, Decl *D,
const AttributeList &Attr) {
- assert(!Attr.isInvalid());
-
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
@@ -665,11 +685,6 @@ static void handleNoSanitizeMemory(Sema &S, Decl *D,
static void handleNoSanitizeThread(Sema &S, Decl *D,
const AttributeList &Attr) {
- assert(!Attr.isInvalid());
-
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
@@ -682,9 +697,7 @@ static void handleNoSanitizeThread(Sema &S, Decl *D,
static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
const AttributeList &Attr,
- SmallVector<Expr*, 1> &Args) {
- assert(!Attr.isInvalid());
-
+ SmallVectorImpl<Expr *> &Args) {
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return false;
@@ -743,9 +756,7 @@ static void handleAcquiredBeforeAttr(Sema &S, Decl *D,
static bool checkLockFunAttrCommon(Sema &S, Decl *D,
const AttributeList &Attr,
- SmallVector<Expr*, 1> &Args) {
- assert(!Attr.isInvalid());
-
+ SmallVectorImpl<Expr *> &Args) {
// zero or more arguments ok
// check that the attribute is applied to a function
@@ -788,11 +799,37 @@ static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+static void handleAssertSharedLockAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ SmallVector<Expr*, 1> Args;
+ if (!checkLockFunAttrCommon(S, D, Attr, Args))
+ return;
+
+ unsigned Size = Args.size();
+ Expr **StartArg = Size == 0 ? 0 : &Args[0];
+ D->addAttr(::new (S.Context)
+ AssertSharedLockAttr(Attr.getRange(), S.Context, StartArg, Size,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleAssertExclusiveLockAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ SmallVector<Expr*, 1> Args;
+ if (!checkLockFunAttrCommon(S, D, Attr, Args))
+ return;
+
+ unsigned Size = Args.size();
+ Expr **StartArg = Size == 0 ? 0 : &Args[0];
+ D->addAttr(::new (S.Context)
+ AssertExclusiveLockAttr(Attr.getRange(), S.Context,
+ StartArg, Size,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+
static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,
const AttributeList &Attr,
- SmallVector<Expr*, 2> &Args) {
- assert(!Attr.isInvalid());
-
+ SmallVectorImpl<Expr *> &Args) {
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return false;
@@ -802,9 +839,9 @@ static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,
return false;
}
- if (!isIntOrBool(Attr.getArg(0))) {
- S.Diag(Attr.getLoc(), diag::err_attribute_first_argument_not_int_or_bool)
- << Attr.getName();
+ if (!isIntOrBool(Attr.getArgAsExpr(0))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << 1 << AANT_ArgumentIntOrBool;
return false;
}
@@ -820,11 +857,10 @@ static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D,
if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
return;
- unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? 0 : &Args[0];
D->addAttr(::new (S.Context)
SharedTrylockFunctionAttr(Attr.getRange(), S.Context,
- Attr.getArg(0), StartArg, Size,
+ Attr.getArgAsExpr(0),
+ Args.data(), Args.size(),
Attr.getAttributeSpellingListIndex()));
}
@@ -834,19 +870,16 @@ static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
return;
- unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? 0 : &Args[0];
D->addAttr(::new (S.Context)
ExclusiveTrylockFunctionAttr(Attr.getRange(), S.Context,
- Attr.getArg(0), StartArg, Size,
+ Attr.getArgAsExpr(0),
+ Args.data(), Args.size(),
Attr.getAttributeSpellingListIndex()));
}
static bool checkLocksRequiredCommon(Sema &S, Decl *D,
const AttributeList &Attr,
- SmallVector<Expr*, 1> &Args) {
- assert(!Attr.isInvalid());
-
+ SmallVectorImpl<Expr *> &Args) {
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return false;
@@ -892,8 +925,6 @@ static void handleSharedLocksRequiredAttr(Sema &S, Decl *D,
static void handleUnlockFunAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- assert(!Attr.isInvalid());
-
// zero or more arguments ok
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
@@ -915,11 +946,6 @@ static void handleUnlockFunAttr(Sema &S, Decl *D,
static void handleLockReturnedAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- assert(!Attr.isInvalid());
-
- if (!checkAttributeNumArgs(S, Attr, 1))
- return;
-
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
<< Attr.getName() << ThreadExpectedFunctionOrMethod;
@@ -940,8 +966,6 @@ static void handleLockReturnedAttr(Sema &S, Decl *D,
static void handleLocksExcludedAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- assert(!Attr.isInvalid());
-
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return;
@@ -964,6 +988,260 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ ConsumableAttr::ConsumedState DefaultState;
+
+ if (Attr.isArgIdent(0)) {
+ IdentifierLoc *IL = Attr.getArgAsIdent(0);
+ if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(),
+ DefaultState)) {
+ S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
+ << Attr.getName() << IL->Ident;
+ return;
+ }
+ } else {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ if (!isa<CXXRecordDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
+ Attr.getName() << ExpectedClass;
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ ConsumableAttr(Attr.getRange(), S.Context, DefaultState,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD,
+ const AttributeList &Attr) {
+ ASTContext &CurrContext = S.getASTContext();
+ QualType ThisType = MD->getThisType(CurrContext)->getPointeeType();
+
+ if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) {
+ if (!RD->hasAttr<ConsumableAttr>()) {
+ S.Diag(Attr.getLoc(), diag::warn_attr_on_unconsumable_class) <<
+ RD->getNameAsString();
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+static void handleCallableWhenAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ return;
+
+ if (!isa<CXXMethodDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
+ Attr.getName() << ExpectedMethod;
+ return;
+ }
+
+ if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
+ return;
+
+ SmallVector<CallableWhenAttr::ConsumedState, 3> States;
+ for (unsigned ArgIndex = 0; ArgIndex < Attr.getNumArgs(); ++ArgIndex) {
+ CallableWhenAttr::ConsumedState CallableState;
+
+ StringRef StateString;
+ SourceLocation Loc;
+ if (!S.checkStringLiteralArgumentAttr(Attr, ArgIndex, StateString, &Loc))
+ return;
+
+ if (!CallableWhenAttr::ConvertStrToConsumedState(StateString,
+ CallableState)) {
+ S.Diag(Loc, diag::warn_attribute_type_not_supported)
+ << Attr.getName() << StateString;
+ return;
+ }
+
+ States.push_back(CallableState);
+ }
+
+ D->addAttr(::new (S.Context)
+ CallableWhenAttr(Attr.getRange(), S.Context, States.data(),
+ States.size(), Attr.getAttributeSpellingListIndex()));
+}
+
+
+static void handleParamTypestateAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!checkAttributeNumArgs(S, Attr, 1)) return;
+
+ if (!isa<ParmVarDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
+ Attr.getName() << ExpectedParameter;
+ return;
+ }
+
+ ParamTypestateAttr::ConsumedState ParamState;
+
+ if (Attr.isArgIdent(0)) {
+ IdentifierLoc *Ident = Attr.getArgAsIdent(0);
+ StringRef StateString = Ident->Ident->getName();
+
+ if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString,
+ ParamState)) {
+ S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
+ << Attr.getName() << StateString;
+ return;
+ }
+ } else {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
+ Attr.getName() << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ // FIXME: This check is currently being done in the analysis. It can be
+ // enabled here only after the parser propagates attributes at
+ // template specialization definition, not declaration.
+ //QualType ReturnType = cast<ParmVarDecl>(D)->getType();
+ //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
+ //
+ //if (!RD || !RD->hasAttr<ConsumableAttr>()) {
+ // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
+ // ReturnType.getAsString();
+ // return;
+ //}
+
+ D->addAttr(::new (S.Context)
+ ParamTypestateAttr(Attr.getRange(), S.Context, ParamState,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+
+static void handleReturnTypestateAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!checkAttributeNumArgs(S, Attr, 1)) return;
+
+ if (!(isa<FunctionDecl>(D) || isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
+ Attr.getName() << ExpectedFunctionMethodOrParameter;
+ return;
+ }
+
+ ReturnTypestateAttr::ConsumedState ReturnState;
+
+ if (Attr.isArgIdent(0)) {
+ IdentifierLoc *IL = Attr.getArgAsIdent(0);
+ if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(),
+ ReturnState)) {
+ S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
+ << Attr.getName() << IL->Ident;
+ return;
+ }
+ } else {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
+ Attr.getName() << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ // FIXME: This check is currently being done in the analysis. It can be
+ // enabled here only after the parser propagates attributes at
+ // template specialization definition, not declaration.
+ //QualType ReturnType;
+ //
+ //if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) {
+ // ReturnType = Param->getType();
+ //
+ //} else if (const CXXConstructorDecl *Constructor =
+ // dyn_cast<CXXConstructorDecl>(D)) {
+ // ReturnType = Constructor->getThisType(S.getASTContext())->getPointeeType();
+ //
+ //} else {
+ //
+ // ReturnType = cast<FunctionDecl>(D)->getCallResultType();
+ //}
+ //
+ //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
+ //
+ //if (!RD || !RD->hasAttr<ConsumableAttr>()) {
+ // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
+ // ReturnType.getAsString();
+ // return;
+ //}
+
+ D->addAttr(::new (S.Context)
+ ReturnTypestateAttr(Attr.getRange(), S.Context, ReturnState,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+
+static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (!checkAttributeNumArgs(S, Attr, 1))
+ return;
+
+ if (!isa<CXXMethodDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
+ Attr.getName() << ExpectedMethod;
+ return;
+ }
+
+ if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
+ return;
+
+ SetTypestateAttr::ConsumedState NewState;
+ if (Attr.isArgIdent(0)) {
+ IdentifierLoc *Ident = Attr.getArgAsIdent(0);
+ StringRef Param = Ident->Ident->getName();
+ if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) {
+ S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
+ << Attr.getName() << Param;
+ return;
+ }
+ } else {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
+ Attr.getName() << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ SetTypestateAttr(Attr.getRange(), S.Context, NewState,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleTestTypestateAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!checkAttributeNumArgs(S, Attr, 1))
+ return;
+
+ if (!isa<CXXMethodDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
+ Attr.getName() << ExpectedMethod;
+ return;
+ }
+
+ if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
+ return;
+
+ TestTypestateAttr::ConsumedState TestState;
+ if (Attr.isArgIdent(0)) {
+ IdentifierLoc *Ident = Attr.getArgAsIdent(0);
+ StringRef Param = Ident->Ident->getName();
+ if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) {
+ S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
+ << Attr.getName() << Param;
+ return;
+ }
+ } else {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
+ Attr.getName() << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ TestTypestateAttr(Attr.getRange(), S.Context, TestState,
+ Attr.getAttributeSpellingListIndex()));
+}
static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,
const AttributeList &Attr) {
@@ -980,10 +1258,6 @@ static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,
}
static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (TagDecl *TD = dyn_cast<TagDecl>(D))
TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context));
else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
@@ -1012,10 +1286,6 @@ static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
// The IBAction attributes only apply to instance methods.
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
if (MD->isInstanceMethod()) {
@@ -1055,10 +1325,6 @@ static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (!checkIBOutletCommon(S, D, Attr))
return;
@@ -1071,36 +1337,46 @@ static void handleIBOutletCollection(Sema &S, Decl *D,
const AttributeList &Attr) {
// The iboutletcollection attribute can have zero or one arguments.
- if (Attr.getParameterName() && Attr.getNumArgs() > 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ if (Attr.getNumArgs() > 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
return;
}
if (!checkIBOutletCommon(S, D, Attr))
return;
- IdentifierInfo *II = Attr.getParameterName();
- if (!II)
- II = &S.Context.Idents.get("NSObject");
-
- ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(),
- S.getScopeForContext(D->getDeclContext()->getParent()));
- if (!TypeRep) {
- S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
- return;
+ ParsedType PT;
+
+ if (Attr.hasParsedType())
+ PT = Attr.getTypeArg();
+ else {
+ PT = S.getTypeName(S.Context.Idents.get("NSObject"), Attr.getLoc(),
+ S.getScopeForContext(D->getDeclContext()->getParent()));
+ if (!PT) {
+ S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << "NSObject";
+ return;
+ }
}
- QualType QT = TypeRep.get();
+
+ TypeSourceInfo *QTLoc = 0;
+ QualType QT = S.GetTypeFromParser(PT, &QTLoc);
+ if (!QTLoc)
+ QTLoc = S.Context.getTrivialTypeSourceInfo(QT, Attr.getLoc());
+
// Diagnose use of non-object type in iboutletcollection attribute.
// FIXME. Gnu attribute extension ignores use of builtin types in
// attributes. So, __attribute__((iboutletcollection(char))) will be
// treated as __attribute__((iboutletcollection())).
if (!QT->isObjCIdType() && !QT->isObjCObjectType()) {
- S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
+ S.Diag(Attr.getLoc(),
+ QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype
+ : diag::err_iboutletcollection_type) << QT;
return;
}
+
D->addAttr(::new (S.Context)
- IBOutletCollectionAttr(Attr.getRange(),S.Context,
- QT, Attr.getParameterLoc(),
+ IBOutletCollectionAttr(Attr.getRange(), S.Context, QTLoc,
Attr.getAttributeSpellingListIndex()));
}
@@ -1122,70 +1398,36 @@ static void possibleTransparentUnionPointerType(QualType &T) {
static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!isFunctionOrMethod(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "alloc_size" << ExpectedFunctionOrMethod;
+ << Attr.getName() << ExpectedFunctionOrMethod;
return;
}
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return;
- // In C++ the implicit 'this' function parameter also counts, and they are
- // counted from one.
- bool HasImplicitThisParam = isInstanceMethod(D);
- unsigned NumArgs;
- if (hasFunctionProto(D))
- NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
- else
- NumArgs = 0;
-
SmallVector<unsigned, 8> SizeArgs;
-
- for (AttributeList::arg_iterator I = Attr.arg_begin(),
- E = Attr.arg_end(); I!=E; ++I) {
- // The argument must be an integer constant expression.
- Expr *Ex = *I;
- llvm::APSInt ArgNum;
- if (Ex->isTypeDependent() || Ex->isValueDependent() ||
- !Ex->isIntegerConstantExpr(ArgNum, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "alloc_size" << Ex->getSourceRange();
+ for (unsigned i = 0; i < Attr.getNumArgs(); ++i) {
+ Expr *Ex = Attr.getArgAsExpr(i);
+ uint64_t Idx;
+ if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(),
+ Attr.getLoc(), i + 1, Ex, Idx))
return;
- }
-
- uint64_t x = ArgNum.getZExtValue();
-
- if (x < 1 || x > NumArgs) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << "alloc_size" << I.getArgNum() << Ex->getSourceRange();
- return;
- }
-
- --x;
- if (HasImplicitThisParam) {
- if (x == 0) {
- S.Diag(Attr.getLoc(),
- diag::err_attribute_invalid_implicit_this_argument)
- << "alloc_size" << Ex->getSourceRange();
- return;
- }
- --x;
- }
// check if the function argument is of an integer type
- QualType T = getFunctionOrMethodArgType(D, x).getNonReferenceType();
+ QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType();
if (!T->isIntegerType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "alloc_size" << Ex->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << Ex->getSourceRange();
return;
}
-
- SizeArgs.push_back(x);
+ SizeArgs.push_back(Idx);
}
// check if the function returns a pointer
if (!getFunctionType(D)->getResultType()->isAnyPointerType()) {
S.Diag(Attr.getLoc(), diag::warn_ns_attribute_wrong_return_type)
- << "alloc_size" << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange();
+ << Attr.getName() << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange();
}
D->addAttr(::new (S.Context)
@@ -1203,47 +1445,16 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- // In C++ the implicit 'this' function parameter also counts, and they are
- // counted from one.
- bool HasImplicitThisParam = isInstanceMethod(D);
- unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
-
- // The nonnull attribute only applies to pointers.
- SmallVector<unsigned, 10> NonNullArgs;
-
- for (AttributeList::arg_iterator I = Attr.arg_begin(),
- E = Attr.arg_end(); I != E; ++I) {
- // The argument must be an integer constant expression.
- Expr *Ex = *I;
- llvm::APSInt ArgNum(32);
- if (Ex->isTypeDependent() || Ex->isValueDependent() ||
- !Ex->isIntegerConstantExpr(ArgNum, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "nonnull" << Ex->getSourceRange();
- return;
- }
-
- unsigned x = (unsigned) ArgNum.getZExtValue();
-
- if (x < 1 || x > NumArgs) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << "nonnull" << I.getArgNum() << Ex->getSourceRange();
+ SmallVector<unsigned, 8> NonNullArgs;
+ for (unsigned i = 0; i < Attr.getNumArgs(); ++i) {
+ Expr *Ex = Attr.getArgAsExpr(i);
+ uint64_t Idx;
+ if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(),
+ Attr.getLoc(), i + 1, Ex, Idx))
return;
- }
-
- --x;
- if (HasImplicitThisParam) {
- if (x == 0) {
- S.Diag(Attr.getLoc(),
- diag::err_attribute_invalid_implicit_this_argument)
- << "nonnull" << Ex->getSourceRange();
- return;
- }
- --x;
- }
// Is the function argument a pointer type?
- QualType T = getFunctionOrMethodArgType(D, x).getNonReferenceType();
+ QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType();
possibleTransparentUnionPointerType(T);
if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
@@ -1253,7 +1464,7 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
continue;
}
- NonNullArgs.push_back(x);
+ NonNullArgs.push_back(Idx);
}
// If no arguments were specified to __attribute__((nonnull)) then all pointer
@@ -1284,43 +1495,52 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
+static const char *ownershipKindToDiagName(OwnershipAttr::OwnershipKind K) {
+ switch (K) {
+ case OwnershipAttr::Holds: return "'ownership_holds'";
+ case OwnershipAttr::Takes: return "'ownership_takes'";
+ case OwnershipAttr::Returns: return "'ownership_returns'";
+ }
+ llvm_unreachable("unknown ownership");
+}
+
static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
- // This attribute must be applied to a function declaration.
- // The first argument to the attribute must be a string,
- // the name of the resource, for example "malloc".
- // The following arguments must be argument indexes, the arguments must be
- // of integer type for Returns, otherwise of pointer type.
+ // This attribute must be applied to a function declaration. The first
+ // argument to the attribute must be an identifier, the name of the resource,
+ // for example: malloc. The following arguments must be argument indexes, the
+ // arguments must be of integer type for Returns, otherwise of pointer type.
// The difference between Holds and Takes is that a pointer may still be used
- // after being held. free() should be __attribute((ownership_takes)), whereas
+ // after being held. free() should be __attribute((ownership_takes)), whereas
// a list append function may well be __attribute((ownership_holds)).
- if (!AL.getParameterName()) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_n_not_string)
- << AL.getName()->getName() << 1;
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL.getName() << 1 << AANT_ArgumentIdentifier;
return;
}
+
// Figure out our Kind, and check arguments while we're at it.
OwnershipAttr::OwnershipKind K;
switch (AL.getKind()) {
case AttributeList::AT_ownership_takes:
K = OwnershipAttr::Takes;
- if (AL.getNumArgs() < 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
+ if (AL.getNumArgs() < 2) {
+ S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2;
return;
}
break;
case AttributeList::AT_ownership_holds:
K = OwnershipAttr::Holds;
- if (AL.getNumArgs() < 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
+ if (AL.getNumArgs() < 2) {
+ S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2;
return;
}
break;
case AttributeList::AT_ownership_returns:
K = OwnershipAttr::Returns;
- if (AL.getNumArgs() > 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
- << AL.getNumArgs() + 1;
+
+ if (AL.getNumArgs() > 2) {
+ S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << 1;
return;
}
break;
@@ -1335,107 +1555,58 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
return;
}
- // In C++ the implicit 'this' function parameter also counts, and they are
- // counted from one.
- bool HasImplicitThisParam = isInstanceMethod(D);
- unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
-
- StringRef Module = AL.getParameterName()->getName();
+ StringRef Module = AL.getArgAsIdent(0)->Ident->getName();
// Normalize the argument, __foo__ becomes foo.
if (Module.startswith("__") && Module.endswith("__"))
Module = Module.substr(2, Module.size() - 4);
- SmallVector<unsigned, 10> OwnershipArgs;
-
- for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E;
- ++I) {
-
- Expr *IdxExpr = *I;
- llvm::APSInt ArgNum(32);
- if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
- || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_not_int)
- << AL.getName()->getName() << IdxExpr->getSourceRange();
- continue;
- }
-
- unsigned x = (unsigned) ArgNum.getZExtValue();
-
- if (x > NumArgs || x < 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << AL.getName()->getName() << x << IdxExpr->getSourceRange();
- continue;
- }
- --x;
- if (HasImplicitThisParam) {
- if (x == 0) {
- S.Diag(AL.getLoc(), diag::err_attribute_invalid_implicit_this_argument)
- << "ownership" << IdxExpr->getSourceRange();
- return;
- }
- --x;
- }
+ SmallVector<unsigned, 8> OwnershipArgs;
+ for (unsigned i = 1; i < AL.getNumArgs(); ++i) {
+ Expr *Ex = AL.getArgAsExpr(i);
+ uint64_t Idx;
+ if (!checkFunctionOrMethodArgumentIndex(S, D, AL.getName()->getName(),
+ AL.getLoc(), i, Ex, Idx))
+ return;
+ // Is the function argument a pointer type?
+ QualType T = getFunctionOrMethodArgType(D, Idx);
+ int Err = -1; // No error
switch (K) {
- case OwnershipAttr::Takes:
- case OwnershipAttr::Holds: {
- // Is the function argument a pointer type?
- QualType T = getFunctionOrMethodArgType(D, x);
- if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
- // FIXME: Should also highlight argument in decl.
- S.Diag(AL.getLoc(), diag::err_ownership_type)
- << ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds")
- << "pointer"
- << IdxExpr->getSourceRange();
- continue;
- }
- break;
+ case OwnershipAttr::Takes:
+ case OwnershipAttr::Holds:
+ if (!T->isAnyPointerType() && !T->isBlockPointerType())
+ Err = 0;
+ break;
+ case OwnershipAttr::Returns:
+ if (!T->isIntegerType())
+ Err = 1;
+ break;
}
- case OwnershipAttr::Returns: {
- if (AL.getNumArgs() > 1) {
- // Is the function argument an integer type?
- Expr *IdxExpr = AL.getArg(0);
- llvm::APSInt ArgNum(32);
- if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
- || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
- S.Diag(AL.getLoc(), diag::err_ownership_type)
- << "ownership_returns" << "integer"
- << IdxExpr->getSourceRange();
- return;
- }
- }
- break;
+ if (-1 != Err) {
+ S.Diag(AL.getLoc(), diag::err_ownership_type) << AL.getName() << Err
+ << Ex->getSourceRange();
+ return;
}
- } // switch
// Check we don't have a conflict with another ownership attribute.
for (specific_attr_iterator<OwnershipAttr>
- i = D->specific_attr_begin<OwnershipAttr>(),
- e = D->specific_attr_end<OwnershipAttr>();
- i != e; ++i) {
- if ((*i)->getOwnKind() != K) {
- for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end();
- I!=E; ++I) {
- if (x == *I) {
- S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
- << AL.getName()->getName() << "ownership_*";
- }
- }
+ i = D->specific_attr_begin<OwnershipAttr>(),
+ e = D->specific_attr_end<OwnershipAttr>(); i != e; ++i) {
+ if ((*i)->getOwnKind() != K && (*i)->args_end() !=
+ std::find((*i)->args_begin(), (*i)->args_end(), Idx)) {
+ S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
+ << AL.getName() << ownershipKindToDiagName((*i)->getOwnKind());
+ return;
}
}
- OwnershipArgs.push_back(x);
+ OwnershipArgs.push_back(Idx);
}
unsigned* start = OwnershipArgs.data();
unsigned size = OwnershipArgs.size();
llvm::array_pod_sort(start, start + size);
- if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
- return;
- }
-
D->addAttr(::new (S.Context)
OwnershipAttr(AL.getLoc(), S.Context, K, Module, start, size,
AL.getAttributeSpellingListIndex()));
@@ -1444,7 +1615,8 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// Check the attribute arguments.
if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
return;
}
@@ -1495,21 +1667,15 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// static ((alias ("y"), weakref)).
// Should we? How to check that weakref is before or after alias?
- if (Attr.getNumArgs() == 1) {
- Expr *Arg = Attr.getArg(0);
- Arg = Arg->IgnoreParenCasts();
- StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
-
- if (!Str || !Str->isAscii()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
- << "weakref" << 1;
- return;
- }
+ // FIXME: it would be good for us to keep the WeakRefAttr as-written instead
+ // of transforming it into an AliasAttr. The WeakRefAttr never uses the
+ // StringRef parameter it was given anyway.
+ StringRef Str;
+ if (Attr.getNumArgs() && S.checkStringLiteralArgumentAttr(Attr, 0, Str))
// GCC will accept anything as the argument of weakref. Should we
// check for an existing decl?
- D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context,
- Str->getString()));
- }
+ D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str,
+ Attr.getAttributeSpellingListIndex()));
D->addAttr(::new (S.Context)
WeakRefAttr(Attr.getRange(), S.Context,
@@ -1517,21 +1683,9 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- return;
- }
-
- Expr *Arg = Attr.getArg(0);
- Arg = Arg->IgnoreParenCasts();
- StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
-
- if (!Str || !Str->isAscii()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
- << "alias" << 1;
+ StringRef Str;
+ if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str))
return;
- }
if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {
S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin);
@@ -1540,16 +1694,11 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// FIXME: check if target symbol exists in current file
- D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context,
- Str->getString(),
+ D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str,
Attr.getAttributeSpellingListIndex()));
}
static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // Check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
@@ -1562,10 +1711,6 @@ static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // Check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
@@ -1583,10 +1728,6 @@ static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // Check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
@@ -1604,10 +1745,6 @@ static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // Check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
@@ -1621,12 +1758,6 @@ static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleAlwaysInlineAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- // Check the attribute arguments.
- 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() << ExpectedFunction;
@@ -1640,21 +1771,11 @@ static void handleAlwaysInlineAttr(Sema &S, Decl *D,
static void handleTLSModelAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- return;
- }
-
- Expr *Arg = Attr.getArg(0);
- Arg = Arg->IgnoreParenCasts();
- StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
-
+ StringRef Model;
+ SourceLocation LiteralLoc;
// Check that it is a string.
- if (!Str) {
- S.Diag(Attr.getLoc(), diag::err_attribute_not_string) << "tls_model";
+ if (!S.checkStringLiteralArgumentAttr(Attr, 0, Model, &LiteralLoc))
return;
- }
if (!isa<VarDecl>(D) || !cast<VarDecl>(D)->getTLSKind()) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
@@ -1663,10 +1784,9 @@ static void handleTLSModelAttr(Sema &S, Decl *D,
}
// Check that the value.
- StringRef Model = Str->getString();
if (Model != "global-dynamic" && Model != "local-dynamic"
&& Model != "initial-exec" && Model != "local-exec") {
- S.Diag(Attr.getLoc(), diag::err_attr_tlsmodel_arg);
+ S.Diag(LiteralLoc, diag::err_attr_tlsmodel_arg);
return;
}
@@ -1676,12 +1796,6 @@ static void handleTLSModelAttr(Sema &S, Decl *D,
}
static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // Check the attribute arguments.
- if (Attr.hasParameterOrArguments()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
- return;
- }
-
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
QualType RetTy = FD->getResultType();
if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
@@ -1696,17 +1810,12 @@ static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
D->addAttr(::new (S.Context)
MayAliasAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
}
static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- assert(!Attr.isInvalid());
if (isa<VarDecl>(D))
D->addAttr(::new (S.Context)
NoCommonAttr(Attr.getRange(), S.Context,
@@ -1717,7 +1826,11 @@ static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- assert(!Attr.isInvalid());
+ if (S.LangOpts.CPlusPlus) {
+ S.Diag(Attr.getLoc(), diag::err_common_not_supported_cplusplus);
+ return;
+ }
+
if (isa<VarDecl>(D))
D->addAttr(::new (S.Context)
CommonAttr(Attr.getRange(), S.Context,
@@ -1744,8 +1857,7 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) {
}
bool Sema::CheckNoReturnAttr(const AttributeList &attr) {
- if (attr.hasParameterOrArguments()) {
- Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ if (!checkAttributeNumArgs(*this, attr, 0)) {
attr.setInvalid();
return true;
}
@@ -1758,10 +1870,6 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D,
// The checking path for 'noreturn' and 'analyzer_noreturn' are different
// because 'analyzer_noreturn' does not impact the type.
-
- if(!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) {
ValueDecl *VD = dyn_cast<ValueDecl>(D);
if (VD == 0 || (!VD->getType()->isBlockPointerType()
@@ -1881,12 +1989,6 @@ static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,
}
static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (Attr.hasParameterOrArguments()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
- return;
- }
-
if (!isa<VarDecl>(D) && !isa<ObjCIvarDecl>(D) && !isFunctionOrMethod(D) &&
!isa<TypeDecl>(D) && !isa<LabelDecl>(D) && !isa<FieldDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
@@ -1901,12 +2003,6 @@ static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleReturnsTwiceAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- // check the attribute arguments.
- 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() << ExpectedFunction;
@@ -1919,14 +2015,8 @@ static void handleReturnsTwiceAttr(Sema &S, Decl *D,
}
static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (Attr.hasParameterOrArguments()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
- return;
- }
-
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (VD->hasLocalStorage() || VD->hasExternalStorage()) {
+ if (VD->hasLocalStorage()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used";
return;
}
@@ -1950,12 +2040,13 @@ static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
int priority = 65535; // FIXME: Do not hardcode such constants.
if (Attr.getNumArgs() > 0) {
- Expr *E = Attr.getArg(0);
+ Expr *E = Attr.getArgAsExpr(0);
llvm::APSInt Idx(32);
if (E->isTypeDependent() || E->isValueDependent() ||
!E->isIntegerConstantExpr(Idx, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
- << "constructor" << 1 << E->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << 1 << AANT_ArgumentIntegerConstant
+ << E->getSourceRange();
return;
}
priority = Idx.getZExtValue();
@@ -1981,12 +2072,13 @@ static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
int priority = 65535; // FIXME: Do not hardcode such constants.
if (Attr.getNumArgs() > 0) {
- Expr *E = Attr.getArg(0);
+ Expr *E = Attr.getArgAsExpr(0);
llvm::APSInt Idx(32);
if (E->isTypeDependent() || E->isValueDependent() ||
!E->isIntegerConstantExpr(Idx, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
- << "destructor" << 1 << E->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << 1 << AANT_ArgumentIntegerConstant
+ << E->getSourceRange();
return;
}
priority = Idx.getZExtValue();
@@ -2004,8 +2096,8 @@ static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
template <typename AttrTy>
-static void handleAttrWithMessage(Sema &S, Decl *D, const AttributeList &Attr,
- const char *Name) {
+static void handleAttrWithMessage(Sema &S, Decl *D,
+ const AttributeList &Attr) {
unsigned NumArgs = Attr.getNumArgs();
if (NumArgs > 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
@@ -2014,15 +2106,8 @@ static void handleAttrWithMessage(Sema &S, Decl *D, const AttributeList &Attr,
// Handle the case where the attribute has a text message.
StringRef Str;
- if (NumArgs == 1) {
- StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0));
- if (!SE) {
- S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_not_string)
- << Name;
- return;
- }
- Str = SE->getString();
- }
+ if (NumArgs == 1 && !S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ return;
D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str,
Attr.getAttributeSpellingListIndex()));
@@ -2030,12 +2115,6 @@ static void handleAttrWithMessage(Sema &S, Decl *D, const AttributeList &Attr,
static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- unsigned NumArgs = Attr.getNumArgs();
- if (NumArgs > 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0;
- return;
- }
-
D->addAttr(::new (S.Context)
ArcWeakrefUnavailableAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@@ -2044,13 +2123,8 @@ static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D,
static void handleObjCRootClassAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<ObjCInterfaceDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface);
- return;
- }
-
- unsigned NumArgs = Attr.getNumArgs();
- if (NumArgs > 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedObjectiveCInterface;
return;
}
@@ -2066,12 +2140,6 @@ static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D,
return;
}
- unsigned NumArgs = Attr.getNumArgs();
- if (NumArgs > 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0;
- return;
- }
-
D->addAttr(::new (S.Context)
ObjCRequiresPropertyDefsAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@@ -2261,13 +2329,15 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
static void handleAvailabilityAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- IdentifierInfo *Platform = Attr.getParameterName();
- SourceLocation PlatformLoc = Attr.getParameterLoc();
+ if (!checkAttributeNumArgs(S, Attr, 1))
+ return;
+ IdentifierLoc *Platform = Attr.getArgAsIdent(0);
unsigned Index = Attr.getAttributeSpellingListIndex();
- if (AvailabilityAttr::getPrettyPlatformName(Platform->getName()).empty())
- S.Diag(PlatformLoc, diag::warn_availability_unknown_platform)
- << Platform;
+ IdentifierInfo *II = Platform->Ident;
+ if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty())
+ S.Diag(Platform->Loc, diag::warn_availability_unknown_platform)
+ << Platform->Ident;
NamedDecl *ND = dyn_cast<NamedDecl>(D);
if (!ND) {
@@ -2280,13 +2350,11 @@ static void handleAvailabilityAttr(Sema &S, Decl *D,
AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted();
bool IsUnavailable = Attr.getUnavailableLoc().isValid();
StringRef Str;
- const StringLiteral *SE =
- dyn_cast_or_null<const StringLiteral>(Attr.getMessageExpr());
- if (SE)
+ if (const StringLiteral *SE =
+ dyn_cast_or_null<StringLiteral>(Attr.getMessageExpr()))
Str = SE->getString();
- AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(),
- Platform,
+ AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), II,
Introduced.Version,
Deprecated.Version,
Obsoleted.Version,
@@ -2346,41 +2414,25 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr,
return;
}
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 1))
+ // Check that the argument is a string literal.
+ StringRef TypeStr;
+ SourceLocation LiteralLoc;
+ if (!S.checkStringLiteralArgumentAttr(Attr, 0, TypeStr, &LiteralLoc))
return;
- Expr *Arg = Attr.getArg(0);
- Arg = Arg->IgnoreParenCasts();
- StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
-
- if (!Str || !Str->isAscii()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
- << (isTypeVisibility ? "type_visibility" : "visibility") << 1;
+ VisibilityAttr::VisibilityType type;
+ if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) {
+ S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported)
+ << Attr.getName() << TypeStr;
return;
}
-
- StringRef TypeStr = Str->getString();
- VisibilityAttr::VisibilityType type;
- if (TypeStr == "default")
+ // Complain about attempts to use protected visibility on targets
+ // (like Darwin) that don't support it.
+ if (type == VisibilityAttr::Protected &&
+ !S.Context.getTargetInfo().hasProtectedVisibility()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility);
type = VisibilityAttr::Default;
- else if (TypeStr == "hidden")
- type = VisibilityAttr::Hidden;
- else if (TypeStr == "internal")
- type = VisibilityAttr::Hidden; // FIXME
- else if (TypeStr == "protected") {
- // Complain about attempts to use protected visibility on targets
- // (like Darwin) that don't support it.
- if (!S.Context.getTargetInfo().hasProtectedVisibility()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility);
- type = VisibilityAttr::Default;
- } else {
- type = VisibilityAttr::Protected;
- }
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
- return;
}
unsigned Index = Attr.getAttributeSpellingListIndex();
@@ -2405,39 +2457,21 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
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();
+ if (!Attr.isArgIdent(0)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << 1 << AANT_ArgumentIdentifier;
return;
}
- 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);
+ IdentifierLoc *IL = Attr.getArgAsIdent(0);
+ ObjCMethodFamilyAttr::FamilyKind F;
+ if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) {
+ S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << Attr.getName()
+ << IL->Ident;
return;
}
- if (family == ObjCMethodFamilyAttr::OMF_init &&
+ if (F == ObjCMethodFamilyAttr::OMF_init &&
!method->getResultType()->isObjCObjectPointerType()) {
S.Diag(method->getLocation(), diag::err_init_method_bad_return_type)
<< method->getResultType();
@@ -2446,17 +2480,15 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
}
method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(),
- S.Context, family));
+ S.Context, F));
}
static void handleObjCExceptionAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D);
if (OCI == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface);
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedObjectiveCInterface;
return;
}
@@ -2466,10 +2498,6 @@ static void handleObjCExceptionAttr(Sema &S, Decl *D,
}
static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- return;
- }
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
QualType T = TD->getUnderlyingType();
if (!T->isCARCBridgableType()) {
@@ -2500,11 +2528,6 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
static void
handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- return;
- }
-
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function);
return;
@@ -2516,23 +2539,17 @@ handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!Attr.getParameterName()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
- << "blocks" << 1;
- return;
- }
-
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ if (!Attr.isArgIdent(0)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << 1 << AANT_ArgumentIdentifier;
return;
}
+ IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
BlocksAttr::BlockType type;
- if (Attr.getParameterName()->isStr("byref"))
- type = BlocksAttr::ByRef;
- else {
+ if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << "blocks" << Attr.getParameterName();
+ << Attr.getName() << II;
return;
}
@@ -2550,12 +2567,13 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
unsigned sentinel = 0;
if (Attr.getNumArgs() > 0) {
- Expr *E = Attr.getArg(0);
+ Expr *E = Attr.getArgAsExpr(0);
llvm::APSInt Idx(32);
if (E->isTypeDependent() || E->isValueDependent() ||
!E->isIntegerConstantExpr(Idx, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
- << "sentinel" << 1 << E->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << 1 << AANT_ArgumentIntegerConstant
+ << E->getSourceRange();
return;
}
@@ -2570,12 +2588,13 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
unsigned nullPos = 0;
if (Attr.getNumArgs() > 1) {
- Expr *E = Attr.getArg(1);
+ Expr *E = Attr.getArgAsExpr(1);
llvm::APSInt Idx(32);
if (E->isTypeDependent() || E->isValueDependent() ||
!E->isIntegerConstantExpr(Idx, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
- << "sentinel" << 2 << E->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << 2 << AANT_ArgumentIntegerConstant
+ << E->getSourceRange();
return;
}
nullPos = Idx.getZExtValue();
@@ -2635,11 +2654,14 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
-static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
+static void handleWarnUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (RecordDecl *RD = dyn_cast<RecordDecl>(D))
+ RD->addAttr(::new (S.Context) WarnUnusedAttr(Attr.getRange(), S.Context));
+ else
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+}
+static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) {
if (!isFunction(D) && !isa<ObjCMethodDecl>(D) && !isa<CXXRecordDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionMethodOrClass;
@@ -2664,12 +2686,6 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr)
}
static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (Attr.hasParameterOrArguments()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
- return;
- }
-
if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) {
if (isa<CXXRecordDecl>(D)) {
D->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context));
@@ -2688,18 +2704,12 @@ static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
-
// weak_import only applies to variable & function declarations.
bool isDef = false;
if (!D->canBeWeakImported(isDef)) {
if (isDef)
- S.Diag(Attr.getLoc(),
- diag::warn_attribute_weak_import_invalid_on_definition)
- << "weak_import" << 2 /*variable and function*/;
+ S.Diag(Attr.getLoc(), diag::warn_attribute_invalid_on_definition)
+ << "weak_import";
else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) ||
(S.Context.getTargetInfo().getTriple().isOSDarwin() &&
(isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) {
@@ -2719,20 +2729,15 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// Handles reqd_work_group_size and work_group_size_hint.
static void handleWorkGroupSize(Sema &S, Decl *D,
const AttributeList &Attr) {
- assert(Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize
- || Attr.getKind() == AttributeList::AT_WorkGroupSizeHint);
-
- // Attribute has 3 arguments.
- if (!checkAttributeNumArgs(S, Attr, 3)) return;
-
unsigned WGSize[3];
for (unsigned i = 0; i < 3; ++i) {
- Expr *E = Attr.getArg(i);
+ Expr *E = Attr.getArgAsExpr(i);
llvm::APSInt ArgNum(32);
if (E->isTypeDependent() || E->isValueDependent() ||
!E->isIntegerConstantExpr(ArgNum, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << Attr.getName()->getName() << E->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << E->getSourceRange();
return;
}
WGSize[i] = (unsigned) ArgNum.getZExtValue();
@@ -2775,11 +2780,15 @@ static void handleWorkGroupSize(Sema &S, Decl *D,
static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) {
assert(Attr.getKind() == AttributeList::AT_VecTypeHint);
- // Attribute has 1 argument.
- if (!checkAttributeNumArgs(S, Attr, 1))
+ if (!Attr.hasParsedType()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
return;
+ }
- QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg());
+ TypeSourceInfo *ParmTSI = 0;
+ QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg(), &ParmTSI);
+ assert(ParmTSI && "no type source info for attribute argument");
if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() &&
(ParmType->isBooleanType() ||
@@ -2792,23 +2801,14 @@ static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) {
if (Attr.getKind() == AttributeList::AT_VecTypeHint &&
D->hasAttr<VecTypeHintAttr>()) {
VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>();
- if (A->getTypeHint() != ParmType) {
+ if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) {
S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
return;
}
}
D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context,
- ParmType, Attr.getLoc()));
-}
-
-static void handleEndianAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!dyn_cast<VarDecl>(D))
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << "endian"
- << 9;
- StringRef EndianType = Attr.getParameterName()->getName();
- if (EndianType != "host" && EndianType != "device")
- S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_endian) << EndianType;
+ ParmTSI));
}
SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
@@ -2826,48 +2826,35 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
}
static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // Attribute has no arguments.
- if (!checkAttributeNumArgs(S, Attr, 1))
- return;
-
// Make sure that there is a string literal as the sections's single
// argument.
- Expr *ArgExpr = Attr.getArg(0);
- StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
- if (!SE) {
- S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) << "section";
+ StringRef Str;
+ SourceLocation LiteralLoc;
+ if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc))
return;
- }
// If the target wants to validate the section specifier, make it happen.
- std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(SE->getString());
+ std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str);
if (!Error.empty()) {
- S.Diag(SE->getLocStart(), diag::err_attribute_section_invalid_for_target)
+ S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
<< Error;
return;
}
// This attribute cannot be applied to local variables.
if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) {
- S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable);
+ S.Diag(LiteralLoc, diag::err_attribute_section_local_variable);
return;
}
unsigned Index = Attr.getAttributeSpellingListIndex();
- SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(),
- SE->getString(), Index);
+ SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), Str, Index);
if (NewAttr)
D->addAttr(NewAttr);
}
static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (Attr.hasParameterOrArguments()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
- return;
- }
-
if (NoThrowAttr *Existing = D->getAttr<NoThrowAttr>()) {
if (Existing->getLocation().isInvalid())
Existing->setRange(Attr.getRange());
@@ -2879,12 +2866,6 @@ static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (Attr.hasParameterOrArguments()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
- return;
- }
-
if (ConstAttr *Existing = D->getAttr<ConstAttr>()) {
if (Existing->getLocation().isInvalid())
Existing->setRange(Attr.getRange());
@@ -2896,56 +2877,55 @@ static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
D->addAttr(::new (S.Context)
PureAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
}
static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!Attr.getParameterName()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- return;
- }
-
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- return;
- }
-
VarDecl *VD = dyn_cast<VarDecl>(D);
-
if (!VD || !VD->hasLocalStorage()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup";
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
return;
}
- // Look up the function
- // FIXME: Lookup probably isn't looking in the right place
- NamedDecl *CleanupDecl
- = S.LookupSingleName(S.TUScope, Attr.getParameterName(),
- Attr.getParameterLoc(), Sema::LookupOrdinaryName);
- if (!CleanupDecl) {
- S.Diag(Attr.getParameterLoc(), diag::err_attribute_cleanup_arg_not_found) <<
- Attr.getParameterName();
- return;
- }
+ Expr *E = Attr.getArgAsExpr(0);
+ SourceLocation Loc = E->getExprLoc();
+ FunctionDecl *FD = 0;
+ DeclarationNameInfo NI;
- FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl);
- if (!FD) {
- S.Diag(Attr.getParameterLoc(),
- diag::err_attribute_cleanup_arg_not_function)
- << Attr.getParameterName();
+ // gcc only allows for simple identifiers. Since we support more than gcc, we
+ // will warn the user.
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (DRE->hasQualifier())
+ S.Diag(Loc, diag::warn_cleanup_ext);
+ FD = dyn_cast<FunctionDecl>(DRE->getDecl());
+ NI = DRE->getNameInfo();
+ if (!FD) {
+ S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1
+ << NI.getName();
+ return;
+ }
+ } else if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+ if (ULE->hasExplicitTemplateArgs())
+ S.Diag(Loc, diag::warn_cleanup_ext);
+ FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true);
+ NI = ULE->getNameInfo();
+ if (!FD) {
+ S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2
+ << NI.getName();
+ if (ULE->getType() == S.Context.OverloadTy)
+ S.NoteAllOverloadCandidates(ULE);
+ return;
+ }
+ } else {
+ S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 0;
return;
}
if (FD->getNumParams() != 1) {
- S.Diag(Attr.getParameterLoc(),
- diag::err_attribute_cleanup_func_must_take_one_arg)
- << Attr.getParameterName();
+ S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg)
+ << NI.getName();
return;
}
@@ -2955,63 +2935,30 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
QualType ParamTy = FD->getParamDecl(0)->getType();
if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(),
ParamTy, Ty) != Sema::Compatible) {
- S.Diag(Attr.getParameterLoc(),
- diag::err_attribute_cleanup_func_arg_incompatible_type) <<
- Attr.getParameterName() << ParamTy << Ty;
+ S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type)
+ << NI.getName() << ParamTy << Ty;
return;
}
D->addAttr(::new (S.Context)
CleanupAttr(Attr.getRange(), S.Context, FD,
Attr.getAttributeSpellingListIndex()));
- S.MarkFunctionReferenced(Attr.getParameterLoc(), FD);
- S.DiagnoseUseOfDecl(FD, Attr.getParameterLoc());
}
/// Handle __attribute__((format_arg((idx)))) attribute based on
/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkAttributeNumArgs(S, Attr, 1))
- return;
-
if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
- // In C++ the implicit 'this' function parameter also counts, and they are
- // counted from one.
- bool HasImplicitThisParam = isInstanceMethod(D);
- unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
- unsigned FirstIdx = 1;
-
- // checks for the 2nd argument
- Expr *IdxExpr = Attr.getArg(0);
- llvm::APSInt Idx(32);
- if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
- !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
- << "format" << 2 << IdxExpr->getSourceRange();
- return;
- }
-
- if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << "format" << 2 << IdxExpr->getSourceRange();
+ Expr *IdxExpr = Attr.getArgAsExpr(0);
+ uint64_t ArgIdx;
+ if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(),
+ Attr.getLoc(), 1, IdxExpr, ArgIdx))
return;
- }
-
- unsigned ArgIdx = Idx.getZExtValue() - 1;
-
- if (HasImplicitThisParam) {
- if (ArgIdx == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_implicit_this_argument)
- << "format_arg" << IdxExpr->getSourceRange();
- return;
- }
- ArgIdx--;
- }
// make sure the format string is really a string
QualType Ty = getFunctionOrMethodArgType(D, ArgIdx);
@@ -3039,8 +2986,14 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
+ // We cannot use the ArgIdx returned from checkFunctionOrMethodArgumentIndex
+ // because that has corrected for the implicit this parameter, and is zero-
+ // based. The attribute expects what the user wrote explicitly.
+ llvm::APSInt Val;
+ IdxExpr->EvaluateAsInt(Val, S.Context);
+
D->addAttr(::new (S.Context)
- FormatArgAttr(Attr.getRange(), S.Context, Idx.getZExtValue(),
+ FormatArgAttr(Attr.getRange(), S.Context, Val.getZExtValue(),
Attr.getAttributeSpellingListIndex()));
}
@@ -3094,18 +3047,14 @@ static void handleInitPriorityAttr(Sema &S, Decl *D,
return;
}
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- Attr.setInvalid();
- return;
- }
- Expr *priorityExpr = Attr.getArg(0);
+ Expr *priorityExpr = Attr.getArgAsExpr(0);
llvm::APSInt priority(32);
if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() ||
!priorityExpr->isIntegerConstantExpr(priority, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "init_priority" << priorityExpr->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << priorityExpr->getSourceRange();
Attr.setInvalid();
return;
}
@@ -3121,8 +3070,9 @@ static void handleInitPriorityAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
-FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format,
- int FormatIdx, int FirstArg,
+FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Format, int FormatIdx,
+ int FirstArg,
unsigned AttrSpellingListIndex) {
// Check whether we already have an equivalent format attribute.
for (specific_attr_iterator<FormatAttr>
@@ -3141,22 +3091,16 @@ FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format,
}
}
- return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx, FirstArg,
- AttrSpellingListIndex);
+ return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx,
+ FirstArg, AttrSpellingListIndex);
}
/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
-
- if (!Attr.getParameterName()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
- << "format" << 1;
- return;
- }
-
- if (Attr.getNumArgs() != 2) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3;
+ if (!Attr.isArgIdent(0)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << 1 << AANT_ArgumentIdentifier;
return;
}
@@ -3172,11 +3116,15 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
unsigned FirstIdx = 1;
- StringRef Format = Attr.getParameterName()->getName();
+ IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
+ StringRef Format = II->getName();
// Normalize the argument, __foo__ becomes foo.
- if (Format.startswith("__") && Format.endswith("__"))
+ if (Format.startswith("__") && Format.endswith("__")) {
Format = Format.substr(2, Format.size() - 4);
+ // If we've modified the string name, we need a new identifier for it.
+ II = &S.Context.Idents.get(Format);
+ }
// Check for supported formats.
FormatAttrKind Kind = getFormatAttrKind(Format);
@@ -3186,17 +3134,18 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (Kind == InvalidFormat) {
S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << "format" << Attr.getParameterName()->getName();
+ << "format" << II->getName();
return;
}
// checks for the 2nd argument
- Expr *IdxExpr = Attr.getArg(0);
+ Expr *IdxExpr = Attr.getArgAsExpr(1);
llvm::APSInt Idx(32);
if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
- << "format" << 2 << IdxExpr->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << 2 << AANT_ArgumentIntegerConstant
+ << IdxExpr->getSourceRange();
return;
}
@@ -3246,12 +3195,13 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
// check the 3rd argument
- Expr *FirstArgExpr = Attr.getArg(1);
+ Expr *FirstArgExpr = Attr.getArgAsExpr(2);
llvm::APSInt FirstArg(32);
if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() ||
!FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
- << "format" << 3 << FirstArgExpr->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << 3 << AANT_ArgumentIntegerConstant
+ << FirstArgExpr->getSourceRange();
return;
}
@@ -3280,7 +3230,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), Format,
+ FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), II,
Idx.getZExtValue(),
FirstArg.getZExtValue(),
Attr.getAttributeSpellingListIndex());
@@ -3290,11 +3240,6 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleTransparentUnionAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
-
// Try to find the underlying union declaration.
RecordDecl *RD = 0;
TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
@@ -3358,37 +3303,30 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D,
}
static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 1))
- return;
-
- Expr *ArgExpr = Attr.getArg(0);
- StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
-
// Make sure that there is a string literal as the annotation's single
// argument.
- if (!SE) {
- S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
+ StringRef Str;
+ if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str))
return;
- }
// Don't duplicate annotations that are already set.
for (specific_attr_iterator<AnnotateAttr>
i = D->specific_attr_begin<AnnotateAttr>(),
e = D->specific_attr_end<AnnotateAttr>(); i != e; ++i) {
- if ((*i)->getAnnotation() == SE->getString())
- return;
+ if ((*i)->getAnnotation() == Str)
+ return;
}
D->addAttr(::new (S.Context)
- AnnotateAttr(Attr.getRange(), S.Context, SE->getString(),
+ AnnotateAttr(Attr.getRange(), S.Context, Str,
Attr.getAttributeSpellingListIndex()));
}
static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// check the attribute arguments.
if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
return;
}
@@ -3398,7 +3336,7 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- Expr *E = Attr.getArg(0);
+ Expr *E = Attr.getArgAsExpr(0);
if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) {
S.Diag(Attr.getEllipsisLoc(),
diag::err_pack_expansion_without_parameter_packs);
@@ -3555,19 +3493,14 @@ void Sema::CheckAlignasUnderalignment(Decl *D) {
static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// This attribute isn't documented, but glibc uses it. It changes
// the width of an int or unsigned int to the specified size.
-
- // Check that there aren't any arguments
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
-
- IdentifierInfo *Name = Attr.getParameterName();
- if (!Name) {
- S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
+ if (!Attr.isArgIdent(0)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
+ << AANT_ArgumentIdentifier;
return;
}
-
- StringRef Str = Attr.getParameterName()->getName();
+
+ IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident;
+ StringRef Str = Name->getName();
// Normalize the attribute name, __foo__ becomes foo.
if (Str.startswith("__") && Str.endswith("__"))
@@ -3639,73 +3572,24 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
// and friends, at least with glibc.
- // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong
- // width on unusual platforms.
// FIXME: Make sure floating-point mappings are accurate
// FIXME: Support XF and TF types
- QualType NewTy;
- switch (DestWidth) {
- case 0:
+ if (!DestWidth) {
S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name;
return;
- default:
+ }
+
+ QualType NewTy;
+
+ if (IntegerMode)
+ NewTy = S.Context.getIntTypeForBitwidth(DestWidth,
+ OldTy->isSignedIntegerType());
+ else
+ NewTy = S.Context.getRealTypeForBitwidth(DestWidth);
+
+ if (NewTy.isNull()) {
S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
return;
- case 8:
- if (!IntegerMode) {
- S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
- return;
- }
- if (OldTy->isSignedIntegerType())
- NewTy = S.Context.SignedCharTy;
- else
- NewTy = S.Context.UnsignedCharTy;
- break;
- case 16:
- if (!IntegerMode) {
- S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
- return;
- }
- if (OldTy->isSignedIntegerType())
- NewTy = S.Context.ShortTy;
- else
- NewTy = S.Context.UnsignedShortTy;
- break;
- case 32:
- if (!IntegerMode)
- NewTy = S.Context.FloatTy;
- else if (OldTy->isSignedIntegerType())
- NewTy = S.Context.IntTy;
- else
- NewTy = S.Context.UnsignedIntTy;
- break;
- case 64:
- if (!IntegerMode)
- NewTy = S.Context.DoubleTy;
- else if (OldTy->isSignedIntegerType())
- if (S.Context.getTargetInfo().getLongWidth() == 64)
- NewTy = S.Context.LongTy;
- else
- NewTy = S.Context.LongLongTy;
- else
- if (S.Context.getTargetInfo().getLongWidth() == 64)
- NewTy = S.Context.UnsignedLongTy;
- else
- NewTy = S.Context.UnsignedLongLongTy;
- break;
- case 96:
- NewTy = S.Context.LongDoubleTy;
- break;
- case 128:
- if (!IntegerMode) {
- S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
- return;
- }
- if (OldTy->isSignedIntegerType())
- NewTy = S.Context.Int128Ty;
- else
- NewTy = S.Context.UnsignedInt128Ty;
- break;
}
if (ComplexMode) {
@@ -3713,18 +3597,17 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
// Install the new type.
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
- // FIXME: preserve existing source info.
- TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy));
- } else
+ if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
+ TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy);
+ else
cast<ValueDecl>(D)->setType(NewTy);
+
+ D->addAttr(::new (S.Context)
+ ModeAttr(Attr.getRange(), S.Context, Name,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (!VD->hasGlobalStorage())
S.Diag(Attr.getLoc(),
@@ -3743,11 +3626,6 @@ static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
-
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
@@ -3761,11 +3639,6 @@ static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
-
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
@@ -3779,12 +3652,6 @@ static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D,
static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.CUDA) {
- // check the attribute arguments.
- 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() << ExpectedVariable;
@@ -3803,7 +3670,8 @@ static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.CUDA) {
// check the attribute arguments.
if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 0;
return;
}
@@ -3823,10 +3691,6 @@ static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.CUDA) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
@@ -3858,11 +3722,6 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.CUDA) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
-
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
@@ -3879,10 +3738,6 @@ static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.CUDA) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
if (!isa<VarDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedVariable;
@@ -3898,10 +3753,6 @@ static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 0))
- return;
-
FunctionDecl *Fn = dyn_cast<FunctionDecl>(D);
if (Fn == 0) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
@@ -4006,19 +3857,17 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){
- assert(!Attr.isInvalid());
D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context));
}
static void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){
- assert(!Attr.isInvalid());
-
- Expr *E = Attr.getArg(0);
+ Expr *E = Attr.getArgAsExpr(0);
llvm::APSInt ArgNum(32);
if (E->isTypeDependent() || E->isValueDependent() ||
!E->isIntegerConstantExpr(ArgNum, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << Attr.getName()->getName() << E->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << E->getSourceRange();
return;
}
@@ -4032,8 +3881,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
return true;
unsigned ReqArgs = attr.getKind() == AttributeList::AT_Pcs ? 1 : 0;
- if (attr.getNumArgs() != ReqArgs || attr.getParameterName()) {
- Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << ReqArgs;
+ if (!checkAttributeNumArgs(*this, attr, ReqArgs)) {
attr.setInvalid();
return true;
}
@@ -4055,16 +3903,11 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
CC_C;
break;
case AttributeList::AT_Pcs: {
- Expr *Arg = attr.getArg(0);
- StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
- if (!Str || !Str->isAscii()) {
- Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
- << "pcs" << 1;
+ StringRef StrRef;
+ if (!checkStringLiteralArgumentAttr(attr, 0, StrRef)) {
attr.setInvalid();
return true;
}
-
- StringRef StrRef = Str->getString();
if (StrRef == "aapcs") {
CC = CC_AAPCS;
break;
@@ -4121,18 +3964,18 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
if (Attr.isInvalid())
return true;
- if (Attr.getNumArgs() != 1) {
- Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ if (!checkAttributeNumArgs(*this, Attr, 1)) {
Attr.setInvalid();
return true;
}
- Expr *NumParamsExpr = Attr.getArg(0);
+ Expr *NumParamsExpr = Attr.getArgAsExpr(0);
llvm::APSInt NumParams(32);
if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() ||
!NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) {
- Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "regparm" << NumParamsExpr->getSourceRange();
+ Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << NumParamsExpr->getSourceRange();
Attr.setInvalid();
return true;
}
@@ -4170,24 +4013,26 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){
return;
}
- Expr *MaxThreadsExpr = Attr.getArg(0);
+ Expr *MaxThreadsExpr = Attr.getArgAsExpr(0);
llvm::APSInt MaxThreads(32);
if (MaxThreadsExpr->isTypeDependent() ||
MaxThreadsExpr->isValueDependent() ||
!MaxThreadsExpr->isIntegerConstantExpr(MaxThreads, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
- << "launch_bounds" << 1 << MaxThreadsExpr->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << 1 << AANT_ArgumentIntegerConstant
+ << MaxThreadsExpr->getSourceRange();
return;
}
llvm::APSInt MinBlocks(32);
if (Attr.getNumArgs() > 1) {
- Expr *MinBlocksExpr = Attr.getArg(1);
+ Expr *MinBlocksExpr = Attr.getArgAsExpr(1);
if (MinBlocksExpr->isTypeDependent() ||
MinBlocksExpr->isValueDependent() ||
!MinBlocksExpr->isIntegerConstantExpr(MinBlocks, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
- << "launch_bounds" << 2 << MinBlocksExpr->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << 2 << AANT_ArgumentIntegerConstant
+ << MinBlocksExpr->getSourceRange();
return;
}
}
@@ -4204,20 +4049,17 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){
static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- StringRef AttrName = Attr.getName()->getName();
- if (!Attr.getParameterName()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_identifier)
- << Attr.getName() << /* arg num = */ 1;
+ if (!Attr.isArgIdent(0)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier;
return;
}
-
- if (Attr.getNumArgs() != 2) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << /* required args = */ 3;
+
+ if (!checkAttributeNumArgs(S, Attr, 3))
return;
- }
- IdentifierInfo *ArgumentKind = Attr.getParameterName();
+ StringRef AttrName = Attr.getName()->getName();
+ IdentifierInfo *ArgumentKind = Attr.getArgAsIdent(0)->Ident;
if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
@@ -4228,13 +4070,13 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
uint64_t ArgumentIdx;
if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName,
Attr.getLoc(), 2,
- Attr.getArg(0), ArgumentIdx))
+ Attr.getArgAsExpr(1), ArgumentIdx))
return;
uint64_t TypeTagIdx;
if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName,
Attr.getLoc(), 3,
- Attr.getArg(1), TypeTagIdx))
+ Attr.getArgAsExpr(2), TypeTagIdx))
return;
bool IsPointer = (AttrName == "pointer_with_type_tag");
@@ -4243,7 +4085,7 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
QualType BufferTy = getFunctionOrMethodArgType(D, ArgumentIdx);
if (!BufferTy->isPointerType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
- << AttrName;
+ << Attr.getName();
}
}
@@ -4255,18 +4097,23 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- IdentifierInfo *PointerKind = Attr.getParameterName();
- if (!PointerKind) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_identifier)
- << "type_tag_for_datatype" << 1;
+ if (!Attr.isArgIdent(0)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << 1 << AANT_ArgumentIdentifier;
return;
}
+
+ if (!checkAttributeNumArgs(S, Attr, 1))
+ return;
- QualType MatchingCType = S.GetTypeFromParser(Attr.getMatchingCType(), NULL);
+ IdentifierInfo *PointerKind = Attr.getArgAsIdent(0)->Ident;
+ TypeSourceInfo *MatchingCTypeLoc = 0;
+ S.GetTypeFromParser(Attr.getMatchingCType(), &MatchingCTypeLoc);
+ assert(MatchingCTypeLoc && "no type source info for attribute argument");
D->addAttr(::new (S.Context)
TypeTagForDatatypeAttr(Attr.getRange(), S.Context, PointerKind,
- MatchingCType,
+ MatchingCTypeLoc,
Attr.getLayoutCompatible(),
Attr.getMustBeNull(),
Attr.getAttributeSpellingListIndex()));
@@ -4411,30 +4258,39 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
const AttributeList &attr) {
+ const int EP_ObjCMethod = 1;
+ const int EP_ObjCProperty = 2;
+
SourceLocation loc = attr.getLoc();
-
+ QualType resultType;
+
ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D);
if (!method) {
- S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << SourceRange(loc, loc) << attr.getName() << ExpectedMethod;
- return;
+ ObjCPropertyDecl *property = dyn_cast<ObjCPropertyDecl>(D);
+ if (!property) {
+ S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
+ << SourceRange(loc, loc) << attr.getName() << ExpectedMethodOrProperty;
+ return;
+ }
+ resultType = property->getType();
}
+ else
+ // Check that the method returns a normal pointer.
+ resultType = method->getResultType();
- // Check that the method returns a normal pointer.
- QualType resultType = method->getResultType();
-
if (!resultType->isReferenceType() &&
(!resultType->isPointerType() || resultType->isObjCRetainableType())) {
- S.Diag(method->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
+ S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
<< SourceRange(loc)
- << attr.getName() << /*method*/ 1 << /*non-retainable pointer*/ 2;
+ << attr.getName() << (method ? EP_ObjCMethod : EP_ObjCProperty)
+ << /*non-retainable pointer*/ 2;
// Drop the attribute.
return;
}
- method->addAttr(::new (S.Context)
+ D->addAttr(::new (S.Context)
ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context,
attr.getAttributeSpellingListIndex()));
}
@@ -4512,14 +4368,14 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D,
<< Attr.getRange() << Attr.getName() << ExpectedStruct;
}
- IdentifierInfo *ParmName = Attr.getParameterName();
+ IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0;
// In Objective-C, verify that the type names an Objective-C type.
// We don't want to check this outside of ObjC because people sometimes
// do crazy C declarations of Objective-C types.
- if (ParmName && S.getLangOpts().ObjC1) {
+ if (Parm && S.getLangOpts().ObjC1) {
// Check for an existing type with this name.
- LookupResult R(S, DeclarationName(ParmName), Attr.getParameterLoc(),
+ LookupResult R(S, DeclarationName(Parm->Ident), Parm->Loc,
Sema::LookupOrdinaryName);
if (S.LookupName(R, Sc)) {
NamedDecl *Target = R.getFoundDecl();
@@ -4531,7 +4387,32 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D,
}
D->addAttr(::new (S.Context)
- NSBridgedAttr(Attr.getRange(), S.Context, ParmName,
+ NSBridgedAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D,
+ const AttributeList &Attr) {
+ if (!isa<RecordDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName()
+ << (S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass
+ : ExpectedStructOrUnion);
+ return;
+ }
+
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id);
+ return;
+ }
+ IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0;
+ if (!Parm) {
+ S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id);
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ ObjCBridgeAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0,
Attr.getAttributeSpellingListIndex()));
}
@@ -4594,66 +4475,55 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
// Microsoft specific attribute handlers.
//===----------------------------------------------------------------------===//
-static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.MicrosoftExt || S.LangOpts.Borland) {
- // check the attribute arguments.
- if (!checkAttributeNumArgs(S, Attr, 1))
- return;
-
- Expr *Arg = Attr.getArg(0);
- StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
- if (!Str || !Str->isAscii()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
- << "uuid" << 1;
- return;
- }
+// Check if MS extensions or some other language extensions are enabled. If
+// not, issue a diagnostic that the given attribute is unused.
+static bool checkMicrosoftExt(Sema &S, const AttributeList &Attr,
+ bool OtherExtension = false) {
+ if (S.LangOpts.MicrosoftExt || OtherExtension)
+ return true;
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return false;
+}
- StringRef StrRef = Str->getString();
+static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (!checkMicrosoftExt(S, Attr, S.LangOpts.Borland))
+ return;
- bool IsCurly = StrRef.size() > 1 && StrRef.front() == '{' &&
- StrRef.back() == '}';
+ StringRef StrRef;
+ SourceLocation LiteralLoc;
+ if (!S.checkStringLiteralArgumentAttr(Attr, 0, StrRef, &LiteralLoc))
+ return;
- // Validate GUID length.
- if (IsCurly && StrRef.size() != 38) {
- S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
- return;
- }
- if (!IsCurly && StrRef.size() != 36) {
- S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
- return;
- }
+ // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or
+ // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}", normalize to the former.
+ if (StrRef.size() == 38 && StrRef.front() == '{' && StrRef.back() == '}')
+ StrRef = StrRef.drop_front().drop_back();
- // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or
- // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
- StringRef::iterator I = StrRef.begin();
- if (IsCurly) // Skip the optional '{'
- ++I;
+ // Validate GUID length.
+ if (StrRef.size() != 36) {
+ S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
+ return;
+ }
- for (int i = 0; i < 36; ++i) {
- if (i == 8 || i == 13 || i == 18 || i == 23) {
- if (*I != '-') {
- S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
- return;
- }
- } else if (!isHexDigit(*I)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
+ for (unsigned i = 0; i < 36; ++i) {
+ if (i == 8 || i == 13 || i == 18 || i == 23) {
+ if (StrRef[i] != '-') {
+ S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
return;
}
- I++;
+ } else if (!isHexDigit(StrRef[i])) {
+ S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
+ return;
}
+ }
- D->addAttr(::new (S.Context)
- UuidAttr(Attr.getRange(), S.Context, Str->getString(),
- Attr.getAttributeSpellingListIndex()));
- } else
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid";
+ D->addAttr(::new (S.Context) UuidAttr(Attr.getRange(), S.Context, StrRef,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!S.LangOpts.MicrosoftExt) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ if (!checkMicrosoftExt(S, Attr))
return;
- }
AttributeList::Kind Kind = Attr.getKind();
if (Kind == AttributeList::AT_SingleInheritance)
@@ -4674,50 +4544,78 @@ static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.MicrosoftExt) {
- AttributeList::Kind Kind = Attr.getKind();
- if (Kind == AttributeList::AT_Ptr32)
- D->addAttr(
- ::new (S.Context) Ptr32Attr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else if (Kind == AttributeList::AT_Ptr64)
- D->addAttr(
- ::new (S.Context) Ptr64Attr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else if (Kind == AttributeList::AT_Win64)
- D->addAttr(
- ::new (S.Context) Win64Attr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- } else
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ if (!checkMicrosoftExt(S, Attr))
+ return;
+
+ AttributeList::Kind Kind = Attr.getKind();
+ if (Kind == AttributeList::AT_Win64)
+ D->addAttr(
+ ::new (S.Context) Win64Attr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.MicrosoftExt)
- D->addAttr(::new (S.Context)
- ForceInlineAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ if (!checkMicrosoftExt(S, Attr))
+ return;
+ D->addAttr(::new (S.Context)
+ ForceInlineAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleSelectAnyAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (!checkMicrosoftExt(S, Attr))
+ return;
+ // Check linkage after possibly merging declaratinos. See
+ // checkAttributesAfterMerging().
+ D->addAttr(::new (S.Context)
+ SelectAnyAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+/// Handles semantic checking for features that are common to all attributes,
+/// such as checking whether a parameter was properly specified, or the correct
+/// number of arguments were passed, etc.
+static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D,
+ const AttributeList &Attr) {
+ // Several attributes carry different semantics than the parsing requires, so
+ // those are opted out of the common handling.
+ //
+ // We also bail on unknown and ignored attributes because those are handled
+ // as part of the target-specific handling logic.
+ if (Attr.hasCustomParsing() ||
+ Attr.getKind() == AttributeList::UnknownAttribute ||
+ Attr.getKind() == AttributeList::IgnoredAttribute)
+ return false;
+
+ // If there are no optional arguments, then checking for the argument count
+ // is trivial.
+ if (Attr.getMinArgs() == Attr.getMaxArgs() &&
+ !checkAttributeNumArgs(S, Attr, Attr.getMinArgs()))
+ return true;
+ return false;
}
//===----------------------------------------------------------------------===//
// Top Level Sema Entry Points
//===----------------------------------------------------------------------===//
-static void ProcessNonInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
- const AttributeList &Attr) {
- switch (Attr.getKind()) {
- case AttributeList::AT_CUDADevice: handleDeviceAttr (S, D, Attr); break;
- case AttributeList::AT_CUDAHost: handleHostAttr (S, D, Attr); break;
- case AttributeList::AT_Overloadable:handleOverloadableAttr(S, D, Attr); break;
- default:
- break;
- }
-}
+/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
+/// the attribute applies to decls. If the attribute is a type attribute, just
+/// silently ignore it if a GNU attribute.
+static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
+ const AttributeList &Attr,
+ bool IncludeCXX11Attributes) {
+ if (Attr.isInvalid())
+ return;
+
+ // Ignore C++11 attributes on declarator chunks: they appertain to the type
+ // instead.
+ if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes)
+ return;
+
+ if (handleCommonAttributeFeatures(S, scope, D, Attr))
+ return;
-static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
- const AttributeList &Attr) {
switch (Attr.getKind()) {
case AttributeList::AT_IBAction: handleIBAction(S, D, Attr); break;
case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break;
@@ -4728,15 +4626,13 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_VectorSize:
case AttributeList::AT_NeonVectorType:
case AttributeList::AT_NeonPolyVectorType:
+ case AttributeList::AT_Ptr32:
+ case AttributeList::AT_Ptr64:
+ case AttributeList::AT_SPtr:
+ case AttributeList::AT_UPtr:
// Ignore these, these are type attributes, handled by
// ProcessTypeAttributes.
break;
- case AttributeList::AT_CUDADevice:
- case AttributeList::AT_CUDAHost:
- case AttributeList::AT_Overloadable:
- // Ignore, this is a non-inheritable attribute, handled
- // by ProcessNonInheritableDeclAttr.
- break;
case AttributeList::AT_Alias: handleAliasAttr (S, D, Attr); break;
case AttributeList::AT_Aligned: handleAlignedAttr (S, D, Attr); break;
case AttributeList::AT_AllocSize: handleAllocSizeAttr (S, D, Attr); break;
@@ -4757,7 +4653,7 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
handleCXX11NoReturnAttr(S, D, Attr);
break;
case AttributeList::AT_Deprecated:
- handleAttrWithMessage<DeprecatedAttr>(S, D, Attr, "deprecated");
+ handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);
break;
case AttributeList::AT_Destructor: handleDestructorAttr (S, D, Attr); break;
case AttributeList::AT_ExtVectorType:
@@ -4769,15 +4665,18 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_Format: handleFormatAttr (S, D, Attr); break;
case AttributeList::AT_FormatArg: handleFormatArgAttr (S, D, Attr); break;
case AttributeList::AT_CUDAGlobal: handleGlobalAttr (S, D, Attr); break;
+ case AttributeList::AT_CUDADevice: handleDeviceAttr (S, D, Attr); break;
+ case AttributeList::AT_CUDAHost: handleHostAttr (S, D, Attr); break;
case AttributeList::AT_GNUInline: handleGNUInlineAttr (S, D, Attr); break;
case AttributeList::AT_CUDALaunchBounds:
handleLaunchBoundsAttr(S, D, Attr);
break;
- case AttributeList::AT_Mode: handleModeAttr (S, D, Attr); break;
case AttributeList::AT_Malloc: handleMallocAttr (S, D, Attr); break;
case AttributeList::AT_MayAlias: handleMayAliasAttr (S, D, Attr); break;
+ case AttributeList::AT_Mode: handleModeAttr (S, D, Attr); break;
case AttributeList::AT_NoCommon: handleNoCommonAttr (S, D, Attr); break;
case AttributeList::AT_NonNull: handleNonNullAttr (S, D, Attr); break;
+ case AttributeList::AT_Overloadable:handleOverloadableAttr(S, D, Attr); break;
case AttributeList::AT_ownership_returns:
case AttributeList::AT_ownership_takes:
case AttributeList::AT_ownership_holds:
@@ -4803,6 +4702,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_NSBridged:
handleNSBridgedAttr(S, scope, D, Attr); break;
+
+ case AttributeList::AT_ObjCBridge:
+ handleObjCBridgeAttr(S, scope, D, Attr); break;
case AttributeList::AT_CFAuditedTransfer:
case AttributeList::AT_CFUnknownTransfer:
@@ -4828,17 +4730,13 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_VecTypeHint:
handleVecTypeHint(S, D, Attr); break;
- case AttributeList::AT_Endian:
- handleEndianAttr(S, D, Attr);
- break;
-
case AttributeList::AT_InitPriority:
handleInitPriorityAttr(S, D, Attr); break;
case AttributeList::AT_Packed: handlePackedAttr (S, D, Attr); break;
case AttributeList::AT_Section: handleSectionAttr (S, D, Attr); break;
case AttributeList::AT_Unavailable:
- handleAttrWithMessage<UnavailableAttr>(S, D, Attr, "unavailable");
+ handleAttrWithMessage<UnavailableAttr>(S, D, Attr);
break;
case AttributeList::AT_ArcWeakrefUnavailable:
handleArcWeakrefUnavailableAttr (S, D, Attr);
@@ -4860,6 +4758,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_TypeVisibility:
handleVisibilityAttr(S, D, Attr, true);
break;
+ case AttributeList::AT_WarnUnused:
+ handleWarnUnusedAttr(S, D, Attr);
+ break;
case AttributeList::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, Attr);
break;
case AttributeList::AT_Weak: handleWeakAttr (S, D, Attr); break;
@@ -4909,7 +4810,6 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
break;
// Microsoft attributes:
- case AttributeList::AT_MsProperty: break;
case AttributeList::AT_MsStruct:
handleMsStructAttr(S, D, Attr);
break;
@@ -4922,15 +4822,22 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
handleInheritanceAttr(S, D, Attr);
break;
case AttributeList::AT_Win64:
- case AttributeList::AT_Ptr32:
- case AttributeList::AT_Ptr64:
handlePortabilityAttr(S, D, Attr);
break;
case AttributeList::AT_ForceInline:
handleForceInlineAttr(S, D, Attr);
break;
+ case AttributeList::AT_SelectAny:
+ handleSelectAnyAttr(S, D, Attr);
+ break;
// Thread safety attributes:
+ case AttributeList::AT_AssertExclusiveLock:
+ handleAssertExclusiveLockAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_AssertSharedLock:
+ handleAssertSharedLockAttr(S, D, Attr);
+ break;
case AttributeList::AT_GuardedVar:
handleGuardedVarAttr(S, D, Attr);
break;
@@ -4995,6 +4902,26 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
handleAcquiredAfterAttr(S, D, Attr);
break;
+ // Consumed analysis attributes.
+ case AttributeList::AT_Consumable:
+ handleConsumableAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_CallableWhen:
+ handleCallableWhenAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_ParamTypestate:
+ handleParamTypestateAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_ReturnTypestate:
+ handleReturnTypestateAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_SetTypestate:
+ handleSetTypestateAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_TestTypestate:
+ handleTestTypestateAttr(S, D, Attr);
+ break;
+
// Type safety attributes.
case AttributeList::AT_ArgumentWithTypeTag:
handleArgumentWithTypeTagAttr(S, D, Attr);
@@ -5014,42 +4941,18 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
}
}
-/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
-/// the attribute applies to decls. If the attribute is a type attribute, just
-/// silently ignore it if a GNU attribute.
-static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
- const AttributeList &Attr,
- bool NonInheritable, bool Inheritable,
- bool IncludeCXX11Attributes) {
- if (Attr.isInvalid())
- return;
-
- // Ignore C++11 attributes on declarator chunks: they appertain to the type
- // instead.
- if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes)
- return;
-
- if (NonInheritable)
- ProcessNonInheritableDeclAttr(S, scope, D, Attr);
-
- if (Inheritable)
- ProcessInheritableDeclAttr(S, scope, D, Attr);
-}
-
/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
/// attribute list to the specified decl, ignoring any type attributes.
void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
const AttributeList *AttrList,
- bool NonInheritable, bool Inheritable,
bool IncludeCXX11Attributes) {
for (const AttributeList* l = AttrList; l; l = l->getNext())
- ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable,
- IncludeCXX11Attributes);
+ ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes);
// GCC accepts
// static int a9 __attribute__((weakref));
// but that looks really pointless. We reject it.
- if (Inheritable && D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
+ if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) <<
cast<NamedDecl>(D)->getNameAsString();
D->dropAttr<WeakRefAttr>();
@@ -5202,11 +5105,10 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {
/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
/// it, apply them to D. This is a bit tricky because PD can have attributes
/// specified in many different places, and we need to find and apply them all.
-void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD,
- bool NonInheritable, bool Inheritable) {
+void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
// Apply decl attributes from the DeclSpec if present.
if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList())
- ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable);
+ ProcessDeclAttributeList(S, D, Attrs);
// Walk the declarator structure, applying decl attributes that were in a type
// position to the decl itself. This handles cases like:
@@ -5214,12 +5116,11 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD,
// when X is a decl attribute.
for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
- ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable,
- /*IncludeCXX11Attributes=*/false);
+ ProcessDeclAttributeList(S, D, Attrs, /*IncludeCXX11Attributes=*/false);
// Finally, apply any attributes on the decl itself.
if (const AttributeList *Attrs = PD.getAttributes())
- ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable);
+ ProcessDeclAttributeList(S, D, Attrs);
}
/// Is the given declaration allowed to use a forbidden type?
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
index e6a131a0761c..6b3400adac6e 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
@@ -14,6 +14,7 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
@@ -27,6 +28,7 @@
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/DeclSpec.h"
@@ -339,9 +341,7 @@ void Sema::ActOnParamUnparsedDefaultArgument(Decl *param,
return;
ParmVarDecl *Param = cast<ParmVarDecl>(param);
- if (Param)
- Param->setUnparsedDefaultArg();
-
+ Param->setUnparsedDefaultArg();
UnparsedDefaultArgLocs[Param] = ArgLoc;
}
@@ -352,9 +352,7 @@ void Sema::ActOnParamDefaultArgumentError(Decl *param) {
return;
ParmVarDecl *Param = cast<ParmVarDecl>(param);
-
Param->setInvalidDecl();
-
UnparsedDefaultArgLocs.erase(Param);
}
@@ -404,6 +402,17 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
}
}
+static bool functionDeclHasDefaultArgument(const FunctionDecl *FD) {
+ for (unsigned NumParams = FD->getNumParams(); NumParams > 0; --NumParams) {
+ const ParmVarDecl *PVD = FD->getParamDecl(NumParams-1);
+ if (!PVD->hasDefaultArg())
+ return false;
+ if (!PVD->hasInheritedDefaultArg())
+ return true;
+ }
+ return false;
+}
+
/// MergeCXXFunctionDecl - Merge two declarations of the same C++
/// function, once we already know that they have the same
/// type. Subroutine of MergeFunctionDecl. Returns true if there was an
@@ -426,9 +435,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
// declaration (not even to the same value).
//
// C++ [dcl.fct.default]p6:
- // Except for member functions of class templates, the default arguments
- // in a member function definition that appears outside of the class
- // definition are added to the set of default arguments provided by the
+ // Except for member functions of class templates, the default arguments
+ // in a member function definition that appears outside of the class
+ // definition are added to the set of default arguments provided by the
// member function declaration in the class definition.
for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) {
ParmVarDecl *OldParam = Old->getParamDecl(p);
@@ -438,9 +447,18 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
bool NewParamHasDfl = NewParam->hasDefaultArg();
NamedDecl *ND = Old;
- if (S && !isDeclInScope(ND, New->getDeclContext(), S))
+
+ // The declaration context corresponding to the scope is the semantic
+ // parent, unless this is a local function declaration, in which case
+ // it is that surrounding function.
+ DeclContext *ScopeDC = New->getLexicalDeclContext();
+ if (!ScopeDC->isFunctionOrMethod())
+ ScopeDC = New->getDeclContext();
+ if (S && !isDeclInScope(ND, ScopeDC, S) &&
+ !New->getDeclContext()->isRecord())
// Ignore default parameters of old decl if they are not in
- // the same scope.
+ // the same scope and this is not an out-of-line definition of
+ // a member function.
OldParamHasDfl = false;
if (OldParamHasDfl && NewParamHasDfl) {
@@ -578,6 +596,17 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
Invalid = true;
}
+ // C++11 [dcl.fct.default]p4: If a friend declaration specifies a default
+ // argument expression, that declaration shall be a definition and shall be
+ // the only declaration of the function or function template in the
+ // translation unit.
+ if (Old->getFriendObjectKind() == Decl::FOK_Undeclared &&
+ functionDeclHasDefaultArgument(Old)) {
+ Diag(New->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ Invalid = true;
+ }
+
if (CheckEquivalentExceptionSpec(Old, New))
Invalid = true;
@@ -851,7 +880,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
diag::err_constexpr_local_var_non_literal_type,
isa<CXXConstructorDecl>(Dcl)))
return false;
- if (!VD->hasInit()) {
+ if (!VD->hasInit() && !VD->isCXXForRangeDecl()) {
SemaRef.Diag(VD->getLocation(),
diag::err_constexpr_local_var_no_init)
<< isa<CXXConstructorDecl>(Dcl);
@@ -897,6 +926,9 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef,
FieldDecl *Field,
llvm::SmallSet<Decl*, 16> &Inits,
bool &Diagnosed) {
+ if (Field->isInvalidDecl())
+ return;
+
if (Field->isUnnamedBitfield())
return;
@@ -925,7 +957,7 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef,
/// definition.
static bool
CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
- llvm::SmallVectorImpl<SourceLocation> &ReturnStmts,
+ SmallVectorImpl<SourceLocation> &ReturnStmts,
SourceLocation &Cxx1yLoc) {
// - its function-body shall be [...] a compound-statement that contains only
switch (S->getStmtClass()) {
@@ -1192,8 +1224,33 @@ bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
if (CurDecl && CurDecl->getIdentifier())
return &II == CurDecl->getIdentifier();
- else
+ return false;
+}
+
+/// \brief Determine whether the identifier II is a typo for the name of
+/// the class type currently being defined. If so, update it to the identifier
+/// that should have been used.
+bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) {
+ assert(getLangOpts().CPlusPlus && "No class names in C!");
+
+ if (!getLangOpts().SpellChecking)
return false;
+
+ CXXRecordDecl *CurDecl;
+ if (SS && SS->isSet() && !SS->isInvalid()) {
+ DeclContext *DC = computeDeclContext(*SS, true);
+ CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC);
+ } else
+ CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
+
+ if (CurDecl && CurDecl->getIdentifier() && II != CurDecl->getIdentifier() &&
+ 3 * II->getName().edit_distance(CurDecl->getIdentifier()->getName())
+ < II->getLength()) {
+ II = CurDecl->getIdentifier();
+ return true;
+ }
+
+ return false;
}
/// \brief Determine whether the given class is a base class of the given
@@ -1224,8 +1281,7 @@ static bool findCircularInheritance(const CXXRecordDecl *Class,
if (Queue.empty())
return false;
- Current = Queue.back();
- Queue.pop_back();
+ Current = Queue.pop_back_val();
}
return false;
@@ -1311,15 +1367,28 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
assert(BaseDecl && "Record type has no declaration");
BaseDecl = BaseDecl->getDefinition();
assert(BaseDecl && "Base type is not incomplete, but has no definition");
- CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
+ CXXRecordDecl *CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
assert(CXXBaseDecl && "Base type is not a C++ type");
+ // A class which contains a flexible array member is not suitable for use as a
+ // base class:
+ // - If the layout determines that a base comes before another base,
+ // the flexible array member would index into the subsequent base.
+ // - If the layout determines that base comes before the derived class,
+ // the flexible array member would index into the derived class.
+ if (CXXBaseDecl->hasFlexibleArrayMember()) {
+ Diag(BaseLoc, diag::err_base_class_has_flexible_array_member)
+ << CXXBaseDecl->getDeclName();
+ return 0;
+ }
+
// C++ [class]p3:
- // If a class is marked final and it appears as a base-type-specifier in
+ // 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();
+ if (FinalAttr *FA = CXXBaseDecl->getAttr<FinalAttr>()) {
+ Diag(BaseLoc, diag::err_class_marked_final_used_as_base)
+ << CXXBaseDecl->getDeclName()
+ << FA->isSpelledAsSealed();
Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl)
<< CXXBaseDecl->getDeclName();
return 0;
@@ -1327,7 +1396,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
if (BaseDecl->isInvalidDecl())
Class->setInvalidDecl();
-
+
// Create the base specifier.
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
Class->getTagKind() == TTK_Class,
@@ -1465,8 +1534,7 @@ void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases,
return;
AdjustDeclIfTemplate(ClassDecl);
- AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl),
- (CXXBaseSpecifier**)(Bases), NumBases);
+ AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases, NumBases);
}
/// \brief Determine whether the type \p Derived is a C++ class that is
@@ -1590,26 +1658,28 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
return false;
}
- // We know that the derived-to-base conversion is ambiguous, and
- // we're going to produce a diagnostic. Perform the derived-to-base
- // search just one more time to compute all of the possible paths so
- // that we can print them out. This is more expensive than any of
- // the previous derived-to-base checks we've done, but at this point
- // performance isn't as much of an issue.
- Paths.clear();
- Paths.setRecordingPaths(true);
- bool StillOkay = IsDerivedFrom(Derived, Base, Paths);
- assert(StillOkay && "Can only be used with a derived-to-base conversion");
- (void)StillOkay;
-
- // Build up a textual representation of the ambiguous paths, e.g.,
- // D -> B -> A, that will be used to illustrate the ambiguous
- // conversions in the diagnostic. We only print one of the paths
- // to each base class subobject.
- std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
-
- Diag(Loc, AmbigiousBaseConvID)
- << Derived << Base << PathDisplayStr << Range << Name;
+ if (AmbigiousBaseConvID) {
+ // We know that the derived-to-base conversion is ambiguous, and
+ // we're going to produce a diagnostic. Perform the derived-to-base
+ // search just one more time to compute all of the possible paths so
+ // that we can print them out. This is more expensive than any of
+ // the previous derived-to-base checks we've done, but at this point
+ // performance isn't as much of an issue.
+ Paths.clear();
+ Paths.setRecordingPaths(true);
+ bool StillOkay = IsDerivedFrom(Derived, Base, Paths);
+ assert(StillOkay && "Can only be used with a derived-to-base conversion");
+ (void)StillOkay;
+
+ // Build up a textual representation of the ambiguous paths, e.g.,
+ // D -> B -> A, that will be used to illustrate the ambiguous
+ // conversions in the diagnostic. We only print one of the paths
+ // to each base class subobject.
+ std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
+
+ Diag(Loc, AmbigiousBaseConvID)
+ << Derived << Base << PathDisplayStr << Range << Name;
+ }
return true;
}
@@ -1675,37 +1745,63 @@ bool Sema::ActOnAccessSpecifier(AccessSpecifier Access,
}
/// CheckOverrideControl - Check C++11 override control semantics.
-void Sema::CheckOverrideControl(Decl *D) {
+void Sema::CheckOverrideControl(NamedDecl *D) {
if (D->isInvalidDecl())
return;
- const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D);
+ // We only care about "override" and "final" declarations.
+ if (!D->hasAttr<OverrideAttr>() && !D->hasAttr<FinalAttr>())
+ return;
- // Do we know which functions this declaration might be overriding?
- bool OverridesAreKnown = !MD ||
- (!MD->getParent()->hasAnyDependentBases() &&
- !MD->getType()->isDependentType());
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D);
- if (!MD || !MD->isVirtual()) {
- if (OverridesAreKnown) {
+ // We can't check dependent instance methods.
+ if (MD && MD->isInstance() &&
+ (MD->getParent()->hasAnyDependentBases() ||
+ MD->getType()->isDependentType()))
+ return;
+
+ if (MD && !MD->isVirtual()) {
+ // If we have a non-virtual method, check if if hides a virtual method.
+ // (In that case, it's most likely the method has the wrong type.)
+ SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
+ FindHiddenVirtualMethods(MD, OverloadedMethods);
+
+ if (!OverloadedMethods.empty()) {
if (OverrideAttr *OA = D->getAttr<OverrideAttr>()) {
Diag(OA->getLocation(),
- diag::override_keyword_only_allowed_on_virtual_member_functions)
- << "override" << FixItHint::CreateRemoval(OA->getLocation());
- D->dropAttr<OverrideAttr>();
- }
- if (FinalAttr *FA = D->getAttr<FinalAttr>()) {
+ diag::override_keyword_hides_virtual_member_function)
+ << "override" << (OverloadedMethods.size() > 1);
+ } else if (FinalAttr *FA = D->getAttr<FinalAttr>()) {
Diag(FA->getLocation(),
- diag::override_keyword_only_allowed_on_virtual_member_functions)
- << "final" << FixItHint::CreateRemoval(FA->getLocation());
- D->dropAttr<FinalAttr>();
+ diag::override_keyword_hides_virtual_member_function)
+ << (FA->isSpelledAsSealed() ? "sealed" : "final")
+ << (OverloadedMethods.size() > 1);
}
+ NoteHiddenVirtualMethods(MD, OverloadedMethods);
+ MD->setInvalidDecl();
+ return;
}
- return;
+ // Fall through into the general case diagnostic.
+ // FIXME: We might want to attempt typo correction here.
}
- if (!OverridesAreKnown)
+ if (!MD || !MD->isVirtual()) {
+ if (OverrideAttr *OA = D->getAttr<OverrideAttr>()) {
+ Diag(OA->getLocation(),
+ diag::override_keyword_only_allowed_on_virtual_member_functions)
+ << "override" << FixItHint::CreateRemoval(OA->getLocation());
+ D->dropAttr<OverrideAttr>();
+ }
+ if (FinalAttr *FA = D->getAttr<FinalAttr>()) {
+ Diag(FA->getLocation(),
+ diag::override_keyword_only_allowed_on_virtual_member_functions)
+ << (FA->isSpelledAsSealed() ? "sealed" : "final")
+ << FixItHint::CreateRemoval(FA->getLocation());
+ D->dropAttr<FinalAttr>();
+ }
return;
+ }
// C++11 [class.virtual]p5:
// If a virtual function is marked with the virt-specifier override and
@@ -1723,11 +1819,13 @@ void Sema::CheckOverrideControl(Decl *D) {
/// C++11 [class.virtual]p4.
bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
const CXXMethodDecl *Old) {
- if (!Old->hasAttr<FinalAttr>())
+ FinalAttr *FA = Old->getAttr<FinalAttr>();
+ if (!FA)
return false;
Diag(New->getLocation(), diag::err_final_function_overridden)
- << New->getDeclName();
+ << New->getDeclName()
+ << FA->isSpelledAsSealed();
Diag(Old->getLocation(), diag::note_overridden_virtual_function);
return true;
}
@@ -1933,19 +2031,20 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
if (MSPropertyAttr) {
Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D,
BitWidth, InitStyle, AS, MSPropertyAttr);
+ if (!Member)
+ return 0;
isInstField = false;
} else {
Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D,
BitWidth, InitStyle, AS);
+ assert(Member && "HandleField never returns null");
}
- assert(Member && "HandleField never returns null");
} else {
assert(InitStyle == ICIS_NoInit || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static);
Member = HandleDeclarator(S, D, TemplateParameterLists);
- if (!Member) {
+ if (!Member)
return 0;
- }
// Non-instance-fields can't have a bitfield.
if (BitWidth) {
@@ -1974,16 +2073,19 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Member->setAccess(AS);
- // If we have declared a member function template, set the access of the
- // templated declaration as well.
+ // If we have declared a member function template or static data member
+ // template, set the access of the templated declaration as well.
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
FunTmpl->getTemplatedDecl()->setAccess(AS);
+ else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
+ VarTmpl->getTemplatedDecl()->setAccess(AS);
}
if (VS.isOverrideSpecified())
Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context));
if (VS.isFinalSpecified())
- Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context));
+ Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context,
+ VS.isFinalSpelledSealed()));
if (VS.getLastLocation().isValid()) {
// Update the end location of a method that has a virt-specifiers.
@@ -2020,57 +2122,71 @@ namespace {
class UninitializedFieldVisitor
: public EvaluatedExprVisitor<UninitializedFieldVisitor> {
Sema &S;
- ValueDecl *VD;
+ // List of Decls to generate a warning on. Also remove Decls that become
+ // initialized.
+ llvm::SmallPtrSet<ValueDecl*, 4> &Decls;
+ // If non-null, add a note to the warning pointing back to the constructor.
+ const CXXConstructorDecl *Constructor;
public:
typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited;
- UninitializedFieldVisitor(Sema &S, ValueDecl *VD) : Inherited(S.Context),
- S(S) {
- if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(VD))
- this->VD = IFD->getAnonField();
- else
- this->VD = VD;
- }
-
- void HandleExpr(Expr *E) {
- if (!E) return;
+ UninitializedFieldVisitor(Sema &S,
+ llvm::SmallPtrSet<ValueDecl*, 4> &Decls,
+ const CXXConstructorDecl *Constructor)
+ : Inherited(S.Context), S(S), Decls(Decls),
+ Constructor(Constructor) { }
+
+ void HandleMemberExpr(MemberExpr *ME, bool CheckReferenceOnly) {
+ if (isa<EnumConstantDecl>(ME->getMemberDecl()))
+ return;
- // Expressions like x(x) sometimes lack the surrounding expressions
- // but need to be checked anyways.
- HandleValue(E);
- Visit(E);
- }
+ // FieldME is the inner-most MemberExpr that is not an anonymous struct
+ // or union.
+ MemberExpr *FieldME = ME;
- void HandleValue(Expr *E) {
- E = E->IgnoreParens();
+ Expr *Base = ME;
+ while (isa<MemberExpr>(Base)) {
+ ME = cast<MemberExpr>(Base);
- if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
- if (isa<EnumConstantDecl>(ME->getMemberDecl()))
+ if (isa<VarDecl>(ME->getMemberDecl()))
return;
- // FieldME is the inner-most MemberExpr that is not an anonymous struct
- // or union.
- MemberExpr *FieldME = ME;
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
+ if (!FD->isAnonymousStructOrUnion())
+ FieldME = ME;
- Expr *Base = E;
- while (isa<MemberExpr>(Base)) {
- ME = cast<MemberExpr>(Base);
+ Base = ME->getBase();
+ }
- if (isa<VarDecl>(ME->getMemberDecl()))
- return;
+ if (!isa<CXXThisExpr>(Base))
+ return;
- if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
- if (!FD->isAnonymousStructOrUnion())
- FieldME = ME;
+ ValueDecl* FoundVD = FieldME->getMemberDecl();
- Base = ME->getBase();
- }
+ if (!Decls.count(FoundVD))
+ return;
- if (VD == FieldME->getMemberDecl() && isa<CXXThisExpr>(Base)) {
- unsigned diag = VD->getType()->isReferenceType()
- ? diag::warn_reference_field_is_uninit
- : diag::warn_field_is_uninit;
- S.Diag(FieldME->getExprLoc(), diag) << VD;
- }
+ const bool IsReference = FoundVD->getType()->isReferenceType();
+
+ // Prevent double warnings on use of unbounded references.
+ if (IsReference != CheckReferenceOnly)
+ return;
+
+ unsigned diag = IsReference
+ ? diag::warn_reference_field_is_uninit
+ : diag::warn_field_is_uninit;
+ S.Diag(FieldME->getExprLoc(), diag) << FoundVD;
+ if (Constructor)
+ S.Diag(Constructor->getLocation(),
+ diag::note_uninit_in_this_constructor)
+ << (Constructor->isDefaultConstructor() && Constructor->isImplicit());
+
+ }
+
+ void HandleValue(Expr *E) {
+ E = E->IgnoreParens();
+
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ HandleMemberExpr(ME, false /*CheckReferenceOnly*/);
return;
}
@@ -2102,6 +2218,13 @@ namespace {
}
}
+ void VisitMemberExpr(MemberExpr *ME) {
+ // All uses of unbounded reference fields will warn.
+ HandleMemberExpr(ME, true /*CheckReferenceOnly*/);
+
+ Inherited::VisitMemberExpr(ME);
+ }
+
void VisitImplicitCastExpr(ImplicitCastExpr *E) {
if (E->getCastKind() == CK_LValueToRValue)
HandleValue(E->getSubExpr());
@@ -2109,6 +2232,16 @@ namespace {
Inherited::VisitImplicitCastExpr(E);
}
+ void VisitCXXConstructExpr(CXXConstructExpr *E) {
+ if (E->getConstructor()->isCopyConstructor())
+ if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(E->getArg(0)))
+ if (ICE->getCastKind() == CK_NoOp)
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(ICE->getSubExpr()))
+ HandleMemberExpr(ME, false /*CheckReferenceOnly*/);
+
+ Inherited::VisitCXXConstructExpr(E);
+ }
+
void VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
Expr *Callee = E->getCallee();
if (isa<MemberExpr>(Callee))
@@ -2116,10 +2249,85 @@ namespace {
Inherited::VisitCXXMemberCallExpr(E);
}
+
+ void VisitBinaryOperator(BinaryOperator *E) {
+ // If a field assignment is detected, remove the field from the
+ // uninitiailized field set.
+ if (E->getOpcode() == BO_Assign)
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(E->getLHS()))
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
+ if (!FD->getType()->isReferenceType())
+ Decls.erase(FD);
+
+ Inherited::VisitBinaryOperator(E);
+ }
};
- static void CheckInitExprContainsUninitializedFields(Sema &S, Expr *E,
- ValueDecl *VD) {
- UninitializedFieldVisitor(S, VD).HandleExpr(E);
+ static void CheckInitExprContainsUninitializedFields(
+ Sema &S, Expr *E, llvm::SmallPtrSet<ValueDecl*, 4> &Decls,
+ const CXXConstructorDecl *Constructor) {
+ if (Decls.size() == 0)
+ return;
+
+ if (!E)
+ return;
+
+ if (CXXDefaultInitExpr *Default = dyn_cast<CXXDefaultInitExpr>(E)) {
+ E = Default->getExpr();
+ if (!E)
+ return;
+ // In class initializers will point to the constructor.
+ UninitializedFieldVisitor(S, Decls, Constructor).Visit(E);
+ } else {
+ UninitializedFieldVisitor(S, Decls, 0).Visit(E);
+ }
+ }
+
+ // Diagnose value-uses of fields to initialize themselves, e.g.
+ // foo(foo)
+ // where foo is not also a parameter to the constructor.
+ // Also diagnose across field uninitialized use such as
+ // x(y), y(x)
+ // TODO: implement -Wuninitialized and fold this into that framework.
+ static void DiagnoseUninitializedFields(
+ Sema &SemaRef, const CXXConstructorDecl *Constructor) {
+
+ if (SemaRef.getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit,
+ Constructor->getLocation())
+ == DiagnosticsEngine::Ignored) {
+ return;
+ }
+
+ if (Constructor->isInvalidDecl())
+ return;
+
+ const CXXRecordDecl *RD = Constructor->getParent();
+
+ // Holds fields that are uninitialized.
+ llvm::SmallPtrSet<ValueDecl*, 4> UninitializedFields;
+
+ // At the beginning, all fields are uninitialized.
+ for (DeclContext::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
+ I != E; ++I) {
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(*I)) {
+ UninitializedFields.insert(FD);
+ } else if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(*I)) {
+ UninitializedFields.insert(IFD->getAnonField());
+ }
+ }
+
+ for (CXXConstructorDecl::init_const_iterator FieldInit =
+ Constructor->init_begin(),
+ FieldInitEnd = Constructor->init_end();
+ FieldInit != FieldInitEnd; ++FieldInit) {
+
+ Expr *InitExpr = (*FieldInit)->getInit();
+
+ CheckInitExprContainsUninitializedFields(
+ SemaRef, InitExpr, UninitializedFields, Constructor);
+
+ if (FieldDecl *Field = (*FieldInit)->getAnyMember())
+ UninitializedFields.erase(Field);
+ }
}
} // namespace
@@ -2146,17 +2354,8 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc,
return;
}
- if (getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit, InitLoc)
- != DiagnosticsEngine::Ignored) {
- CheckInitExprContainsUninitializedFields(*this, InitExpr, FD);
- }
-
ExprResult Init = InitExpr;
if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
- if (isa<InitListExpr>(InitExpr) && isStdInitializerList(FD->getType(), 0)) {
- Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list)
- << /*at end of ctor*/1 << InitExpr->getSourceRange();
- }
InitializedEntity Entity = InitializedEntity::InitializeMember(FD);
InitializationKind Kind = FD->getInClassInitStyle() == ICIS_ListInit
? InitializationKind::CreateDirectList(InitExpr->getLocStart())
@@ -2254,12 +2453,11 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
const DeclSpec &DS,
SourceLocation IdLoc,
SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RParenLoc,
SourceLocation EllipsisLoc) {
Expr *List = new (Context) ParenListExpr(Context, LParenLoc,
- llvm::makeArrayRef(Args, NumArgs),
- RParenLoc);
+ Args, RParenLoc);
return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
DS, IdLoc, List, EllipsisLoc);
}
@@ -2269,21 +2467,20 @@ namespace {
// Callback to only accept typo corrections that can be a valid C++ member
// intializer: either a non-static field member or a base class.
class MemInitializerValidatorCCC : public CorrectionCandidateCallback {
- public:
+public:
explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl)
: ClassDecl(ClassDecl) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) LLVM_OVERRIDE {
if (NamedDecl *ND = candidate.getCorrectionDecl()) {
if (FieldDecl *Member = dyn_cast<FieldDecl>(ND))
return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl);
- else
- return isa<TypeDecl>(ND);
+ return isa<TypeDecl>(ND);
}
return false;
}
- private:
+private:
CXXRecordDecl *ClassDecl;
};
@@ -2389,18 +2586,13 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
if (R.empty() && BaseType.isNull() &&
(Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
Validator, ClassDecl))) {
- std::string CorrectedStr(Corr.getAsString(getLangOpts()));
- std::string CorrectedQuotedStr(Corr.getQuoted(getLangOpts()));
if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {
// We have found a non-static data member with a similar
// name to what was typed; complain and initialize that
// member.
- Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
- << MemberOrBase << true << CorrectedQuotedStr
- << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
- Diag(Member->getLocation(), diag::note_previous_decl)
- << CorrectedQuotedStr;
-
+ diagnoseTypo(Corr,
+ PDiag(diag::err_mem_init_not_member_or_class_suggest)
+ << MemberOrBase << true);
return BuildMemberInitializer(Member, Init, IdLoc);
} else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) {
const CXXBaseSpecifier *DirectBaseSpec;
@@ -2411,12 +2603,13 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
// We have found a direct or virtual base class with a
// similar name to what was typed; complain and initialize
// that base class.
- Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
- << MemberOrBase << false << CorrectedQuotedStr
- << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
+ diagnoseTypo(Corr,
+ PDiag(diag::err_mem_init_not_member_or_class_suggest)
+ << MemberOrBase << false,
+ PDiag() /*Suppress note, we provide our own.*/);
- const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec
- : VirtualBaseSpec;
+ const CXXBaseSpecifier *BaseSpec = DirectBaseSpec ? DirectBaseSpec
+ : VirtualBaseSpec;
Diag(BaseSpec->getLocStart(),
diag::note_base_class_specified_here)
<< BaseSpec->getType()
@@ -2480,15 +2673,7 @@ static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member,
}
}
- if (isa<MaterializeTemporaryExpr>(Init->IgnoreParens())) {
- // Taking the address of a temporary will be diagnosed as a hard error.
- if (IsPointer)
- return;
-
- S.Diag(Init->getExprLoc(), diag::warn_bind_ref_member_to_temporary)
- << Member << Init->getSourceRange();
- } else if (const DeclRefExpr *DRE
- = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) {
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) {
// We only warn when referring to a non-reference parameter declaration.
const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl());
if (!Parameter || Parameter->getType()->isReferenceType())
@@ -2521,10 +2706,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
if (Member->isInvalidDecl())
return true;
- // Diagnose value-uses of fields to initialize themselves, e.g.
- // foo(foo)
- // where foo is not also a parameter to the constructor.
- // TODO: implement -Wuninitialized and fold this into that framework.
MultiExprArg Args;
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs());
@@ -2535,19 +2716,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
Args = Init;
}
- if (getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit, IdLoc)
- != DiagnosticsEngine::Ignored)
- for (unsigned i = 0, e = Args.size(); i != e; ++i)
- // FIXME: Warn about the case when other fields are used before being
- // initialized. For example, let this field be the i'th field. When
- // initializing the i'th field, throw a warning if any of the >= i'th
- // fields are used, as they are not yet initialized.
- // Right now we are only handling the case where the i'th field uses
- // itself in its initializer.
- // Also need to take into account that some fields may be initialized by
- // in-class initializers, see C++11 [class.base.init]p9.
- CheckInitExprContainsUninitializedFields(*this, Args[i], Member);
-
SourceRange InitRange = Init->getSourceRange();
if (Member->getType()->isDependentType() || Init->isTypeDependent()) {
@@ -2559,11 +2727,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
if (isa<InitListExpr>(Init)) {
InitList = true;
Args = Init;
-
- if (isStdInitializerList(Member->getType(), 0)) {
- Diag(IdLoc, diag::warn_dangling_std_initializer_list)
- << /*at end of ctor*/1 << InitRange;
- }
}
// Initialize the member.
@@ -2580,6 +2743,8 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
if (MemberInit.isInvalid())
return true;
+ CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(), IdLoc);
+
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
@@ -2588,7 +2753,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
return true;
Init = MemberInit.get();
- CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc);
}
if (DirectMember) {
@@ -2742,9 +2906,9 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
<< BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
- CXXBaseSpecifier *BaseSpec = const_cast<CXXBaseSpecifier *>(DirectBaseSpec);
+ const CXXBaseSpecifier *BaseSpec = DirectBaseSpec;
if (!BaseSpec)
- BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec);
+ BaseSpec = VirtualBaseSpec;
// Initialize the base.
bool InitList = true;
@@ -3228,6 +3392,8 @@ static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
FieldDecl *Field,
IndirectFieldDecl *Indirect = 0) {
+ if (Field->isInvalidDecl())
+ return false;
// Overwhelmingly common case: we have a direct initializer for this field.
if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(Field))
@@ -3266,7 +3432,7 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
// Don't try to build an implicit initializer if there were semantic
// errors in any of the initializers (and therefore we might be
// missing some that the user actually wrote).
- if (Info.AnyErrorsInInits || Field->isInvalidDecl())
+ if (Info.AnyErrorsInInits)
return false;
CXXCtorInitializer *Init = 0;
@@ -3333,7 +3499,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
for (unsigned i = 0; i < Initializers.size(); i++) {
CXXCtorInitializer *Member = Initializers[i];
-
+
if (Member->isBaseInitializer())
Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
else
@@ -3354,12 +3520,28 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
if (CXXCtorInitializer *Value
= Info.AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
+ // [class.base.init]p7, per DR257:
+ // A mem-initializer where the mem-initializer-id names a virtual base
+ // class is ignored during execution of a constructor of any class that
+ // is not the most derived class.
+ if (ClassDecl->isAbstract()) {
+ // FIXME: Provide a fixit to remove the base specifier. This requires
+ // tracking the location of the associated comma for a base specifier.
+ Diag(Value->getSourceLocation(), diag::warn_abstract_vbase_init_ignored)
+ << VBase->getType() << ClassDecl;
+ DiagnoseAbstractType(ClassDecl);
+ }
+
Info.AllToInit.push_back(Value);
- } else if (!AnyErrors) {
+ } else if (!AnyErrors && !ClassDecl->isAbstract()) {
+ // [class.base.init]p8, per DR257:
+ // If a given [...] base class is not named by a mem-initializer-id
+ // [...] and the entity is not a virtual base class of an abstract
+ // class, then [...] the entity is default-initialized.
bool IsInheritedVirtualBase = !DirectVBases.count(VBase);
CXXCtorInitializer *CXXBaseInit;
if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
- VBase, IsInheritedVirtualBase,
+ VBase, IsInheritedVirtualBase,
CXXBaseInit)) {
HadError = true;
continue;
@@ -3465,12 +3647,12 @@ static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*>
IdealInits.push_back(Field);
}
-static void *GetKeyForBase(ASTContext &Context, QualType BaseType) {
- return const_cast<Type*>(Context.getCanonicalType(BaseType).getTypePtr());
+static const void *GetKeyForBase(ASTContext &Context, QualType BaseType) {
+ return Context.getCanonicalType(BaseType).getTypePtr();
}
-static void *GetKeyForMember(ASTContext &Context,
- CXXCtorInitializer *Member) {
+static const void *GetKeyForMember(ASTContext &Context,
+ CXXCtorInitializer *Member) {
if (!Member->isAnyMemberInitializer())
return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0));
@@ -3534,7 +3716,7 @@ static void DiagnoseBaseOrMemInitializerOrder(
CXXCtorInitializer *PrevInit = 0;
for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) {
CXXCtorInitializer *Init = Inits[InitIndex];
- void *InitKey = GetKeyForMember(SemaRef.Context, Init);
+ const void *InitKey = GetKeyForMember(SemaRef.Context, Init);
// Scan forward to try to find this initializer in the idealized
// initializers list.
@@ -3660,7 +3842,7 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
// Mapping for the duplicate initializers check.
// For member initializers, this is keyed with a FieldDecl*.
// For base initializers, this is keyed with a Type*.
- llvm::DenseMap<void*, CXXCtorInitializer *> Members;
+ llvm::DenseMap<const void *, CXXCtorInitializer *> Members;
// Mapping for the inconsistent anonymous-union initializers check.
RedundantUnionMap MemberUnions;
@@ -3678,7 +3860,8 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
CheckRedundantUnionInit(*this, Init, MemberUnions))
HadError = true;
} else if (Init->isBaseInitializer()) {
- void *Key = GetKeyForBase(Context, QualType(Init->getBaseClass(), 0));
+ const void *Key =
+ GetKeyForBase(Context, QualType(Init->getBaseClass(), 0));
if (CheckRedundantInit(*this, Init, Members[Key]))
HadError = true;
} else {
@@ -3702,6 +3885,8 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits);
SetCtorInitializers(Constructor, AnyErrors, MemInits);
+
+ DiagnoseUninitializedFields(*this, Constructor);
}
void
@@ -3750,7 +3935,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
<< Field->getDeclName()
<< FieldType);
- MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+ MarkFunctionReferenced(Location, Dtor);
DiagnoseUseOfDecl(Dtor, Location);
}
@@ -3783,7 +3968,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
<< Base->getSourceRange(),
Context.getTypeDeclType(ClassDecl));
- MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+ MarkFunctionReferenced(Location, Dtor);
DiagnoseUseOfDecl(Dtor, Location);
}
@@ -3807,12 +3992,19 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
assert(Dtor && "No dtor found for BaseClassDecl!");
- CheckDestructorAccess(ClassDecl->getLocation(), Dtor,
- PDiag(diag::err_access_dtor_vbase)
- << VBase->getType(),
- Context.getTypeDeclType(ClassDecl));
-
- MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+ if (CheckDestructorAccess(
+ ClassDecl->getLocation(), Dtor,
+ PDiag(diag::err_access_dtor_vbase)
+ << Context.getTypeDeclType(ClassDecl) << VBase->getType(),
+ Context.getTypeDeclType(ClassDecl)) ==
+ AR_accessible) {
+ CheckDerivedToBaseConversion(
+ Context.getTypeDeclType(ClassDecl), VBase->getType(),
+ diag::err_access_dtor_vbase, 0, ClassDecl->getLocation(),
+ SourceRange(), DeclarationName(), 0);
+ }
+
+ MarkFunctionReferenced(Location, Dtor);
DiagnoseUseOfDecl(Dtor, Location);
}
}
@@ -3822,8 +4014,10 @@ void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) {
return;
if (CXXConstructorDecl *Constructor
- = dyn_cast<CXXConstructorDecl>(CDtorDecl))
+ = dyn_cast<CXXConstructorDecl>(CDtorDecl)) {
SetCtorInitializers(Constructor, /*AnyErrors=*/false);
+ DiagnoseUninitializedFields(*this, Constructor);
+ }
}
bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
@@ -3835,8 +4029,8 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
public:
NonAbstractTypeDiagnoser(unsigned DiagID, AbstractDiagSelID SelID)
: TypeDiagnoser(DiagID == 0), DiagID(DiagID), SelID(SelID) { }
-
- virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) LLVM_OVERRIDE {
if (Suppressed) return;
if (SelID == -1)
S.Diag(Loc, DiagID) << T;
@@ -3893,6 +4087,12 @@ void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) {
if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD))
return;
+ // If the diagnostic is suppressed, don't emit the notes. We're only
+ // going to emit them once, so try to attach them to a diagnostic we're
+ // actually going to show.
+ if (Diags.isLastDiagnosticIgnored())
+ return;
+
CXXFinalOverriderMap FinalOverriders;
RD->getFinalOverriders(FinalOverriders);
@@ -4172,9 +4372,12 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
diag::warn_non_virtual_dtor) << Context.getRecordType(Record);
}
- if (Record->isAbstract() && Record->hasAttr<FinalAttr>()) {
- Diag(Record->getLocation(), diag::warn_abstract_final_class);
- DiagnoseAbstractType(Record);
+ if (Record->isAbstract()) {
+ if (FinalAttr *FA = Record->getAttr<FinalAttr>()) {
+ Diag(Record->getLocation(), diag::warn_abstract_final_class)
+ << FA->isSpelledAsSealed();
+ DiagnoseAbstractType(Record);
+ }
}
if (!Record->isDependentType()) {
@@ -4184,7 +4387,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
// See if a method overloads virtual methods in a base
// class without overriding any.
if (!M->isStatic())
- DiagnoseHiddenVirtualMethods(Record, *M);
+ DiagnoseHiddenVirtualMethods(*M);
// Check whether the explicitly-defaulted special members are valid.
if (!M->isInvalidDecl() && M->isExplicitlyDefaulted())
@@ -4243,6 +4446,13 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
+ // Check to see if we're trying to lay out a struct using the ms_struct
+ // attribute that is dynamic.
+ if (Record->isMsStruct(Context) && Record->isDynamicClass()) {
+ Diag(Record->getLocation(), diag::warn_pragma_ms_struct_failed);
+ Record->dropAttr<MsStructAttr>();
+ }
+
// Declare inheriting constructors. We do this eagerly here because:
// - The standard requires an eager diagnostic for conflicting inheriting
// constructors from different classes.
@@ -4278,6 +4488,7 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
// C++11 [dcl.constexpr]p4:
// In the definition of a constexpr constructor [...]
+ bool Ctor = true;
switch (CSM) {
case Sema::CXXDefaultConstructor:
// Since default constructor lookup is essentially trivial (and cannot
@@ -4295,6 +4506,12 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
case Sema::CXXCopyAssignment:
case Sema::CXXMoveAssignment:
+ if (!S.getLangOpts().CPlusPlus1y)
+ return false;
+ // In C++1y, we need to perform overload resolution.
+ Ctor = false;
+ break;
+
case Sema::CXXDestructor:
case Sema::CXXInvalid:
return false;
@@ -4307,15 +4524,22 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
// If we squint, this is guaranteed, since exactly one non-static data member
// will be initialized (if the constructor isn't deleted), we just don't know
// which one.
- if (ClassDecl->isUnion())
+ if (Ctor && ClassDecl->isUnion())
return true;
// -- the class shall not have any virtual base classes;
- if (ClassDecl->getNumVBases())
+ if (Ctor && ClassDecl->getNumVBases())
+ return false;
+
+ // C++1y [class.copy]p26:
+ // -- [the class] is a literal type, and
+ if (!Ctor && !ClassDecl->isLiteral())
return false;
// -- every constructor involved in initializing [...] base class
// sub-objects shall be a constexpr constructor;
+ // -- the assignment operator selected to copy/move each direct base
+ // class is a constexpr function, and
for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
BEnd = ClassDecl->bases_end();
B != BEnd; ++B) {
@@ -4331,6 +4555,9 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
// [...] shall be a constexpr constructor;
// -- every non-static data member and base class sub-object shall be
// initialized
+ // -- for each non-stastic data member of X that is of class type (or array
+ // thereof), the assignment operator selected to copy/move that member is
+ // a constexpr function
for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
FEnd = ClassDecl->field_end();
F != FEnd; ++F) {
@@ -4380,6 +4607,21 @@ updateExceptionSpec(Sema &S, FunctionDecl *FD, const FunctionProtoType *FPT,
FPT->getArgTypes(), EPI));
}
+static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S,
+ CXXMethodDecl *MD) {
+ FunctionProtoType::ExtProtoInfo EPI;
+
+ // Build an exception specification pointing back at this member.
+ EPI.ExceptionSpecType = EST_Unevaluated;
+ EPI.ExceptionSpecDecl = MD;
+
+ // Set the calling convention to the default for C++ instance methods.
+ EPI.ExtInfo = EPI.ExtInfo.withCallingConv(
+ S.Context.getDefaultCallingConvention(/*IsVariadic=*/false,
+ /*IsCXXMethod=*/true));
+ return EPI;
+}
+
void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) {
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
if (FPT->getExceptionSpecType() != EST_Unevaluated)
@@ -4461,7 +4703,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
// A defaulted special member cannot have cv-qualifiers.
if (Type->getTypeQuals()) {
Diag(MD->getLocation(), diag::err_defaulted_special_member_quals)
- << (CSM == CXXMoveAssignment);
+ << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus1y;
HadError = true;
}
}
@@ -4506,13 +4748,16 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
// would have been implicitly declared as constexpr,
// Do not apply this rule to members of class templates, since core issue 1358
// makes such functions always instantiate to constexpr functions. For
- // non-constructors, this is checked elsewhere.
+ // functions which cannot be constexpr (for non-constructors in C++11 and for
+ // destructors in C++1y), this is checked elsewhere.
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, RD, CSM,
HasConstParam);
- if (isa<CXXConstructorDecl>(MD) && MD->isConstexpr() && !Constexpr &&
+ if ((getLangOpts().CPlusPlus1y ? !isa<CXXDestructorDecl>(MD)
+ : isa<CXXConstructorDecl>(MD)) &&
+ MD->isConstexpr() && !Constexpr &&
MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
Diag(MD->getLocStart(), diag::err_incorrect_defaulted_constexpr) << CSM;
- // FIXME: Explain why the constructor can't be constexpr.
+ // FIXME: Explain why the special member can't be constexpr.
HadError = true;
}
@@ -4573,7 +4818,9 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
void Sema::CheckExplicitlyDefaultedMemberExceptionSpec(
CXXMethodDecl *MD, const FunctionProtoType *SpecifiedType) {
// Compute the implicit exception specification.
- FunctionProtoType::ExtProtoInfo EPI;
+ CallingConv CC = Context.getDefaultCallingConvention(/*IsVariadic=*/false,
+ /*IsCXXMethod=*/true);
+ FunctionProtoType::ExtProtoInfo EPI(CC);
computeImplicitExceptionSpec(*this, MD->getLocation(), MD).getEPI(EPI);
const FunctionProtoType *ImplicitType = cast<FunctionProtoType>(
Context.getFunctionType(Context.VoidTy, None, EPI));
@@ -4586,14 +4833,28 @@ void Sema::CheckExplicitlyDefaultedMemberExceptionSpec(
SpecifiedType, MD->getLocation());
}
-void Sema::CheckDelayedExplicitlyDefaultedMemberExceptionSpecs() {
- for (unsigned I = 0, N = DelayedDefaultedMemberExceptionSpecs.size();
- I != N; ++I)
- CheckExplicitlyDefaultedMemberExceptionSpec(
- DelayedDefaultedMemberExceptionSpecs[I].first,
- DelayedDefaultedMemberExceptionSpecs[I].second);
+void Sema::CheckDelayedMemberExceptionSpecs() {
+ SmallVector<std::pair<const CXXDestructorDecl *, const CXXDestructorDecl *>,
+ 2> Checks;
+ SmallVector<std::pair<CXXMethodDecl *, const FunctionProtoType *>, 2> Specs;
- DelayedDefaultedMemberExceptionSpecs.clear();
+ std::swap(Checks, DelayedDestructorExceptionSpecChecks);
+ std::swap(Specs, DelayedDefaultedMemberExceptionSpecs);
+
+ // Perform any deferred checking of exception specifications for virtual
+ // destructors.
+ for (unsigned i = 0, e = Checks.size(); i != e; ++i) {
+ const CXXDestructorDecl *Dtor = Checks[i].first;
+ assert(!Dtor->getParent()->isDependentType() &&
+ "Should not ever add destructors of templates into the list.");
+ CheckOverridingFunctionExceptionSpec(Dtor, Checks[i].second);
+ }
+
+ // Check that any explicitly-defaulted methods have exception specifications
+ // compatible with their implicit exception specifications.
+ for (unsigned I = 0, N = Specs.size(); I != N; ++I)
+ CheckExplicitlyDefaultedMemberExceptionSpec(Specs[I].first,
+ Specs[I].second);
}
namespace {
@@ -4652,6 +4913,10 @@ struct SpecialMemberDeletionInfo {
// cv-qualifiers on class members don't affect default ctor / dtor calls.
if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor)
Quals = 0;
+ // cv-qualifiers on class members affect the type of both '*this' and the
+ // argument for an assignment.
+ if (IsAssignment)
+ TQ |= Quals;
return S.LookupSpecialMember(Class, CSM,
ConstArg || (Quals & Qualifiers::Const),
VolatileArg || (Quals & Qualifiers::Volatile),
@@ -5015,10 +5280,15 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
SMI.shouldDeleteForBase(BI))
return true;
- for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(),
- BE = RD->vbases_end(); BI != BE; ++BI)
- if (SMI.shouldDeleteForBase(BI))
- return true;
+ // Per DR1611, do not consider virtual bases of constructors of abstract
+ // classes, since we are not going to construct them.
+ if (!RD->isAbstract() || !SMI.IsConstructor) {
+ for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(),
+ BE = RD->vbases_end();
+ BI != BE; ++BI)
+ if (SMI.shouldDeleteForBase(BI))
+ return true;
+ }
for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
FE = RD->field_end(); FI != FE; ++FI)
@@ -5310,9 +5580,9 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
bool ConstArg = false;
- // C++11 [class.copy]p12, p25:
- // A [special member] is trivial if its declared parameter type is the same
- // as if it had been implicitly declared [...]
+ // C++11 [class.copy]p12, p25: [DR1593]
+ // A [special member] is trivial if [...] its parameter-type-list is
+ // equivalent to the parameter-type-list of an implicit declaration [...]
switch (CSM) {
case CXXDefaultConstructor:
case CXXDestructor:
@@ -5356,11 +5626,6 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
llvm_unreachable("not a special member");
}
- // FIXME: We require that the parameter-declaration-clause is equivalent to
- // that of an implicit declaration, not just that the declared parameter type
- // matches, in order to prevent absuridities like a function simultaneously
- // being a trivial copy constructor and a non-trivial default constructor.
- // This issue has not yet been assigned a core issue number.
if (MD->getMinRequiredArguments() < MD->getNumParams()) {
if (Diagnose)
Diag(MD->getParamDecl(MD->getMinRequiredArguments())->getLocation(),
@@ -5524,12 +5789,10 @@ static void AddMostOverridenMethods(const CXXMethodDecl *MD,
AddMostOverridenMethods(*I, Methods);
}
-/// \brief See if a method overloads virtual methods in a base class without
+/// \brief Check if a method overloads virtual methods in a base class without
/// overriding any.
-void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
- if (Diags.getDiagnosticLevel(diag::warn_overloaded_virtual,
- MD->getLocation()) == DiagnosticsEngine::Ignored)
- return;
+void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD,
+ SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) {
if (!MD->getDeclName().isIdentifier())
return;
@@ -5542,6 +5805,7 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
// Keep the base methods that were overriden or introduced in the subclass
// by 'using' in a set. A base method not in this set is hidden.
+ CXXRecordDecl *DC = MD->getParent();
DeclContext::lookup_result R = DC->lookup(MD->getDeclName());
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
NamedDecl *ND = *I;
@@ -5551,18 +5815,38 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
AddMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods);
}
- if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths) &&
- !Data.OverloadedMethods.empty()) {
+ if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths))
+ OverloadedMethods = Data.OverloadedMethods;
+}
+
+void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD,
+ SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) {
+ for (unsigned i = 0, e = OverloadedMethods.size(); i != e; ++i) {
+ CXXMethodDecl *overloadedMD = OverloadedMethods[i];
+ PartialDiagnostic PD = PDiag(
+ diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD;
+ HandleFunctionTypeMismatch(PD, MD->getType(), overloadedMD->getType());
+ Diag(overloadedMD->getLocation(), PD);
+ }
+}
+
+/// \brief Diagnose methods which overload virtual methods in a base class
+/// without overriding any.
+void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) {
+ if (MD->isInvalidDecl())
+ return;
+
+ if (Diags.getDiagnosticLevel(diag::warn_overloaded_virtual,
+ MD->getLocation()) == DiagnosticsEngine::Ignored)
+ return;
+
+ SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
+ FindHiddenVirtualMethods(MD, OverloadedMethods);
+ if (!OverloadedMethods.empty()) {
Diag(MD->getLocation(), diag::warn_overloaded_virtual)
- << MD << (Data.OverloadedMethods.size() > 1);
+ << MD << (OverloadedMethods.size() > 1);
- for (unsigned i = 0, e = Data.OverloadedMethods.size(); i != e; ++i) {
- CXXMethodDecl *overloadedMD = Data.OverloadedMethods[i];
- PartialDiagnostic PD = PDiag(
- diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD;
- HandleFunctionTypeMismatch(PD, MD->getType(), overloadedMD->getType());
- Diag(overloadedMD->getLocation(), PD);
- }
+ NoteHiddenVirtualMethods(MD, OverloadedMethods);
}
}
@@ -5877,7 +6161,7 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
CXXRecordDecl *RD = Destructor->getParent();
- if (Destructor->isVirtual()) {
+ if (!Destructor->getOperatorDelete() && Destructor->isVirtual()) {
SourceLocation Loc;
if (!Destructor->isImplicit())
@@ -5891,6 +6175,10 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
Context.DeclarationNames.getCXXOperatorName(OO_Delete);
if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
return true;
+ // If there's no class-specific operator delete, look up the global
+ // non-array delete.
+ if (!OperatorDelete)
+ OperatorDelete = FindUsualDeallocationFunction(Loc, true, Name);
MarkFunctionReferenced(Loc, OperatorDelete);
@@ -6029,8 +6317,8 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
if (SC == SC_Static) {
if (!D.isInvalidType())
Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member)
- << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
- << SourceRange(D.getIdentifierLoc());
+ << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
+ << D.getName().getSourceRange();
D.setInvalidType();
SC = SC_None;
}
@@ -6541,11 +6829,10 @@ namespace {
// Callback to only accept typo corrections that are namespaces.
class NamespaceValidatorCCC : public CorrectionCandidateCallback {
- public:
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
- if (NamedDecl *ND = candidate.getCorrectionDecl()) {
+public:
+ bool ValidateCandidate(const TypoCorrection &candidate) LLVM_OVERRIDE {
+ if (NamedDecl *ND = candidate.getCorrectionDecl())
return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
- }
return false;
}
};
@@ -6561,21 +6848,19 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(),
R.getLookupKind(), Sc, &SS,
Validator)) {
- std::string CorrectedStr(Corrected.getAsString(S.getLangOpts()));
- std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOpts()));
- if (DeclContext *DC = S.computeDeclContext(SS, false))
- S.Diag(IdentLoc, diag::err_using_directive_member_suggest)
- << Ident << DC << CorrectedQuotedStr << SS.getRange()
- << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
- CorrectedStr);
- else
- S.Diag(IdentLoc, diag::err_using_directive_suggest)
- << Ident << CorrectedQuotedStr
- << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
-
- S.Diag(Corrected.getCorrectionDecl()->getLocation(),
- diag::note_namespace_defined_here) << CorrectedQuotedStr;
-
+ if (DeclContext *DC = S.computeDeclContext(SS, false)) {
+ std::string CorrectedStr(Corrected.getAsString(S.getLangOpts()));
+ bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
+ Ident->getName().equals(CorrectedStr);
+ S.diagnoseTypo(Corrected,
+ S.PDiag(diag::err_using_directive_member_suggest)
+ << Ident << DC << DroppedSpecifier << SS.getRange(),
+ S.PDiag(diag::note_namespace_defined_here));
+ } else {
+ S.diagnoseTypo(Corrected,
+ S.PDiag(diag::err_using_directive_suggest) << Ident,
+ S.PDiag(diag::note_namespace_defined_here));
+ }
R.addDecl(Corrected.getCorrectionDecl());
return true;
}
@@ -6649,7 +6934,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
IdentLoc, Named, CommonAncestor);
if (IsUsingDirectiveInToplevelContext(CurContext) &&
- !SourceMgr.isFromMainFile(SourceMgr.getExpansionLoc(IdentLoc))) {
+ !SourceMgr.isInMainFile(SourceMgr.getExpansionLoc(IdentLoc))) {
Diag(IdentLoc, diag::warn_using_directive_in_header);
}
@@ -6668,7 +6953,7 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
// If the scope has an associated entity and the using directive is at
// namespace or translation unit scope, add the UsingDirectiveDecl into
// its lookup structure so qualified name lookup can find it.
- DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+ DeclContext *Ctx = S->getEntity();
if (Ctx && !Ctx->isFunctionOrMethod())
Ctx->addDecl(UDir);
else
@@ -6685,7 +6970,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
CXXScopeSpec &SS,
UnqualifiedId &Name,
AttributeList *AttrList,
- bool IsTypeName,
+ bool HasTypenameKeyword,
SourceLocation TypenameLoc) {
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
@@ -6727,13 +7012,10 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
return 0;
// Warn about access declarations.
- // TODO: store that the declaration was written without 'using' and
- // talk about access decls instead of using decls in the
- // diagnostics.
if (!HasUsingKeyword) {
- UsingLoc = Name.getLocStart();
-
- Diag(UsingLoc, diag::warn_access_decl_deprecated)
+ Diag(Name.getLocStart(),
+ getLangOpts().CPlusPlus11 ? diag::err_access_decl
+ : diag::warn_access_decl_deprecated)
<< FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
}
@@ -6744,7 +7026,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
TargetNameInfo, AttrList,
/* IsInstantiation */ false,
- IsTypeName, TypenameLoc);
+ HasTypenameKeyword, TypenameLoc);
if (UD)
PushOnScopeChains(UD, S, /*AddToContext*/ false);
@@ -6754,20 +7036,15 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
/// \brief Determine whether a using declaration considers the given
/// declarations as "equivalent", e.g., if they are redeclarations of
/// the same entity or are both typedefs of the same type.
-static bool
-IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2,
- bool &SuppressRedeclaration) {
- if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) {
- SuppressRedeclaration = false;
+static bool
+IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2) {
+ if (D1->getCanonicalDecl() == D2->getCanonicalDecl())
return true;
- }
if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1))
- if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2)) {
- SuppressRedeclaration = true;
+ if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2))
return Context.hasSameType(TD1->getUnderlyingType(),
TD2->getUnderlyingType());
- }
return false;
}
@@ -6776,7 +7053,8 @@ IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2,
/// Determines whether to create a using shadow decl for a particular
/// decl, given the set of decls existing prior to this using lookup.
bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
- const LookupResult &Previous) {
+ const LookupResult &Previous,
+ UsingShadowDecl *&PrevShadow) {
// Diagnose finding a decl which is not from a base class of the
// current class. We do this now because there are cases where this
// function will silently decide not to build a shadow decl, which
@@ -6836,16 +7114,22 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
// FIXME: but we might be increasing its access, in which case we
// should redeclare it.
NamedDecl *NonTag = 0, *Tag = 0;
+ bool FoundEquivalentDecl = false;
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
- bool Result;
- if (IsEquivalentForUsingDecl(Context, D, Target, Result))
- return Result;
+ if (IsEquivalentForUsingDecl(Context, D, Target)) {
+ if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I))
+ PrevShadow = Shadow;
+ FoundEquivalentDecl = true;
+ }
(isa<TagDecl>(D) ? Tag : NonTag) = D;
}
+ if (FoundEquivalentDecl)
+ return false;
+
if (Target->isFunctionOrFunctionTemplate()) {
FunctionDecl *FD;
if (isa<FunctionTemplateDecl>(Target))
@@ -6904,7 +7188,8 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
/// Builds a shadow declaration corresponding to a 'using' declaration.
UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
UsingDecl *UD,
- NamedDecl *Orig) {
+ NamedDecl *Orig,
+ UsingShadowDecl *PrevDecl) {
// If we resolved to another shadow declaration, just coalesce them.
NamedDecl *Target = Orig;
@@ -6912,16 +7197,18 @@ UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration");
}
-
+
UsingShadowDecl *Shadow
= UsingShadowDecl::Create(Context, CurContext,
UD->getLocation(), UD, Target);
UD->addShadowDecl(Shadow);
-
+
Shadow->setAccess(UD->getAccess());
if (Orig->isInvalidDecl() || UD->isInvalidDecl())
Shadow->setInvalidDecl();
-
+
+ Shadow->setPreviousDecl(PrevDecl);
+
if (S)
PushOnScopeChains(Shadow, S);
else
@@ -6979,6 +7266,42 @@ void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
// be possible for this to happen, because...?
}
+namespace {
+class UsingValidatorCCC : public CorrectionCandidateCallback {
+public:
+ UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation,
+ bool RequireMember)
+ : HasTypenameKeyword(HasTypenameKeyword),
+ IsInstantiation(IsInstantiation), RequireMember(RequireMember) {}
+
+ bool ValidateCandidate(const TypoCorrection &Candidate) LLVM_OVERRIDE {
+ NamedDecl *ND = Candidate.getCorrectionDecl();
+
+ // Keywords are not valid here.
+ if (!ND || isa<NamespaceDecl>(ND))
+ return false;
+
+ if (RequireMember && !isa<FieldDecl>(ND) && !isa<CXXMethodDecl>(ND) &&
+ !isa<TypeDecl>(ND))
+ return false;
+
+ // Completely unqualified names are invalid for a 'using' declaration.
+ if (Candidate.WillReplaceSpecifier() && !Candidate.getCorrectionSpecifier())
+ return false;
+
+ if (isa<TypeDecl>(ND))
+ return HasTypenameKeyword || !IsInstantiation;
+
+ return !HasTypenameKeyword;
+ }
+
+private:
+ bool HasTypenameKeyword;
+ bool IsInstantiation;
+ bool RequireMember;
+};
+} // end anonymous namespace
+
/// Builds a using declaration.
///
/// \param IsInstantiation - Whether this call arises from an
@@ -6990,7 +7313,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
const DeclarationNameInfo &NameInfo,
AttributeList *AttrList,
bool IsInstantiation,
- bool IsTypeName,
+ bool HasTypenameKeyword,
SourceLocation TypenameLoc) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
SourceLocation IdentLoc = NameInfo.getLoc();
@@ -7025,7 +7348,8 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
}
// Check for invalid redeclarations.
- if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous))
+ if (CheckUsingDeclRedeclaration(UsingLoc, HasTypenameKeyword,
+ SS, IdentLoc, Previous))
return 0;
// Check for bad qualifiers.
@@ -7036,7 +7360,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
NamedDecl *D;
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
if (!LookupContext) {
- if (IsTypeName) {
+ if (HasTypenameKeyword) {
// FIXME: not all declaration name kinds are legal here
D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
UsingLoc, TypenameLoc,
@@ -7048,7 +7372,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
}
} else {
D = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc,
- NameInfo, IsTypeName);
+ NameInfo, HasTypenameKeyword);
}
D->setAccess(AS);
CurContext->addDecl(D);
@@ -7088,11 +7412,27 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
LookupQualifiedName(R, LookupContext);
+ // Try to correct typos if possible.
if (R.empty()) {
- Diag(IdentLoc, diag::err_no_member)
- << NameInfo.getName() << LookupContext << SS.getRange();
- UD->setInvalidDecl();
- return UD;
+ UsingValidatorCCC CCC(HasTypenameKeyword, IsInstantiation,
+ CurContext->isRecord());
+ if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
+ R.getLookupKind(), S, &SS, CCC)){
+ // We reject any correction for which ND would be NULL.
+ NamedDecl *ND = Corrected.getCorrectionDecl();
+ R.setLookupName(Corrected.getCorrection());
+ R.addDecl(ND);
+ // We reject candidates where DroppedSpecifier == true, hence the
+ // literal '0' below.
+ diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest)
+ << NameInfo.getName() << LookupContext << 0
+ << SS.getRange());
+ } else {
+ Diag(IdentLoc, diag::err_no_member)
+ << NameInfo.getName() << LookupContext << SS.getRange();
+ UD->setInvalidDecl();
+ return UD;
+ }
}
if (R.isAmbiguous()) {
@@ -7100,7 +7440,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
return UD;
}
- if (IsTypeName) {
+ if (HasTypenameKeyword) {
// If we asked for a typename and got a non-type decl, error out.
if (!R.getAsSingle<TypeDecl>()) {
Diag(IdentLoc, diag::err_using_typename_non_type);
@@ -7132,8 +7472,9 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
}
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
- if (!CheckUsingShadowDecl(UD, *I, Previous))
- BuildUsingShadowDecl(S, UD, *I);
+ UsingShadowDecl *PrevDecl = 0;
+ if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl))
+ BuildUsingShadowDecl(S, UD, *I, PrevDecl);
}
return UD;
@@ -7141,7 +7482,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
/// Additional checks for a using declaration referring to a constructor name.
bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
- assert(!UD->isTypeName() && "expecting a constructor name");
+ assert(!UD->hasTypename() && "expecting a constructor name");
const Type *SourceType = UD->getQualifier()->getAsType();
assert(SourceType &&
@@ -7162,7 +7503,7 @@ bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
if (BaseIt == BaseE) {
// Did not find SourceType in the bases.
- Diag(UD->getUsingLocation(),
+ Diag(UD->getUsingLoc(),
diag::err_using_decl_constructor_not_in_direct_base)
<< UD->getNameInfo().getSourceRange()
<< QualType(SourceType, 0) << TargetClass;
@@ -7179,7 +7520,7 @@ bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
/// redeclaration. Note that this is checking only for the using decl
/// itself, not for any ill-formedness among the UsingShadowDecls.
bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
- bool isTypeName,
+ bool HasTypenameKeyword,
const CXXScopeSpec &SS,
SourceLocation NameLoc,
const LookupResult &Prev) {
@@ -7202,7 +7543,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
bool DTypename;
NestedNameSpecifier *DQual;
if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
- DTypename = UD->isTypeName();
+ DTypename = UD->hasTypename();
DQual = UD->getQualifier();
} else if (UnresolvedUsingValueDecl *UD
= dyn_cast<UnresolvedUsingValueDecl>(D)) {
@@ -7216,7 +7557,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
// using decls differ if one says 'typename' and the other doesn't.
// FIXME: non-dependent using decls?
- if (isTypeName != DTypename) continue;
+ if (HasTypenameKeyword != DTypename) continue;
// using decls differ if they name different scopes (but note that
// template instantiation can cause this check to trigger when it
@@ -7498,7 +7839,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
if (Invalid)
NewDecl->setInvalidDecl();
else if (OldDecl)
- NewDecl->setPreviousDeclaration(OldDecl);
+ NewDecl->setPreviousDecl(OldDecl);
NewND = NewDecl;
} else {
@@ -7788,9 +8129,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
DefaultCon->setImplicit();
// Build an exception specification pointing back at this constructor.
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = DefaultCon;
+ FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, DefaultCon);
DefaultCon->setType(Context.getFunctionType(Context.VoidTy, None, EPI));
// We don't need to use SpecialMemberIsTrivial here; triviality for default
@@ -7833,18 +8172,19 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
SourceLocation Loc = Constructor->getLocation();
Constructor->setBody(new (Context) CompoundStmt(Loc));
- Constructor->setUsed();
+ Constructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Constructor);
}
+
+ DiagnoseUninitializedFields(*this, Constructor);
}
void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) {
- // Check that any explicitly-defaulted methods have exception specifications
- // compatible with their implicit exception specifications.
- CheckDelayedExplicitlyDefaultedMemberExceptionSpecs();
+ // Perform any delayed checks on exception specifications.
+ CheckDelayedMemberExceptionSpecs();
}
namespace {
@@ -7887,8 +8227,8 @@ private:
/// constructors.
struct InheritingConstructorsForType {
InheritingConstructor NonTemplate;
- llvm::SmallVector<
- std::pair<TemplateParameterList*, InheritingConstructor>, 4> Templates;
+ SmallVector<std::pair<TemplateParameterList *, InheritingConstructor>, 4>
+ Templates;
InheritingConstructor &getEntry(Sema &S, const CXXConstructorDecl *Ctor) {
if (FunctionTemplateDecl *FTD = Ctor->getDescribedFunctionTemplate()) {
@@ -8171,7 +8511,7 @@ void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation,
SourceLocation Loc = Constructor->getLocation();
Constructor->setBody(new (Context) CompoundStmt(Loc));
- Constructor->setUsed();
+ Constructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
if (ASTMutationListener *L = getASTMutationListener()) {
@@ -8252,9 +8592,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
Destructor->setImplicit();
// Build an exception specification pointing back at this destructor.
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = Destructor;
+ FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, Destructor);
Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI));
AddOverriddenMethods(ClassDecl, Destructor);
@@ -8305,8 +8643,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
SourceLocation Loc = Destructor->getLocation();
Destructor->setBody(new (Context) CompoundStmt(Loc));
- Destructor->setImplicitlyDefined(true);
- Destructor->setUsed();
+ Destructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
if (ASTMutationListener *L = getASTMutationListener()) {
@@ -8320,23 +8657,11 @@ void Sema::ActOnFinishCXXMemberDecls() {
// If the context is an invalid C++ class, just suppress these checks.
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) {
if (Record->isInvalidDecl()) {
+ DelayedDefaultedMemberExceptionSpecs.clear();
DelayedDestructorExceptionSpecChecks.clear();
return;
}
}
-
- // Perform any deferred checking of exception specifications for virtual
- // destructors.
- for (unsigned i = 0, e = DelayedDestructorExceptionSpecChecks.size();
- i != e; ++i) {
- const CXXDestructorDecl *Dtor =
- DelayedDestructorExceptionSpecChecks[i].first;
- assert(!Dtor->getParent()->isDependentType() &&
- "Should not ever add destructors of templates into the list.");
- CheckOverridingFunctionExceptionSpec(Dtor,
- DelayedDestructorExceptionSpecChecks[i].second);
- }
- DelayedDestructorExceptionSpecChecks.clear();
}
void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
@@ -8368,13 +8693,144 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
// needs to be done somewhere else.
}
+namespace {
+/// \brief An abstract base class for all helper classes used in building the
+// copy/move operators. These classes serve as factory functions and help us
+// avoid using the same Expr* in the AST twice.
+class ExprBuilder {
+ ExprBuilder(const ExprBuilder&) LLVM_DELETED_FUNCTION;
+ ExprBuilder &operator=(const ExprBuilder&) LLVM_DELETED_FUNCTION;
+
+protected:
+ static Expr *assertNotNull(Expr *E) {
+ assert(E && "Expression construction must not fail.");
+ return E;
+ }
+
+public:
+ ExprBuilder() {}
+ virtual ~ExprBuilder() {}
+
+ virtual Expr *build(Sema &S, SourceLocation Loc) const = 0;
+};
+
+class RefBuilder: public ExprBuilder {
+ VarDecl *Var;
+ QualType VarType;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(S.BuildDeclRefExpr(Var, VarType, VK_LValue, Loc).take());
+ }
+
+ RefBuilder(VarDecl *Var, QualType VarType)
+ : Var(Var), VarType(VarType) {}
+};
+
+class ThisBuilder: public ExprBuilder {
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(S.ActOnCXXThis(Loc).takeAs<Expr>());
+ }
+};
+
+class CastBuilder: public ExprBuilder {
+ const ExprBuilder &Builder;
+ QualType Type;
+ ExprValueKind Kind;
+ const CXXCastPath &Path;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(S.ImpCastExprToType(Builder.build(S, Loc), Type,
+ CK_UncheckedDerivedToBase, Kind,
+ &Path).take());
+ }
+
+ CastBuilder(const ExprBuilder &Builder, QualType Type, ExprValueKind Kind,
+ const CXXCastPath &Path)
+ : Builder(Builder), Type(Type), Kind(Kind), Path(Path) {}
+};
+
+class DerefBuilder: public ExprBuilder {
+ const ExprBuilder &Builder;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(
+ S.CreateBuiltinUnaryOp(Loc, UO_Deref, Builder.build(S, Loc)).take());
+ }
+
+ DerefBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
+};
+
+class MemberBuilder: public ExprBuilder {
+ const ExprBuilder &Builder;
+ QualType Type;
+ CXXScopeSpec SS;
+ bool IsArrow;
+ LookupResult &MemberLookup;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(S.BuildMemberReferenceExpr(
+ Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(), 0,
+ MemberLookup, 0).take());
+ }
+
+ MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow,
+ LookupResult &MemberLookup)
+ : Builder(Builder), Type(Type), IsArrow(IsArrow),
+ MemberLookup(MemberLookup) {}
+};
+
+class MoveCastBuilder: public ExprBuilder {
+ const ExprBuilder &Builder;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(CastForMoving(S, Builder.build(S, Loc)));
+ }
+
+ MoveCastBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
+};
+
+class LvalueConvBuilder: public ExprBuilder {
+ const ExprBuilder &Builder;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ return assertNotNull(
+ S.DefaultLvalueConversion(Builder.build(S, Loc)).take());
+ }
+
+ LvalueConvBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
+};
+
+class SubscriptBuilder: public ExprBuilder {
+ const ExprBuilder &Base;
+ const ExprBuilder &Index;
+
+public:
+ virtual Expr *build(Sema &S, SourceLocation Loc) const
+ LLVM_OVERRIDE {
+ return assertNotNull(S.CreateBuiltinArraySubscriptExpr(
+ Base.build(S, Loc), Loc, Index.build(S, Loc), Loc).take());
+ }
+
+ SubscriptBuilder(const ExprBuilder &Base, const ExprBuilder &Index)
+ : Base(Base), Index(Index) {}
+};
+
+} // end anonymous namespace
+
/// When generating a defaulted copy or move assignment operator, if a field
/// should be copied with __builtin_memcpy rather than via explicit assignments,
/// do so. This optimization only applies for arrays of scalars, and for arrays
/// of class type where the selected copy/move-assignment operator is trivial.
static StmtResult
buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
- Expr *To, Expr *From) {
+ const ExprBuilder &ToB, const ExprBuilder &FromB) {
// Compute the size of the memory buffer to be copied.
QualType SizeType = S.Context.getSizeType();
llvm::APInt Size(S.Context.getTypeSize(SizeType),
@@ -8383,9 +8839,11 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
// Take the address of the field references for "from" and "to". We
// directly construct UnaryOperators here because semantic analysis
// does not permit us to take the address of an xvalue.
+ Expr *From = FromB.build(S, Loc);
From = new (S.Context) UnaryOperator(From, UO_AddrOf,
S.Context.getPointerType(From->getType()),
VK_RValue, OK_Ordinary, Loc);
+ Expr *To = ToB.build(S, Loc);
To = new (S.Context) UnaryOperator(To, UO_AddrOf,
S.Context.getPointerType(To->getType()),
VK_RValue, OK_Ordinary, Loc);
@@ -8451,7 +8909,7 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
/// if a memcpy should be used instead.
static StmtResult
buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
- Expr *To, Expr *From,
+ const ExprBuilder &To, const ExprBuilder &From,
bool CopyingBaseSubobject, bool Copying,
unsigned Depth = 0) {
// C++11 [class.copy]p28:
@@ -8524,8 +8982,8 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
// Create the reference to operator=.
ExprResult OpEqualRef
- = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS,
- /*TemplateKWLoc=*/SourceLocation(),
+ = S.BuildMemberReferenceExpr(To.build(S, Loc), T, Loc, /*isArrow=*/false,
+ SS, /*TemplateKWLoc=*/SourceLocation(),
/*FirstQualifierInScope=*/0,
OpLookup,
/*TemplateArgs=*/0,
@@ -8535,9 +8993,10 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
// Build the call to the assignment operator.
+ Expr *FromInst = From.build(S, Loc);
ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0,
OpEqualRef.takeAs<Expr>(),
- Loc, &From, 1, Loc);
+ Loc, FromInst, Loc);
if (Call.isInvalid())
return StmtError();
@@ -8556,7 +9015,8 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
// operator is used.
const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T);
if (!ArrayTy) {
- ExprResult Assignment = S.CreateBuiltinBinOp(Loc, BO_Assign, To, From);
+ ExprResult Assignment = S.CreateBuiltinBinOp(
+ Loc, BO_Assign, To.build(S, Loc), From.build(S, Loc));
if (Assignment.isInvalid())
return StmtError();
return S.ActOnExprStmt(Assignment);
@@ -8589,31 +9049,28 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0);
IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc));
- // Create a reference to the iteration variable; we'll use this several
- // times throughout.
- Expr *IterationVarRef
- = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc).take();
- assert(IterationVarRef && "Reference to invented variable cannot fail!");
- Expr *IterationVarRefRVal = S.DefaultLvalueConversion(IterationVarRef).take();
- assert(IterationVarRefRVal && "Conversion of invented variable cannot fail!");
+ // Creates a reference to the iteration variable.
+ RefBuilder IterationVarRef(IterationVar, SizeType);
+ LvalueConvBuilder IterationVarRefRVal(IterationVarRef);
// Create the DeclStmt that holds the iteration variable.
Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc);
// Subscript the "from" and "to" expressions with the iteration variable.
- From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc,
- IterationVarRefRVal,
- Loc));
- To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc,
- IterationVarRefRVal,
- Loc));
- if (!Copying) // Cast to rvalue
- From = CastForMoving(S, From);
+ SubscriptBuilder FromIndexCopy(From, IterationVarRefRVal);
+ MoveCastBuilder FromIndexMove(FromIndexCopy);
+ const ExprBuilder *FromIndex;
+ if (Copying)
+ FromIndex = &FromIndexCopy;
+ else
+ FromIndex = &FromIndexMove;
+
+ SubscriptBuilder ToIndex(To, IterationVarRefRVal);
// Build the copy/move for an individual element of the array.
StmtResult Copy =
buildSingleCopyAssignRecursively(S, Loc, ArrayTy->getElementType(),
- To, From, CopyingBaseSubobject,
+ ToIndex, *FromIndex, CopyingBaseSubobject,
Copying, Depth + 1);
// Bail out if copying fails or if we determined that we should use memcpy.
if (Copy.isInvalid() || !Copy.get())
@@ -8623,15 +9080,15 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
llvm::APInt Upper
= ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType));
Expr *Comparison
- = new (S.Context) BinaryOperator(IterationVarRefRVal,
+ = new (S.Context) BinaryOperator(IterationVarRefRVal.build(S, Loc),
IntegerLiteral::Create(S.Context, Upper, SizeType, Loc),
BO_NE, S.Context.BoolTy,
VK_RValue, OK_Ordinary, Loc, false);
// Create the pre-increment of the iteration variable.
Expr *Increment
- = new (S.Context) UnaryOperator(IterationVarRef, UO_PreInc, SizeType,
- VK_LValue, OK_Ordinary, Loc);
+ = new (S.Context) UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc,
+ SizeType, VK_LValue, OK_Ordinary, Loc);
// Construct the loop that copies all elements of this array.
return S.ActOnForStmt(Loc, Loc, InitStmt,
@@ -8642,7 +9099,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
static StmtResult
buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
- Expr *To, Expr *From,
+ const ExprBuilder &To, const ExprBuilder &From,
bool CopyingBaseSubobject, bool Copying) {
// Maybe we should use a memcpy?
if (T->isArrayType() && !T.isConstQualified() && !T.isVolatileQualified() &&
@@ -8736,29 +9193,31 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
QualType ArgType = Context.getTypeDeclType(ClassDecl);
QualType RetType = Context.getLValueReferenceType(ArgType);
- if (ClassDecl->implicitCopyAssignmentHasConstParam())
+ bool Const = ClassDecl->implicitCopyAssignmentHasConstParam();
+ if (Const)
ArgType = ArgType.withConst();
ArgType = Context.getLValueReferenceType(ArgType);
+ bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
+ CXXCopyAssignment,
+ Const);
+
// An implicitly-declared copy assignment operator is an inline public
// member of its class.
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationNameInfo NameInfo(Name, ClassLoc);
- CXXMethodDecl *CopyAssignment
- = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
- /*TInfo=*/0,
- /*StorageClass=*/SC_None,
- /*isInline=*/true, /*isConstexpr=*/false,
- SourceLocation());
+ CXXMethodDecl *CopyAssignment =
+ CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
+ /*TInfo=*/ 0, /*StorageClass=*/ SC_None,
+ /*isInline=*/ true, Constexpr, SourceLocation());
CopyAssignment->setAccess(AS_public);
CopyAssignment->setDefaulted();
CopyAssignment->setImplicit();
// Build an exception specification pointing back at this member.
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = CopyAssignment;
+ FunctionProtoType::ExtProtoInfo EPI =
+ getImplicitMethodEPI(*this, CopyAssignment);
CopyAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
// Add the parameter to the operator.
@@ -8775,11 +9234,6 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment)
: ClassDecl->hasTrivialCopyAssignment());
- // C++0x [class.copy]p19:
- // .... If the class definition does not explicitly declare a copy
- // assignment operator, there is no user-declared move constructor, and
- // there is no user-declared move assignment operator, a copy assignment
- // operator is implicitly declared as defaulted.
if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))
SetDeclDeleted(CopyAssignment, ClassLoc);
@@ -8793,6 +9247,58 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
return CopyAssignment;
}
+/// Diagnose an implicit copy operation for a class which is odr-used, but
+/// which is deprecated because the class has a user-declared copy constructor,
+/// copy assignment operator, or destructor.
+static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp,
+ SourceLocation UseLoc) {
+ assert(CopyOp->isImplicit());
+
+ CXXRecordDecl *RD = CopyOp->getParent();
+ CXXMethodDecl *UserDeclaredOperation = 0;
+
+ // In Microsoft mode, assignment operations don't affect constructors and
+ // vice versa.
+ if (RD->hasUserDeclaredDestructor()) {
+ UserDeclaredOperation = RD->getDestructor();
+ } else if (!isa<CXXConstructorDecl>(CopyOp) &&
+ RD->hasUserDeclaredCopyConstructor() &&
+ !S.getLangOpts().MicrosoftMode) {
+ // Find any user-declared copy constructor.
+ for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(),
+ E = RD->ctor_end(); I != E; ++I) {
+ if (I->isCopyConstructor()) {
+ UserDeclaredOperation = *I;
+ break;
+ }
+ }
+ assert(UserDeclaredOperation);
+ } else if (isa<CXXConstructorDecl>(CopyOp) &&
+ RD->hasUserDeclaredCopyAssignment() &&
+ !S.getLangOpts().MicrosoftMode) {
+ // Find any user-declared move assignment operator.
+ for (CXXRecordDecl::method_iterator I = RD->method_begin(),
+ E = RD->method_end(); I != E; ++I) {
+ if (I->isCopyAssignmentOperator()) {
+ UserDeclaredOperation = *I;
+ break;
+ }
+ }
+ assert(UserDeclaredOperation);
+ }
+
+ if (UserDeclaredOperation) {
+ S.Diag(UserDeclaredOperation->getLocation(),
+ diag::warn_deprecated_copy_operation)
+ << RD << /*copy assignment*/!isa<CXXConstructorDecl>(CopyOp)
+ << /*destructor*/isa<CXXDestructorDecl>(UserDeclaredOperation);
+ S.Diag(UseLoc, diag::note_member_synthesized_at)
+ << (isa<CXXConstructorDecl>(CopyOp) ? Sema::CXXCopyConstructor
+ : Sema::CXXCopyAssignment)
+ << RD;
+ }
+}
+
void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CXXMethodDecl *CopyAssignOperator) {
assert((CopyAssignOperator->isDefaulted() &&
@@ -8808,8 +9314,15 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CopyAssignOperator->setInvalidDecl();
return;
}
-
- CopyAssignOperator->setUsed();
+
+ // C++11 [class.copy]p18:
+ // The [definition of an implicitly declared copy assignment operator] is
+ // deprecated if the class has a user-declared copy constructor or a
+ // user-declared destructor.
+ if (getLangOpts().CPlusPlus11 && CopyAssignOperator->isImplicit())
+ diagnoseDeprecatedCopyOperation(*this, CopyAssignOperator, CurrentLocation);
+
+ CopyAssignOperator->markUsed(Context);
SynthesizedFunctionScope Scope(*this, CopyAssignOperator);
DiagnosticErrorTrap Trap(Diags);
@@ -8838,15 +9351,11 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// Our location for everything implicitly-generated.
SourceLocation Loc = CopyAssignOperator->getLocation();
- // Construct a reference to the "other" object. We'll be using this
- // throughout the generated ASTs.
- Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_LValue, Loc).take();
- assert(OtherRef && "Reference to parameter cannot fail!");
-
- // Construct the "this" pointer. We'll be using this throughout the generated
- // ASTs.
- Expr *This = ActOnCXXThis(Loc).takeAs<Expr>();
- assert(This && "Reference to this cannot fail!");
+ // Builds a DeclRefExpr for the "other" object.
+ RefBuilder OtherRef(Other, OtherRefType);
+
+ // Builds the "this" pointer.
+ ThisBuilder This;
// Assign base classes.
bool Invalid = false;
@@ -8865,24 +9374,19 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// Construct the "from" expression, which is an implicit cast to the
// appropriately-qualified base type.
- Expr *From = OtherRef;
- From = ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals),
- CK_UncheckedDerivedToBase,
- VK_LValue, &BasePath).take();
+ CastBuilder From(OtherRef, Context.getQualifiedType(BaseType, OtherQuals),
+ VK_LValue, BasePath);
// Dereference "this".
- ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
-
- // Implicitly cast "this" to the appropriately-qualified base type.
- To = ImpCastExprToType(To.take(),
- Context.getCVRQualifiedType(BaseType,
- CopyAssignOperator->getTypeQualifiers()),
- CK_UncheckedDerivedToBase,
- VK_LValue, &BasePath);
+ DerefBuilder DerefThis(This);
+ CastBuilder To(DerefThis,
+ Context.getCVRQualifiedType(
+ BaseType, CopyAssignOperator->getTypeQualifiers()),
+ VK_LValue, BasePath);
// Build the copy.
StmtResult Copy = buildSingleCopyAssign(*this, Loc, BaseType,
- To.get(), From,
+ To, From,
/*CopyingBaseSubobject=*/true,
/*Copying=*/true);
if (Copy.isInvalid()) {
@@ -8902,7 +9406,12 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
Field != FieldEnd; ++Field) {
if (Field->isUnnamedBitfield())
continue;
-
+
+ if (Field->isInvalidDecl()) {
+ Invalid = true;
+ continue;
+ }
+
// Check for members of reference type; we can't copy those.
if (Field->getType()->isReferenceType()) {
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
@@ -8943,20 +9452,14 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
LookupMemberName);
MemberLookup.addDecl(*Field);
MemberLookup.resolveKind();
- ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType,
- Loc, /*IsArrow=*/false,
- SS, SourceLocation(), 0,
- MemberLookup, 0);
- ExprResult To = BuildMemberReferenceExpr(This, This->getType(),
- Loc, /*IsArrow=*/true,
- SS, SourceLocation(), 0,
- MemberLookup, 0);
- assert(!From.isInvalid() && "Implicit field reference cannot fail");
- assert(!To.isInvalid() && "Implicit field reference cannot fail");
+
+ MemberBuilder From(OtherRef, OtherRefType, /*IsArrow=*/false, MemberLookup);
+
+ MemberBuilder To(This, getCurrentThisType(), /*IsArrow=*/true, MemberLookup);
// Build the copy of this field.
StmtResult Copy = buildSingleCopyAssign(*this, Loc, FieldType,
- To.get(), From.get(),
+ To, From,
/*CopyingBaseSubobject=*/false,
/*Copying=*/true);
if (Copy.isInvalid()) {
@@ -8972,7 +9475,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
if (!Invalid) {
// Add a "return *this;"
- ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
+ ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
@@ -9067,120 +9570,13 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD) {
return ExceptSpec;
}
-/// Determine whether the class type has any direct or indirect virtual base
-/// classes which have a non-trivial move assignment operator.
-static bool
-hasVirtualBaseWithNonTrivialMoveAssignment(Sema &S, CXXRecordDecl *ClassDecl) {
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd; ++Base) {
- CXXRecordDecl *BaseClass =
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-
- // Try to declare the move assignment. If it would be deleted, then the
- // class does not have a non-trivial move assignment.
- if (BaseClass->needsImplicitMoveAssignment())
- S.DeclareImplicitMoveAssignment(BaseClass);
-
- if (BaseClass->hasNonTrivialMoveAssignment())
- return true;
- }
-
- return false;
-}
-
-/// Determine whether the given type either has a move constructor or is
-/// trivially copyable.
-static bool
-hasMoveOrIsTriviallyCopyable(Sema &S, QualType Type, bool IsConstructor) {
- Type = S.Context.getBaseElementType(Type);
-
- // FIXME: Technically, non-trivially-copyable non-class types, such as
- // reference types, are supposed to return false here, but that appears
- // to be a standard defect.
- CXXRecordDecl *ClassDecl = Type->getAsCXXRecordDecl();
- if (!ClassDecl || !ClassDecl->getDefinition() || ClassDecl->isInvalidDecl())
- return true;
-
- if (Type.isTriviallyCopyableType(S.Context))
- return true;
-
- if (IsConstructor) {
- // FIXME: Need this because otherwise hasMoveConstructor isn't guaranteed to
- // give the right answer.
- if (ClassDecl->needsImplicitMoveConstructor())
- S.DeclareImplicitMoveConstructor(ClassDecl);
- return ClassDecl->hasMoveConstructor();
- }
-
- // FIXME: Need this because otherwise hasMoveAssignment isn't guaranteed to
- // give the right answer.
- if (ClassDecl->needsImplicitMoveAssignment())
- S.DeclareImplicitMoveAssignment(ClassDecl);
- return ClassDecl->hasMoveAssignment();
-}
-
-/// Determine whether all non-static data members and direct or virtual bases
-/// of class \p ClassDecl have either a move operation, or are trivially
-/// copyable.
-static bool subobjectsHaveMoveOrTrivialCopy(Sema &S, CXXRecordDecl *ClassDecl,
- bool IsConstructor) {
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- BaseEnd = ClassDecl->bases_end();
- Base != BaseEnd; ++Base) {
- if (Base->isVirtual())
- continue;
-
- if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor))
- return false;
- }
-
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd; ++Base) {
- if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor))
- return false;
- }
-
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
- if (!hasMoveOrIsTriviallyCopyable(S, Field->getType(), IsConstructor))
- return false;
- }
-
- return true;
-}
-
CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
- // C++11 [class.copy]p20:
- // If the definition of a class X does not explicitly declare a move
- // assignment operator, one will be implicitly declared as defaulted
- // if and only if:
- //
- // - [first 4 bullets]
assert(ClassDecl->needsImplicitMoveAssignment());
DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment);
if (DSM.isAlreadyBeingDeclared())
return 0;
- // [Checked after we build the declaration]
- // - the move assignment operator would not be implicitly defined as
- // deleted,
-
- // [DR1402]:
- // - X has no direct or indirect virtual base class with a non-trivial
- // move assignment operator, and
- // - each of X's non-static data members and direct or virtual base classes
- // has a type that either has a move assignment operator or is trivially
- // copyable.
- if (hasVirtualBaseWithNonTrivialMoveAssignment(*this, ClassDecl) ||
- !subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl,/*Constructor*/false)) {
- ClassDecl->setFailedImplicitMoveAssignment();
- return 0;
- }
-
// Note: The following rules are largely analoguous to the move
// constructor rules.
@@ -9188,26 +9584,26 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
QualType RetType = Context.getLValueReferenceType(ArgType);
ArgType = Context.getRValueReferenceType(ArgType);
+ bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
+ CXXMoveAssignment,
+ false);
+
// An implicitly-declared move assignment operator is an inline public
// member of its class.
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationNameInfo NameInfo(Name, ClassLoc);
- CXXMethodDecl *MoveAssignment
- = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
- /*TInfo=*/0,
- /*StorageClass=*/SC_None,
- /*isInline=*/true,
- /*isConstexpr=*/false,
- SourceLocation());
+ CXXMethodDecl *MoveAssignment =
+ CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
+ /*TInfo=*/0, /*StorageClass=*/SC_None,
+ /*isInline=*/true, Constexpr, SourceLocation());
MoveAssignment->setAccess(AS_public);
MoveAssignment->setDefaulted();
MoveAssignment->setImplicit();
// Build an exception specification pointing back at this member.
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = MoveAssignment;
+ FunctionProtoType::ExtProtoInfo EPI =
+ getImplicitMethodEPI(*this, MoveAssignment);
MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
// Add the parameter to the operator.
@@ -9224,18 +9620,9 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment)
: ClassDecl->hasTrivialMoveAssignment());
- // C++0x [class.copy]p9:
- // If the definition of a class X does not explicitly declare a move
- // assignment operator, one will be implicitly declared as defaulted if and
- // only if:
- // [...]
- // - the move assignment operator would not be implicitly defined as
- // deleted.
if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) {
- // Cache this result so that we don't try to generate this over and over
- // on every lookup, leaking memory and wasting time.
- ClassDecl->setFailedImplicitMoveAssignment();
- return 0;
+ ClassDecl->setImplicitMoveAssignmentIsDeleted();
+ SetDeclDeleted(MoveAssignment, ClassLoc);
}
// Note that we have added this copy-assignment operator.
@@ -9248,6 +9635,94 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
return MoveAssignment;
}
+/// Check if we're implicitly defining a move assignment operator for a class
+/// with virtual bases. Such a move assignment might move-assign the virtual
+/// base multiple times.
+static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class,
+ SourceLocation CurrentLocation) {
+ assert(!Class->isDependentContext() && "should not define dependent move");
+
+ // Only a virtual base could get implicitly move-assigned multiple times.
+ // Only a non-trivial move assignment can observe this. We only want to
+ // diagnose if we implicitly define an assignment operator that assigns
+ // two base classes, both of which move-assign the same virtual base.
+ if (Class->getNumVBases() == 0 || Class->hasTrivialMoveAssignment() ||
+ Class->getNumBases() < 2)
+ return;
+
+ llvm::SmallVector<CXXBaseSpecifier *, 16> Worklist;
+ typedef llvm::DenseMap<CXXRecordDecl*, CXXBaseSpecifier*> VBaseMap;
+ VBaseMap VBases;
+
+ for (CXXRecordDecl::base_class_iterator BI = Class->bases_begin(),
+ BE = Class->bases_end();
+ BI != BE; ++BI) {
+ Worklist.push_back(&*BI);
+ while (!Worklist.empty()) {
+ CXXBaseSpecifier *BaseSpec = Worklist.pop_back_val();
+ CXXRecordDecl *Base = BaseSpec->getType()->getAsCXXRecordDecl();
+
+ // If the base has no non-trivial move assignment operators,
+ // we don't care about moves from it.
+ if (!Base->hasNonTrivialMoveAssignment())
+ continue;
+
+ // If there's nothing virtual here, skip it.
+ if (!BaseSpec->isVirtual() && !Base->getNumVBases())
+ continue;
+
+ // If we're not actually going to call a move assignment for this base,
+ // or the selected move assignment is trivial, skip it.
+ Sema::SpecialMemberOverloadResult *SMOR =
+ S.LookupSpecialMember(Base, Sema::CXXMoveAssignment,
+ /*ConstArg*/false, /*VolatileArg*/false,
+ /*RValueThis*/true, /*ConstThis*/false,
+ /*VolatileThis*/false);
+ if (!SMOR->getMethod() || SMOR->getMethod()->isTrivial() ||
+ !SMOR->getMethod()->isMoveAssignmentOperator())
+ continue;
+
+ if (BaseSpec->isVirtual()) {
+ // We're going to move-assign this virtual base, and its move
+ // assignment operator is not trivial. If this can happen for
+ // multiple distinct direct bases of Class, diagnose it. (If it
+ // only happens in one base, we'll diagnose it when synthesizing
+ // that base class's move assignment operator.)
+ CXXBaseSpecifier *&Existing =
+ VBases.insert(std::make_pair(Base->getCanonicalDecl(), BI))
+ .first->second;
+ if (Existing && Existing != BI) {
+ S.Diag(CurrentLocation, diag::warn_vbase_moved_multiple_times)
+ << Class << Base;
+ S.Diag(Existing->getLocStart(), diag::note_vbase_moved_here)
+ << (Base->getCanonicalDecl() ==
+ Existing->getType()->getAsCXXRecordDecl()->getCanonicalDecl())
+ << Base << Existing->getType() << Existing->getSourceRange();
+ S.Diag(BI->getLocStart(), diag::note_vbase_moved_here)
+ << (Base->getCanonicalDecl() ==
+ BI->getType()->getAsCXXRecordDecl()->getCanonicalDecl())
+ << Base << BI->getType() << BaseSpec->getSourceRange();
+
+ // Only diagnose each vbase once.
+ Existing = 0;
+ }
+ } else {
+ // Only walk over bases that have defaulted move assignment operators.
+ // We assume that any user-provided move assignment operator handles
+ // the multiple-moves-of-vbase case itself somehow.
+ if (!SMOR->getMethod()->isDefaulted())
+ continue;
+
+ // We're going to move the base classes of Base. Add them to the list.
+ for (CXXRecordDecl::base_class_iterator BI = Base->bases_begin(),
+ BE = Base->bases_end();
+ BI != BE; ++BI)
+ Worklist.push_back(&*BI);
+ }
+ }
+ }
+}
+
void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
CXXMethodDecl *MoveAssignOperator) {
assert((MoveAssignOperator->isDefaulted() &&
@@ -9264,7 +9739,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
return;
}
- MoveAssignOperator->setUsed();
+ MoveAssignOperator->markUsed(Context);
SynthesizedFunctionScope Scope(*this, MoveAssignOperator);
DiagnosticErrorTrap Trap(Diags);
@@ -9277,6 +9752,10 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
// are assigned, in the order in which they were declared in the class
// definition.
+ // Issue a warning if our implicit move assignment operator will move
+ // from a virtual base more than once.
+ checkMoveAssignmentForRepeatedMove(*this, ClassDecl, CurrentLocation);
+
// The statements that form the synthesized function body.
SmallVector<Stmt*, 8> Statements;
@@ -9284,28 +9763,32 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0);
QualType OtherRefType = Other->getType()->
getAs<RValueReferenceType>()->getPointeeType();
- assert(OtherRefType.getQualifiers() == 0 &&
+ assert(!OtherRefType.getQualifiers() &&
"Bad argument type of defaulted move assignment");
// Our location for everything implicitly-generated.
SourceLocation Loc = MoveAssignOperator->getLocation();
- // Construct a reference to the "other" object. We'll be using this
- // throughout the generated ASTs.
- Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_LValue, Loc).take();
- assert(OtherRef && "Reference to parameter cannot fail!");
+ // Builds a reference to the "other" object.
+ RefBuilder OtherRef(Other, OtherRefType);
// Cast to rvalue.
- OtherRef = CastForMoving(*this, OtherRef);
+ MoveCastBuilder MoveOther(OtherRef);
- // Construct the "this" pointer. We'll be using this throughout the generated
- // ASTs.
- Expr *This = ActOnCXXThis(Loc).takeAs<Expr>();
- assert(This && "Reference to this cannot fail!");
+ // Builds the "this" pointer.
+ ThisBuilder This;
// Assign base classes.
bool Invalid = false;
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
E = ClassDecl->bases_end(); Base != E; ++Base) {
+ // C++11 [class.copy]p28:
+ // It is unspecified whether subobjects representing virtual base classes
+ // are assigned more than once by the implicitly-defined copy assignment
+ // operator.
+ // FIXME: Do not assign to a vbase that will be assigned by some other base
+ // class. For a move-assignment, this can result in the vbase being moved
+ // multiple times.
+
// Form the assignment:
// static_cast<Base*>(this)->Base::operator=(static_cast<Base&&>(other));
QualType BaseType = Base->getType().getUnqualifiedType();
@@ -9319,23 +9802,20 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
// Construct the "from" expression, which is an implicit cast to the
// appropriately-qualified base type.
- Expr *From = OtherRef;
- From = ImpCastExprToType(From, BaseType, CK_UncheckedDerivedToBase,
- VK_XValue, &BasePath).take();
+ CastBuilder From(OtherRef, BaseType, VK_XValue, BasePath);
// Dereference "this".
- ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
+ DerefBuilder DerefThis(This);
// Implicitly cast "this" to the appropriately-qualified base type.
- To = ImpCastExprToType(To.take(),
- Context.getCVRQualifiedType(BaseType,
- MoveAssignOperator->getTypeQualifiers()),
- CK_UncheckedDerivedToBase,
- VK_LValue, &BasePath);
+ CastBuilder To(DerefThis,
+ Context.getCVRQualifiedType(
+ BaseType, MoveAssignOperator->getTypeQualifiers()),
+ VK_LValue, BasePath);
// Build the move.
StmtResult Move = buildSingleCopyAssign(*this, Loc, BaseType,
- To.get(), From,
+ To, From,
/*CopyingBaseSubobject=*/true,
/*Copying=*/false);
if (Move.isInvalid()) {
@@ -9356,6 +9836,11 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
if (Field->isUnnamedBitfield())
continue;
+ if (Field->isInvalidDecl()) {
+ Invalid = true;
+ continue;
+ }
+
// Check for members of reference type; we can't move those.
if (Field->getType()->isReferenceType()) {
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
@@ -9391,29 +9876,22 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
}
// Build references to the field in the object we're copying from and to.
- CXXScopeSpec SS; // Intentionally empty
LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
LookupMemberName);
MemberLookup.addDecl(*Field);
MemberLookup.resolveKind();
- ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType,
- Loc, /*IsArrow=*/false,
- SS, SourceLocation(), 0,
- MemberLookup, 0);
- ExprResult To = BuildMemberReferenceExpr(This, This->getType(),
- Loc, /*IsArrow=*/true,
- SS, SourceLocation(), 0,
- MemberLookup, 0);
- assert(!From.isInvalid() && "Implicit field reference cannot fail");
- assert(!To.isInvalid() && "Implicit field reference cannot fail");
-
- assert(!From.get()->isLValue() && // could be xvalue or prvalue
+ MemberBuilder From(MoveOther, OtherRefType,
+ /*IsArrow=*/false, MemberLookup);
+ MemberBuilder To(This, getCurrentThisType(),
+ /*IsArrow=*/true, MemberLookup);
+
+ assert(!From.build(*this, Loc)->isLValue() && // could be xvalue or prvalue
"Member reference with rvalue base must be rvalue except for reference "
"members, which aren't allowed for move assignment.");
// Build the move of this field.
StmtResult Move = buildSingleCopyAssign(*this, Loc, FieldType,
- To.get(), From.get(),
+ To, From,
/*CopyingBaseSubobject=*/false,
/*Copying=*/false);
if (Move.isInvalid()) {
@@ -9429,7 +9907,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
if (!Invalid) {
// Add a "return *this;"
- ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
+ ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
@@ -9557,9 +10035,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
CopyConstructor->setDefaulted();
// Build an exception specification pointing back at this member.
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = CopyConstructor;
+ FunctionProtoType::ExtProtoInfo EPI =
+ getImplicitMethodEPI(*this, CopyConstructor);
CopyConstructor->setType(
Context.getFunctionType(Context.VoidTy, ArgType, EPI));
@@ -9576,11 +10053,6 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
: ClassDecl->hasTrivialCopyConstructor());
- // C++11 [class.copy]p8:
- // ... If the class definition does not explicitly declare a copy
- // constructor, there is no user-declared move constructor, and there is no
- // user-declared move assignment operator, a copy constructor is implicitly
- // declared as defaulted.
if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
SetDeclDeleted(CopyConstructor, ClassLoc);
@@ -9605,6 +10077,13 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CXXRecordDecl *ClassDecl = CopyConstructor->getParent();
assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
+ // C++11 [class.copy]p7:
+ // The [definition of an implicitly declared copy constructor] is
+ // deprecated if the class has a user-declared copy assignment operator
+ // or a user-declared destructor.
+ if (getLangOpts().CPlusPlus11 && CopyConstructor->isImplicit())
+ diagnoseDeprecatedCopyOperation(*this, CopyConstructor, CurrentLocation);
+
SynthesizedFunctionScope Scope(*this, CopyConstructor);
DiagnosticErrorTrap Trap(Diags);
@@ -9615,15 +10094,12 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CopyConstructor->setInvalidDecl();
} else {
Sema::CompoundScopeRAII CompoundScope(*this);
- CopyConstructor->setBody(ActOnCompoundStmt(CopyConstructor->getLocation(),
- CopyConstructor->getLocation(),
- MultiStmtArg(),
- /*isStmtExpr=*/false)
- .takeAs<Stmt>());
- CopyConstructor->setImplicitlyDefined(true);
+ CopyConstructor->setBody(ActOnCompoundStmt(
+ CopyConstructor->getLocation(), CopyConstructor->getLocation(), None,
+ /*isStmtExpr=*/ false).takeAs<Stmt>());
}
-
- CopyConstructor->setUsed();
+
+ CopyConstructor->markUsed(Context);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(CopyConstructor);
}
@@ -9696,29 +10172,12 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD) {
CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
CXXRecordDecl *ClassDecl) {
- // C++11 [class.copy]p9:
- // If the definition of a class X does not explicitly declare a move
- // constructor, one will be implicitly declared as defaulted if and only if:
- //
- // - [first 4 bullets]
assert(ClassDecl->needsImplicitMoveConstructor());
DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor);
if (DSM.isAlreadyBeingDeclared())
return 0;
- // [Checked after we build the declaration]
- // - the move assignment operator would not be implicitly defined as
- // deleted,
-
- // [DR1402]:
- // - each of X's non-static data members and direct or virtual base classes
- // has a type that either has a move constructor or is trivially copyable.
- if (!subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl, /*Constructor*/true)) {
- ClassDecl->setFailedImplicitMoveConstructor();
- return 0;
- }
-
QualType ClassType = Context.getTypeDeclType(ClassDecl);
QualType ArgType = Context.getRValueReferenceType(ClassType);
@@ -9732,7 +10191,7 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationNameInfo NameInfo(Name, ClassLoc);
- // C++0x [class.copy]p11:
+ // C++11 [class.copy]p11:
// An implicitly-declared copy/move constructor is an inline public
// member of its class.
CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create(
@@ -9743,9 +10202,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
MoveConstructor->setDefaulted();
// Build an exception specification pointing back at this member.
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = MoveConstructor;
+ FunctionProtoType::ExtProtoInfo EPI =
+ getImplicitMethodEPI(*this, MoveConstructor);
MoveConstructor->setType(
Context.getFunctionType(Context.VoidTy, ArgType, EPI));
@@ -9762,16 +10220,9 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
: ClassDecl->hasTrivialMoveConstructor());
- // C++0x [class.copy]p9:
- // If the definition of a class X does not explicitly declare a move
- // constructor, one will be implicitly declared as defaulted if and only if:
- // [...]
- // - the move constructor would not be implicitly defined as deleted.
if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) {
- // Cache this result so that we don't try to generate this over and over
- // on every lookup, leaking memory and wasting time.
- ClassDecl->setFailedImplicitMoveConstructor();
- return 0;
+ ClassDecl->setImplicitMoveConstructorIsDeleted();
+ SetDeclDeleted(MoveConstructor, ClassLoc);
}
// Note that we have declared this constructor.
@@ -9805,15 +10256,12 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
MoveConstructor->setInvalidDecl();
} else {
Sema::CompoundScopeRAII CompoundScope(*this);
- MoveConstructor->setBody(ActOnCompoundStmt(MoveConstructor->getLocation(),
- MoveConstructor->getLocation(),
- MultiStmtArg(),
- /*isStmtExpr=*/false)
- .takeAs<Stmt>());
- MoveConstructor->setImplicitlyDefined(true);
+ MoveConstructor->setBody(ActOnCompoundStmt(
+ MoveConstructor->getLocation(), MoveConstructor->getLocation(), None,
+ /*isStmtExpr=*/ false).takeAs<Stmt>());
}
- MoveConstructor->setUsed();
+ MoveConstructor->markUsed(Context);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(MoveConstructor);
@@ -9821,64 +10269,96 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
}
bool Sema::isImplicitlyDeleted(FunctionDecl *FD) {
- return FD->isDeleted() &&
- (FD->isDefaulted() || FD->isImplicit()) &&
- isa<CXXMethodDecl>(FD);
-}
-
-/// \brief Mark the call operator of the given lambda closure type as "used".
-static void markLambdaCallOperatorUsed(Sema &S, CXXRecordDecl *Lambda) {
- CXXMethodDecl *CallOperator
- = cast<CXXMethodDecl>(
- Lambda->lookup(
- S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).front());
- CallOperator->setReferenced();
- CallOperator->setUsed();
+ return FD->isDeleted() && FD->isDefaulted() && isa<CXXMethodDecl>(FD);
}
void Sema::DefineImplicitLambdaToFunctionPointerConversion(
- SourceLocation CurrentLocation,
- CXXConversionDecl *Conv)
-{
+ SourceLocation CurrentLocation,
+ CXXConversionDecl *Conv) {
CXXRecordDecl *Lambda = Conv->getParent();
+ CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
+ // If we are defining a specialization of a conversion to function-ptr
+ // cache the deduced template arguments for this specialization
+ // so that we can use them to retrieve the corresponding call-operator
+ // and static-invoker.
+ const TemplateArgumentList *DeducedTemplateArgs = 0;
+
- // Make sure that the lambda call operator is marked used.
- markLambdaCallOperatorUsed(*this, Lambda);
-
- Conv->setUsed();
-
+ // Retrieve the corresponding call-operator specialization.
+ if (Lambda->isGenericLambda()) {
+ assert(Conv->isFunctionTemplateSpecialization());
+ FunctionTemplateDecl *CallOpTemplate =
+ CallOp->getDescribedFunctionTemplate();
+ DeducedTemplateArgs = Conv->getTemplateSpecializationArgs();
+ void *InsertPos = 0;
+ FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization(
+ DeducedTemplateArgs->data(),
+ DeducedTemplateArgs->size(),
+ InsertPos);
+ assert(CallOpSpec &&
+ "Conversion operator must have a corresponding call operator");
+ CallOp = cast<CXXMethodDecl>(CallOpSpec);
+ }
+ // Mark the call operator referenced (and add to pending instantiations
+ // if necessary).
+ // For both the conversion and static-invoker template specializations
+ // we construct their body's in this function, so no need to add them
+ // to the PendingInstantiations.
+ MarkFunctionReferenced(CurrentLocation, CallOp);
+
SynthesizedFunctionScope Scope(*this, Conv);
DiagnosticErrorTrap Trap(Diags);
+
+ // Retreive the static invoker...
+ CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker();
+ // ... and get the corresponding specialization for a generic lambda.
+ if (Lambda->isGenericLambda()) {
+ assert(DeducedTemplateArgs &&
+ "Must have deduced template arguments from Conversion Operator");
+ FunctionTemplateDecl *InvokeTemplate =
+ Invoker->getDescribedFunctionTemplate();
+ void *InsertPos = 0;
+ FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization(
+ DeducedTemplateArgs->data(),
+ DeducedTemplateArgs->size(),
+ InsertPos);
+ assert(InvokeSpec &&
+ "Must have a corresponding static invoker specialization");
+ Invoker = cast<CXXMethodDecl>(InvokeSpec);
+ }
+ // Construct the body of the conversion function { return __invoke; }.
+ Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(),
+ VK_LValue, Conv->getLocation()).take();
+ assert(FunctionRef && "Can't refer to __invoke function?");
+ Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take();
+ Conv->setBody(new (Context) CompoundStmt(Context, Return,
+ Conv->getLocation(),
+ Conv->getLocation()));
+
+ Conv->markUsed(Context);
+ Conv->setReferenced();
- // Return the address of the __invoke function.
- DeclarationName InvokeName = &Context.Idents.get("__invoke");
- CXXMethodDecl *Invoke
- = cast<CXXMethodDecl>(Lambda->lookup(InvokeName).front());
- Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(),
- VK_LValue, Conv->getLocation()).take();
- assert(FunctionRef && "Can't refer to __invoke function?");
- Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take();
- Conv->setBody(new (Context) CompoundStmt(Context, Return,
- Conv->getLocation(),
- Conv->getLocation()));
-
// Fill in the __invoke function with a dummy implementation. IR generation
// will fill in the actual details.
- Invoke->setUsed();
- Invoke->setReferenced();
- Invoke->setBody(new (Context) CompoundStmt(Conv->getLocation()));
-
+ Invoker->markUsed(Context);
+ Invoker->setReferenced();
+ Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
+
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Conv);
- L->CompletedImplicitDefinition(Invoke);
- }
+ L->CompletedImplicitDefinition(Invoker);
+ }
}
+
+
void Sema::DefineImplicitLambdaToBlockPointerConversion(
SourceLocation CurrentLocation,
CXXConversionDecl *Conv)
{
- Conv->setUsed();
+ assert(!Conv->getParent()->isGenericLambda());
+
+ Conv->markUsed(Context);
SynthesizedFunctionScope Scope(*this, Conv);
DiagnosticErrorTrap Trap(Diags);
@@ -10057,12 +10537,14 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
SmallVector<Expr *, 8> AllArgs;
bool Invalid = GatherArgumentsForCall(Loc, Constructor,
- Proto, 0, Args, NumArgs, AllArgs,
+ Proto, 0,
+ llvm::makeArrayRef(Args, NumArgs),
+ AllArgs,
CallType, AllowExplicit,
IsListInitialization);
ConvertedArgs.append(AllArgs.begin(), AllArgs.end());
- DiagnoseSentinelCalls(Constructor, Loc, AllArgs.data(), AllArgs.size());
+ DiagnoseSentinelCalls(Constructor, Loc, AllArgs);
CheckConstructorCall(Constructor,
llvm::makeArrayRef<const Expr *>(AllArgs.data(),
@@ -10356,11 +10838,12 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
if (!TpDecl)
TpDecl = FnDecl->getPrimaryTemplate();
- // template <char...> type operator "" name() is the only valid template
- // signature, and the only valid signature with no parameters.
+ // template <char...> type operator "" name() and
+ // template <class T, T...> type operator "" name() are the only valid
+ // template signatures, and the only valid signatures with no parameters.
if (TpDecl) {
if (FnDecl->param_size() == 0) {
- // Must have only one template parameter
+ // Must have one or two template parameters
TemplateParameterList *Params = TpDecl->getTemplateParameters();
if (Params->size() == 1) {
NonTypeTemplateParmDecl *PmDecl =
@@ -10370,6 +10853,27 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
if (PmDecl && PmDecl->isTemplateParameterPack() &&
Context.hasSameType(PmDecl->getType(), Context.CharTy))
Valid = true;
+ } else if (Params->size() == 2) {
+ TemplateTypeParmDecl *PmType =
+ dyn_cast<TemplateTypeParmDecl>(Params->getParam(0));
+ NonTypeTemplateParmDecl *PmArgs =
+ dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(1));
+
+ // The second template parameter must be a parameter pack with the
+ // first template parameter as its type.
+ if (PmType && PmArgs &&
+ !PmType->isTemplateParameterPack() &&
+ PmArgs->isTemplateParameterPack()) {
+ const TemplateTypeParmType *TArgs =
+ PmArgs->getType()->getAs<TemplateTypeParmType>();
+ if (TArgs && TArgs->getDepth() == PmType->getDepth() &&
+ TArgs->getIndex() == PmType->getIndex()) {
+ Valid = true;
+ if (ActiveTemplateInstantiations.empty())
+ Diag(FnDecl->getLocation(),
+ diag::ext_string_literal_operator_template);
+ }
+ }
}
}
} else if (FnDecl->param_size()) {
@@ -10383,7 +10887,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
if (Context.hasSameType(T, Context.UnsignedLongLongTy) ||
Context.hasSameType(T, Context.LongDoubleTy) ||
Context.hasSameType(T, Context.CharTy) ||
- Context.hasSameType(T, Context.WCharTy) ||
+ Context.hasSameType(T, Context.WideCharTy) ||
Context.hasSameType(T, Context.Char16Ty) ||
Context.hasSameType(T, Context.Char32Ty)) {
if (++Param == FnDecl->param_end())
@@ -10413,7 +10917,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
// const char *, const wchar_t*, const char16_t*, and const char32_t*
// are allowed as the first parameter to a two-parameter function
if (!(Context.hasSameType(T, Context.CharTy) ||
- Context.hasSameType(T, Context.WCharTy) ||
+ Context.hasSameType(T, Context.WideCharTy) ||
Context.hasSameType(T, Context.Char16Ty) ||
Context.hasSameType(T, Context.Char32Ty)))
goto FinishedParams;
@@ -10452,7 +10956,8 @@ FinishedParams:
// C++11 [usrlit.suffix]p1:
// Literal suffix identifiers that do not start with an underscore
// are reserved for future standardization.
- Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved);
+ Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved)
+ << NumericLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
}
return false;
@@ -10599,13 +11104,13 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated);
// C++ [except.handle]p16:
- // The object declared in an exception-declaration or, if the
- // exception-declaration does not specify a name, a temporary (12.2) is
+ // The object declared in an exception-declaration or, if the
+ // exception-declaration does not specify a name, a temporary (12.2) is
// copy-initialized (8.5) from the exception object. [...]
// The object is destroyed when the handler exits, after the destruction
// of any automatic objects initialized within the handler.
//
- // We just pretend to initialize the object with itself, then make sure
+ // We just pretend to initialize the object with itself, then make sure
// it can be destroyed later.
QualType initType = ExDeclType;
@@ -10623,7 +11128,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
else {
// If the constructor used was non-trivial, set this as the
// "initializer".
- CXXConstructExpr *construct = cast<CXXConstructExpr>(result.take());
+ CXXConstructExpr *construct = result.takeAs<CXXConstructExpr>();
if (!construct->getConstructor()->isTrivial()) {
Expr *init = MaybeCreateExprWithCleanups(construct);
ExDecl->setInit(init);
@@ -10826,13 +11331,10 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
bool isExplicitSpecialization = false;
bool Invalid = false;
- if (TemplateParameterList *TemplateParams
- = MatchTemplateParametersToScopeSpecifier(TagLoc, NameLoc, SS,
- TempParamLists.data(),
- TempParamLists.size(),
- /*friend*/ true,
- isExplicitSpecialization,
- Invalid)) {
+ if (TemplateParameterList *TemplateParams =
+ MatchTemplateParametersToScopeSpecifier(
+ TagLoc, NameLoc, SS, TempParamLists, /*friend*/ true,
+ isExplicitSpecialization, Invalid)) {
if (TemplateParams->size() > 0) {
// This is a declaration of a class template.
if (Invalid)
@@ -10916,6 +11418,8 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
// Handle the case of a templated-scope friend class. e.g.
// template <class T> class A<T>::B;
// FIXME: we don't support these right now.
+ Diag(NameLoc, diag::warn_template_qualified_friend_unsupported)
+ << SS.getScopeRep() << SS.getRange() << cast<CXXRecordDecl>(CurContext);
ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name);
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
@@ -11080,28 +11584,61 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
ForRedeclaration);
- // FIXME: there are different rules in local classes
+ // There are five cases here.
+ // - There's no scope specifier and we're in a local class. Only look
+ // for functions declared in the immediately-enclosing block scope.
+ // We recover from invalid scope qualifiers as if they just weren't there.
+ FunctionDecl *FunctionContainingLocalClass = 0;
+ if ((SS.isInvalid() || !SS.isSet()) &&
+ (FunctionContainingLocalClass =
+ cast<CXXRecordDecl>(CurContext)->isLocalClass())) {
+ // C++11 [class.friend]p11:
+ // If a friend declaration appears in a local class and the name
+ // specified is an unqualified name, a prior declaration is
+ // looked up without considering scopes that are outside the
+ // innermost enclosing non-class scope. For a friend function
+ // declaration, if there is no prior declaration, the program is
+ // ill-formed.
+
+ // Find the innermost enclosing non-class scope. This is the block
+ // scope containing the local class definition (or for a nested class,
+ // the outer local class).
+ DCScope = S->getFnParent();
+
+ // Look up the function name in the scope.
+ Previous.clear(LookupLocalFriendName);
+ LookupName(Previous, S, /*AllowBuiltinCreation*/false);
+
+ if (!Previous.empty()) {
+ // All possible previous declarations must have the same context:
+ // either they were declared at block scope or they are members of
+ // one of the enclosing local classes.
+ DC = Previous.getRepresentativeDecl()->getDeclContext();
+ } else {
+ // This is ill-formed, but provide the context that we would have
+ // declared the function in, if we were permitted to, for error recovery.
+ DC = FunctionContainingLocalClass;
+ }
+ adjustContextForLocalExternDecl(DC);
+
+ // C++ [class.friend]p6:
+ // A function can be defined in a friend declaration of a class if and
+ // only if the class is a non-local class (9.8), the function name is
+ // unqualified, and the function has namespace scope.
+ if (D.isFunctionDefinition()) {
+ Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class);
+ }
- // There are four cases here.
// - There's no scope specifier, in which case we just go to the
// appropriate scope and look for a function or function template
// there as appropriate.
- // Recover from invalid scope qualifiers as if they just weren't there.
- if (SS.isInvalid() || !SS.isSet()) {
- // C++0x [namespace.memdef]p3:
+ } else if (SS.isInvalid() || !SS.isSet()) {
+ // C++11 [namespace.memdef]p3:
// If the name in a friend declaration is neither qualified nor
// a template-id and the declaration is a function or an
// elaborated-type-specifier, the lookup to determine whether
// the entity has been previously declared shall not consider
// any scopes outside the innermost enclosing namespace.
- // C++0x [class.friend]p11:
- // If a friend declaration appears in a local class and the name
- // specified is an unqualified name, a prior declaration is
- // looked up without considering scopes that are outside the
- // innermost enclosing non-class scope. For a friend function
- // declaration, if there is no prior declaration, the program is
- // ill-formed.
- bool isLocal = cast<CXXRecordDecl>(CurContext)->isLocalClass();
bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId;
// Find the appropriate context according to the above.
@@ -11124,10 +11661,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
while (true) {
LookupQualifiedName(Previous, LookupDC);
- // TODO: decide what we think about using declarations.
- if (isLocal)
- break;
-
if (!Previous.empty()) {
DC = LookupDC;
break;
@@ -11142,15 +11675,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
}
DCScope = getScopeForDeclContext(S, DC);
-
- // C++ [class.friend]p6:
- // A function can be defined in a friend declaration of a class if and
- // only if the class is a non-local class (9.8), the function name is
- // unqualified, and the function has namespace scope.
- if (isLocal && D.isFunctionDefinition()) {
- Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class);
- }
-
+
// - There's a non-dependent scope specifier, in which case we
// compute it and do a previous lookup there for a function
// or function template.
@@ -11242,15 +11767,18 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
FakeDCScope.setEntity(DC);
DCScope = &FakeDCScope;
}
-
+
bool AddToScope = true;
NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous,
TemplateParams, AddToScope);
if (!ND) return 0;
- assert(ND->getDeclContext() == DC);
assert(ND->getLexicalDeclContext() == CurContext);
+ // If we performed typo correction, we might have added a scope specifier
+ // and changed the decl context.
+ DC = ND->getDeclContext();
+
// Add the function declaration to the appropriate lookup tables,
// adjusting the redeclarations list as necessary. We don't
// want to do this yet if the friending class is dependent.
@@ -11281,6 +11809,18 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
else
FD = cast<FunctionDecl>(ND);
+ // C++11 [dcl.fct.default]p4: If a friend declaration specifies a
+ // default argument expression, that declaration shall be a definition
+ // and shall be the only declaration of the function or function
+ // template in the translation unit.
+ if (functionDeclHasDefaultArgument(FD)) {
+ if (FunctionDecl *OldFD = FD->getPreviousDecl()) {
+ Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
+ Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ } else if (!D.isFunctionDefinition())
+ Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_must_be_def);
+ }
+
// Mark templated-scope function declarations as unsupported.
if (FD->getNumTemplateParameterLists())
FrD->setUnsupportedFriend(true);
@@ -11346,7 +11886,8 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
CXXSpecialMember Member = getSpecialMember(MD);
if (Member == CXXInvalid) {
- Diag(DefaultLoc, diag::err_default_special_members);
+ if (!MD->isInvalidDecl())
+ Diag(DefaultLoc, diag::err_default_special_members);
return;
}
@@ -11374,47 +11915,29 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
ResolveExceptionSpec(DefaultLoc,
MD->getType()->castAs<FunctionProtoType>());
+ if (MD->isInvalidDecl())
+ return;
+
switch (Member) {
- case CXXDefaultConstructor: {
- CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
- if (!CD->isInvalidDecl())
- DefineImplicitDefaultConstructor(DefaultLoc, CD);
+ case CXXDefaultConstructor:
+ DefineImplicitDefaultConstructor(DefaultLoc,
+ cast<CXXConstructorDecl>(MD));
break;
- }
-
- case CXXCopyConstructor: {
- CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
- if (!CD->isInvalidDecl())
- DefineImplicitCopyConstructor(DefaultLoc, CD);
+ case CXXCopyConstructor:
+ DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD));
break;
- }
-
- case CXXCopyAssignment: {
- if (!MD->isInvalidDecl())
- DefineImplicitCopyAssignment(DefaultLoc, MD);
+ case CXXCopyAssignment:
+ DefineImplicitCopyAssignment(DefaultLoc, MD);
break;
- }
-
- case CXXDestructor: {
- CXXDestructorDecl *DD = cast<CXXDestructorDecl>(MD);
- if (!DD->isInvalidDecl())
- DefineImplicitDestructor(DefaultLoc, DD);
+ case CXXDestructor:
+ DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(MD));
break;
- }
-
- case CXXMoveConstructor: {
- CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
- if (!CD->isInvalidDecl())
- DefineImplicitMoveConstructor(DefaultLoc, CD);
+ case CXXMoveConstructor:
+ DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD));
break;
- }
-
- case CXXMoveAssignment: {
- if (!MD->isInvalidDecl())
- DefineImplicitMoveAssignment(DefaultLoc, MD);
+ case CXXMoveAssignment:
+ DefineImplicitMoveAssignment(DefaultLoc, MD);
break;
- }
-
case CXXInvalid:
llvm_unreachable("Invalid special member.");
}
@@ -11454,27 +11977,11 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
if (NewCC == OldCC)
return false;
- // If either of the calling conventions are set to "default", we need to pick
- // something more sensible based on the target. This supports code where the
- // one method explicitly sets thiscall, and another has no explicit calling
- // convention.
- CallingConv Default =
- Context.getTargetInfo().getDefaultCallingConv(TargetInfo::CCMT_Member);
- if (NewCC == CC_Default)
- NewCC = Default;
- if (OldCC == CC_Default)
- OldCC = Default;
-
- // If the calling conventions still don't match, then report the error
- if (NewCC != OldCC) {
- Diag(New->getLocation(),
- diag::err_conflicting_overriding_cc_attributes)
- << New->getDeclName() << New->getType() << Old->getType();
- Diag(Old->getLocation(), diag::note_overridden_virtual_function);
- return true;
- }
-
- return false;
+ Diag(New->getLocation(),
+ diag::err_conflicting_overriding_cc_attributes)
+ << New->getDeclName() << New->getType() << Old->getType();
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ return true;
}
bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
@@ -11595,13 +12102,13 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) {
}
/// \brief Determine whether the given declaration is a static data member.
-static bool isStaticDataMember(Decl *D) {
- VarDecl *Var = dyn_cast_or_null<VarDecl>(D);
- if (!Var)
- return false;
-
- return Var->isStaticDataMember();
+static bool isStaticDataMember(const Decl *D) {
+ if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
+ return Var->isStaticDataMember();
+
+ return false;
}
+
/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse
/// an initializer for the out-of-line declaration 'Dcl'. The scope
/// is a fresh scope pushed for just this purpose.
@@ -11744,19 +12251,14 @@ bool Sema::DefineUsedVTables() {
// vtable even though we're using it.
const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(Class);
if (KeyFunction && !KeyFunction->hasBody()) {
- switch (KeyFunction->getTemplateSpecializationKind()) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- case TSK_ExplicitInstantiationDeclaration:
- // The key function is in another translation unit.
- DefineVTable = false;
- break;
-
- case TSK_ExplicitInstantiationDefinition:
- case TSK_ImplicitInstantiation:
- // We will be instantiating the key function.
- break;
- }
+ // The key function is in another translation unit.
+ DefineVTable = false;
+ TemplateSpecializationKind TSK =
+ KeyFunction->getTemplateSpecializationKind();
+ assert(TSK != TSK_ExplicitInstantiationDefinition &&
+ TSK != TSK_ImplicitInstantiation &&
+ "Instantiations don't have key functions");
+ (void)TSK;
} else if (!KeyFunction) {
// If we have a class with no key function that is the subject
// of an explicit instantiation declaration, suppress the
@@ -11799,7 +12301,7 @@ bool Sema::DefineUsedVTables() {
Consumer.HandleVTable(Class, VTablesUsed[Canonical]);
// Optionally warn if we're emitting a weak vtable.
- if (Class->hasExternalLinkage() &&
+ if (Class->isExternallyVisible() &&
Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
const FunctionDecl *KeyFunctionDef = 0;
if (!KeyFunction ||
@@ -11920,8 +12422,6 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
llvm::SmallSet<CXXConstructorDecl*, 4> &Invalid,
llvm::SmallSet<CXXConstructorDecl*, 4> &Current,
Sema &S) {
- llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(),
- CE = Current.end();
if (Ctor->isInvalidDecl())
return;
@@ -11946,8 +12446,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
// We know that beyond here, we aren't chaining into a cycle.
if (!Target || !Target->isDelegatingConstructor() ||
Target->isInvalidDecl() || Valid.count(TCanonical)) {
- for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI)
- Valid.insert(*CI);
+ Valid.insert(Current.begin(), Current.end());
Current.clear();
// We've hit a cycle.
} else if (TCanonical == Canonical || Invalid.count(TCanonical) ||
@@ -11974,8 +12473,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
}
}
- for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI)
- Invalid.insert(*CI);
+ Invalid.insert(Current.begin(), Current.end());
Current.clear();
} else {
DelegatingCycleHelper(Target, Valid, Invalid, Current, S);
@@ -11986,16 +12484,15 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
void Sema::CheckDelegatingCtorCycles() {
llvm::SmallSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;
- llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(),
- CE = Current.end();
-
for (DelegatingCtorDeclsType::iterator
I = DelegatingCtorDecls.begin(ExternalSource),
E = DelegatingCtorDecls.end();
I != E; ++I)
DelegatingCycleHelper(*I, Valid, Invalid, Current, *this);
- for (CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI)
+ for (llvm::SmallSet<CXXConstructorDecl *, 4>::iterator CI = Invalid.begin(),
+ CE = Invalid.end();
+ CI != CE; ++CI)
(*CI)->setInvalidDecl();
}
@@ -12211,8 +12708,7 @@ Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
if (D->hasAttr<CUDADeviceAttr>()) {
if (D->hasAttr<CUDAHostAttr>())
return CFT_HostDevice;
- else
- return CFT_Device;
+ return CFT_Device;
}
return CFT_Host;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
index f33e7bcb1671..f44fb3251141 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
@@ -324,15 +324,15 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope);
PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope);
+ // The ObjC parser requires parameter names so there's no need to check.
+ CheckParmsForFunctionDef(MDecl->param_begin(), MDecl->param_end(),
+ /*CheckParameterNames=*/false);
+
// Introduce all of the other parameters into this scope.
for (ObjCMethodDecl::param_iterator PI = MDecl->param_begin(),
E = MDecl->param_end(); PI != E; ++PI) {
ParmVarDecl *Param = (*PI);
if (!Param->isInvalidDecl() &&
- RequireCompleteType(Param->getLocation(), Param->getType(),
- diag::err_typecheck_decl_incomplete_type))
- Param->setInvalidDecl();
- if (!Param->isInvalidDecl() &&
getLangOpts().ObjCAutoRefCount &&
!HasExplicitOwnershipAttr(*this, Param))
Diag(Param->getLocation(), diag::warn_arc_strong_pointer_objc_pointer) <<
@@ -350,7 +350,7 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
case OMF_release:
case OMF_autorelease:
Diag(MDecl->getLocation(), diag::err_arc_illegal_method_def)
- << MDecl->getSelector();
+ << 0 << MDecl->getSelector();
break;
case OMF_None:
@@ -459,6 +459,23 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
// Create a declaration to describe this @interface.
ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+
+ if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) {
+ // A previous decl with a different name is because of
+ // @compatibility_alias, for example:
+ // \code
+ // @class NewImage;
+ // @compatibility_alias OldImage NewImage;
+ // \endcode
+ // A lookup for 'OldImage' will return the 'NewImage' decl.
+ //
+ // In such a case use the real declaration name, instead of the alias one,
+ // otherwise we will break IdentifierResolver and redecls-chain invariants.
+ // FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl
+ // has been aliased.
+ ClassName = PrevIDecl->getIdentifier();
+ }
+
ObjCInterfaceDecl *IDecl
= ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName,
PrevIDecl, ClassLoc);
@@ -494,11 +511,9 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
if (TypoCorrection Corrected = CorrectTypo(
DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope,
NULL, Validator)) {
+ diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
+ << SuperName << ClassName);
PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
- Diag(SuperLoc, diag::err_undef_superclass_suggest)
- << SuperName << ClassName << PrevDecl->getDeclName();
- Diag(PrevDecl->getLocation(), diag::note_previous_decl)
- << PrevDecl->getDeclName();
}
}
@@ -575,6 +590,29 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
return ActOnObjCContainerStartDefinition(IDecl);
}
+/// ActOnTypedefedProtocols - this action finds protocol list as part of the
+/// typedef'ed use for a qualified super class and adds them to the list
+/// of the protocols.
+void Sema::ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
+ IdentifierInfo *SuperName,
+ SourceLocation SuperLoc) {
+ if (!SuperName)
+ return;
+ NamedDecl* IDecl = LookupSingleName(TUScope, SuperName, SuperLoc,
+ LookupOrdinaryName);
+ if (!IDecl)
+ return;
+
+ if (const TypedefNameDecl *TDecl = dyn_cast_or_null<TypedefNameDecl>(IDecl)) {
+ QualType T = TDecl->getUnderlyingType();
+ if (T->isObjCObjectType())
+ if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>())
+ for (ObjCObjectType::qual_iterator I = OPT->qual_begin(),
+ E = OPT->qual_end(); I != E; ++I)
+ ProtocolRefs.push_back(*I);
+ }
+}
+
/// ActOnCompatibilityAlias - this action is called after complete parsing of
/// a \@compatibility_alias declaration. It sets up the alias relationships.
Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc,
@@ -586,10 +624,7 @@ Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc,
NamedDecl *ADecl = LookupSingleName(TUScope, AliasName, AliasLocation,
LookupOrdinaryName, ForRedeclaration);
if (ADecl) {
- if (isa<ObjCCompatibleAliasDecl>(ADecl))
- Diag(AliasLocation, diag::warn_previous_alias_decl);
- else
- Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName;
+ Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName;
Diag(ADecl->getLocation(), diag::note_previous_declaration);
return 0;
}
@@ -732,12 +767,9 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
TypoCorrection Corrected = CorrectTypo(
DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second),
LookupObjCProtocolName, TUScope, NULL, Validator);
- if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) {
- Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest)
- << ProtocolId[i].first << Corrected.getCorrection();
- Diag(PDecl->getLocation(), diag::note_previous_decl)
- << PDecl->getDeclName();
- }
+ if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>()))
+ diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest)
+ << ProtocolId[i].first);
}
if (!PDecl) {
@@ -819,7 +851,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
DeclsInGroup.push_back(PDecl);
}
- return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false);
+ return BuildDeclaratorGroup(DeclsInGroup, false);
}
Decl *Sema::
@@ -935,6 +967,7 @@ Decl *Sema::ActOnStartCategoryImplementation(
<< CatName;
Diag(CatIDecl->getImplementation()->getLocation(),
diag::note_previous_definition);
+ CDecl->setInvalidDecl();
} else {
CatIDecl->setImplementation(CDecl);
// Warn on implementating category of deprecated class under
@@ -954,7 +987,7 @@ Decl *Sema::ActOnStartClassImplementation(
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperClassname,
SourceLocation SuperClassLoc) {
- ObjCInterfaceDecl* IDecl = 0;
+ ObjCInterfaceDecl *IDecl = 0;
// Check for another declaration kind with the same name.
NamedDecl *PrevDecl
= LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName,
@@ -966,24 +999,19 @@ Decl *Sema::ActOnStartClassImplementation(
RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
diag::warn_undef_interface);
} else {
- // We did not find anything with the name ClassName; try to correct for
+ // We did not find anything with the name ClassName; try to correct for
// typos in the class name.
ObjCInterfaceValidatorCCC Validator;
- if (TypoCorrection Corrected = CorrectTypo(
- DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope,
- NULL, Validator)) {
- // Suggest the (potentially) correct interface name. However, put the
- // fix-it hint itself in a separate note, since changing the name in
- // the warning would make the fix-it change semantics.However, don't
- // provide a code-modification hint or use the typo name for recovery,
- // because this is just a warning. The program may actually be correct.
- IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
- DeclarationName CorrectedName = Corrected.getCorrection();
- Diag(ClassLoc, diag::warn_undef_interface_suggest)
- << ClassName << CorrectedName;
- Diag(IDecl->getLocation(), diag::note_previous_decl) << CorrectedName
- << FixItHint::CreateReplacement(ClassLoc, CorrectedName.getAsString());
- IDecl = 0;
+ TypoCorrection Corrected =
+ CorrectTypo(DeclarationNameInfo(ClassName, ClassLoc),
+ LookupOrdinaryName, TUScope, NULL, Validator);
+ if (Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
+ // Suggest the (potentially) correct interface name. Don't provide a
+ // code-modification hint or use the typo name for recovery, because
+ // this is just a warning. The program may actually be correct.
+ diagnoseTypo(Corrected,
+ PDiag(diag::warn_undef_interface_suggest) << ClassName,
+ /*ErrorRecovery*/false);
} else {
Diag(ClassLoc, diag::warn_undef_interface) << ClassName;
}
@@ -1056,6 +1084,7 @@ Decl *Sema::ActOnStartClassImplementation(
Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;
Diag(IDecl->getImplementation()->getLocation(),
diag::note_previous_definition);
+ IMPDecl->setInvalidDecl();
} else { // add it to the list.
IDecl->setImplementation(IMPDecl);
PushOnScopeChains(IMPDecl, TUScope);
@@ -1084,7 +1113,7 @@ Sema::ActOnFinishObjCImplementation(Decl *ObjCImpDecl, ArrayRef<Decl *> Decls) {
DeclsInGroup.push_back(ObjCImpDecl);
- return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false);
+ return BuildDeclaratorGroup(DeclsInGroup, false);
}
void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
@@ -1124,6 +1153,19 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
Diag(ClsIvar->getLocation(), diag::note_previous_definition);
continue;
}
+ // Check class extensions (unnamed categories) for duplicate ivars.
+ for (ObjCInterfaceDecl::visible_extensions_iterator
+ Ext = IDecl->visible_extensions_begin(),
+ ExtEnd = IDecl->visible_extensions_end();
+ Ext != ExtEnd; ++Ext) {
+ ObjCCategoryDecl *CDecl = *Ext;
+ if (const ObjCIvarDecl *ClsExtIvar =
+ CDecl->getIvarDecl(ImplIvar->getIdentifier())) {
+ Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);
+ Diag(ClsExtIvar->getLocation(), diag::note_previous_definition);
+ continue;
+ }
+ }
// Instance ivar to Implementation's DeclContext.
ImplIvar->setLexicalDeclContext(ImpDecl);
IDecl->makeDeclVisibleInContext(ImplIvar);
@@ -1469,8 +1511,8 @@ static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl,
reasonSelector = R_NonObjectReturn;
}
- S.Diag(impl->getLocation(), errorID) << familySelector << reasonSelector;
- S.Diag(decl->getLocation(), noteID) << familySelector << reasonSelector;
+ S.Diag(impl->getLocation(), errorID) << int(familySelector) << int(reasonSelector);
+ S.Diag(decl->getLocation(), noteID) << int(familySelector) << int(reasonSelector);
return true;
}
@@ -1689,9 +1731,8 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
// implemented in the implementation class. If so, their types match.
for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(),
E = CDecl->instmeth_end(); I != E; ++I) {
- if (InsMapSeen.count((*I)->getSelector()))
- continue;
- InsMapSeen.insert((*I)->getSelector());
+ if (!InsMapSeen.insert((*I)->getSelector()))
+ continue;
if (!(*I)->isPropertyAccessor() &&
!InsMap.count((*I)->getSelector())) {
if (ImmediateClass)
@@ -1718,11 +1759,11 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
// Check and see if class methods in class interface have been
// implemented in the implementation class. If so, their types match.
- for (ObjCInterfaceDecl::classmeth_iterator
- I = CDecl->classmeth_begin(), E = CDecl->classmeth_end(); I != E; ++I) {
- if (ClsMapSeen.count((*I)->getSelector()))
- continue;
- ClsMapSeen.insert((*I)->getSelector());
+ for (ObjCInterfaceDecl::classmeth_iterator I = CDecl->classmeth_begin(),
+ E = CDecl->classmeth_end();
+ I != E; ++I) {
+ if (!ClsMapSeen.insert((*I)->getSelector()))
+ continue;
if (!ClsMap.count((*I)->getSelector())) {
if (ImmediateClass)
WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl,
@@ -1742,6 +1783,16 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
}
}
+ if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl> (CDecl)) {
+ // Also, check for methods declared in protocols inherited by
+ // this protocol.
+ for (ObjCProtocolDecl::protocol_iterator
+ PI = PD->protocol_begin(), E = PD->protocol_end(); PI != E; ++PI)
+ MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+ IMPDecl, (*PI), IncompleteImpl, false,
+ WarnCategoryMethodImpl);
+ }
+
if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
// when checking that methods in implementation match their declaration,
// i.e. when WarnCategoryMethodImpl is false, check declarations in class
@@ -1901,13 +1952,6 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
NamedDecl *PrevDecl
= LookupSingleName(TUScope, IdentList[i], IdentLocs[i],
LookupOrdinaryName, ForRedeclaration);
- if (PrevDecl && PrevDecl->isTemplateParameter()) {
- // Maybe we will complain about the shadowed template parameter.
- DiagnoseTemplateParameterShadow(AtClassLoc, PrevDecl);
- // Just pretend that we didn't see the previous declaration.
- PrevDecl = 0;
- }
-
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
// GCC apparently allows the following idiom:
//
@@ -1936,17 +1980,35 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
// Create a declaration to describe this forward declaration.
ObjCInterfaceDecl *PrevIDecl
= dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+
+ IdentifierInfo *ClassName = IdentList[i];
+ if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) {
+ // A previous decl with a different name is because of
+ // @compatibility_alias, for example:
+ // \code
+ // @class NewImage;
+ // @compatibility_alias OldImage NewImage;
+ // \endcode
+ // A lookup for 'OldImage' will return the 'NewImage' decl.
+ //
+ // In such a case use the real declaration name, instead of the alias one,
+ // otherwise we will break IdentifierResolver and redecls-chain invariants.
+ // FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl
+ // has been aliased.
+ ClassName = PrevIDecl->getIdentifier();
+ }
+
ObjCInterfaceDecl *IDecl
= ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
- IdentList[i], PrevIDecl, IdentLocs[i]);
+ ClassName, PrevIDecl, IdentLocs[i]);
IDecl->setAtEndRange(IdentLocs[i]);
PushOnScopeChains(IDecl, TUScope);
CheckObjCDeclScope(IDecl);
DeclsInGroup.push_back(IDecl);
}
-
- return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false);
+
+ return BuildDeclaratorGroup(DeclsInGroup, false);
}
static bool tryMatchRecordTypes(ASTContext &Context,
@@ -2093,6 +2155,10 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) {
// signature.
ObjCMethodList *Previous = List;
for (; List; Previous = List, List = List->getNext()) {
+ // If we are building a module, keep all of the methods.
+ if (getLangOpts().Modules && !getLangOpts().CurrentModule.empty())
+ continue;
+
if (!MatchTwoMethodDeclarations(Method, List->Method))
continue;
@@ -2182,7 +2248,7 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
// Gather the non-hidden methods.
ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
- llvm::SmallVector<ObjCMethodDecl *, 4> Methods;
+ SmallVector<ObjCMethodDecl *, 4> Methods;
for (ObjCMethodList *M = &MethList; M; M = M->getNext()) {
if (M->Method && !M->Method->isHidden()) {
// If we're not supposed to warn about mismatches, we're done.
@@ -2269,7 +2335,140 @@ ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
return 0;
}
-/// DiagnoseDuplicateIvars -
+static void
+HelperSelectorsForTypoCorrection(
+ SmallVectorImpl<const ObjCMethodDecl *> &BestMethod,
+ StringRef Typo, const ObjCMethodDecl * Method) {
+ const unsigned MaxEditDistance = 1;
+ unsigned BestEditDistance = MaxEditDistance + 1;
+ std::string MethodName = Method->getSelector().getAsString();
+
+ unsigned MinPossibleEditDistance = abs((int)MethodName.size() - (int)Typo.size());
+ if (MinPossibleEditDistance > 0 &&
+ Typo.size() / MinPossibleEditDistance < 1)
+ return;
+ unsigned EditDistance = Typo.edit_distance(MethodName, true, MaxEditDistance);
+ if (EditDistance > MaxEditDistance)
+ return;
+ if (EditDistance == BestEditDistance)
+ BestMethod.push_back(Method);
+ else if (EditDistance < BestEditDistance) {
+ BestMethod.clear();
+ BestMethod.push_back(Method);
+ }
+}
+
+static bool HelperIsMethodInObjCType(Sema &S, Selector Sel,
+ QualType ObjectType) {
+ if (ObjectType.isNull())
+ return true;
+ if (S.LookupMethodInObjectType(Sel, ObjectType, true/*Instance method*/))
+ return true;
+ return S.LookupMethodInObjectType(Sel, ObjectType, false/*Class method*/) != 0;
+}
+
+const ObjCMethodDecl *
+Sema::SelectorsForTypoCorrection(Selector Sel,
+ QualType ObjectType) {
+ unsigned NumArgs = Sel.getNumArgs();
+ SmallVector<const ObjCMethodDecl *, 8> Methods;
+ bool ObjectIsId = true, ObjectIsClass = true;
+ if (ObjectType.isNull())
+ ObjectIsId = ObjectIsClass = false;
+ else if (!ObjectType->isObjCObjectPointerType())
+ return 0;
+ else if (const ObjCObjectPointerType *ObjCPtr =
+ ObjectType->getAsObjCInterfacePointerType()) {
+ ObjectType = QualType(ObjCPtr->getInterfaceType(), 0);
+ ObjectIsId = ObjectIsClass = false;
+ }
+ else if (ObjectType->isObjCIdType() || ObjectType->isObjCQualifiedIdType())
+ ObjectIsClass = false;
+ else if (ObjectType->isObjCClassType() || ObjectType->isObjCQualifiedClassType())
+ ObjectIsId = false;
+ else
+ return 0;
+
+ for (GlobalMethodPool::iterator b = MethodPool.begin(),
+ e = MethodPool.end(); b != e; b++) {
+ // instance methods
+ for (ObjCMethodList *M = &b->second.first; M; M=M->getNext())
+ if (M->Method &&
+ (M->Method->getSelector().getNumArgs() == NumArgs) &&
+ (M->Method->getSelector() != Sel)) {
+ if (ObjectIsId)
+ Methods.push_back(M->Method);
+ else if (!ObjectIsClass &&
+ HelperIsMethodInObjCType(*this, M->Method->getSelector(), ObjectType))
+ Methods.push_back(M->Method);
+ }
+ // class methods
+ for (ObjCMethodList *M = &b->second.second; M; M=M->getNext())
+ if (M->Method &&
+ (M->Method->getSelector().getNumArgs() == NumArgs) &&
+ (M->Method->getSelector() != Sel)) {
+ if (ObjectIsClass)
+ Methods.push_back(M->Method);
+ else if (!ObjectIsId &&
+ HelperIsMethodInObjCType(*this, M->Method->getSelector(), ObjectType))
+ Methods.push_back(M->Method);
+ }
+ }
+
+ SmallVector<const ObjCMethodDecl *, 8> SelectedMethods;
+ for (unsigned i = 0, e = Methods.size(); i < e; i++) {
+ HelperSelectorsForTypoCorrection(SelectedMethods,
+ Sel.getAsString(), Methods[i]);
+ }
+ return (SelectedMethods.size() == 1) ? SelectedMethods[0] : NULL;
+}
+
+static void
+HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,
+ ObjCMethodList &MethList) {
+ ObjCMethodList *M = &MethList;
+ ObjCMethodDecl *TargetMethod = M->Method;
+ while (TargetMethod &&
+ isa<ObjCImplDecl>(TargetMethod->getDeclContext())) {
+ M = M->getNext();
+ TargetMethod = M ? M->Method : 0;
+ }
+ if (!TargetMethod)
+ return;
+ bool FirstTime = true;
+ for (M = M->getNext(); M; M=M->getNext()) {
+ ObjCMethodDecl *MatchingMethodDecl = M->Method;
+ if (isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext()))
+ continue;
+ if (!S.MatchTwoMethodDeclarations(TargetMethod,
+ MatchingMethodDecl, Sema::MMS_loose)) {
+ if (FirstTime) {
+ FirstTime = false;
+ S.Diag(TargetMethod->getLocation(), diag::warning_multiple_selectors)
+ << TargetMethod->getSelector();
+ }
+ S.Diag(MatchingMethodDecl->getLocation(), diag::note_also_found);
+ }
+ }
+}
+
+void Sema::DiagnoseMismatchedMethodsInGlobalPool() {
+ unsigned DIAG = diag::warning_multiple_selectors;
+ if (Diags.getDiagnosticLevel(DIAG, SourceLocation())
+ == DiagnosticsEngine::Ignored)
+ return;
+ for (GlobalMethodPool::iterator b = MethodPool.begin(),
+ e = MethodPool.end(); b != e; b++) {
+ // first, instance methods
+ ObjCMethodList &InstMethList = b->second.first;
+ HelperToDiagnoseMismatchedMethodsInGlobalPool(*this, InstMethList);
+ // second, class methods
+ ObjCMethodList &ClsMethList = b->second.second;
+ HelperToDiagnoseMismatchedMethodsInGlobalPool(*this, ClsMethList);
+ }
+}
+
+/// DiagnoseDuplicateIvars -
/// Check for duplicate ivars in the entire class at the start of
/// \@implementation. This becomes necesssary because class extension can
/// add ivars to a class in random order which will not be known until
@@ -2313,13 +2512,9 @@ Sema::ObjCContainerKind Sema::getObjCContainerKind() const {
}
}
-// Note: For class/category implemenations, allMethods/allProperties is
-// always null.
-Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
- Decl **allMethods, unsigned allNum,
- Decl **allProperties, unsigned pNum,
- DeclGroupPtrTy *allTUVars, unsigned tuvNum) {
-
+// Note: For class/category implementations, allMethods is always null.
+Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
+ ArrayRef<DeclGroupPtrTy> allTUVars) {
if (getObjCContainerKind() == Sema::OCK_None)
return 0;
@@ -2337,7 +2532,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;
- for (unsigned i = 0; i < allNum; i++ ) {
+ for (unsigned i = 0, e = allMethods.size(); i != e; i++ ) {
ObjCMethodDecl *Method =
cast_or_null<ObjCMethodDecl>(allMethods[i]);
@@ -2504,8 +2699,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
}
if (isInterfaceDeclKind) {
// Reject invalid vardecls.
- for (unsigned i = 0; i != tuvNum; i++) {
- DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>();
+ for (unsigned i = 0, e = allTUVars.size(); i != e; i++) {
+ DeclGroupRef DG = allTUVars[i].get();
for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) {
if (!VDecl->hasExternalStorage())
@@ -2515,8 +2710,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
}
ActOnObjCContainerFinishDefinition();
- for (unsigned i = 0; i != tuvNum; i++) {
- DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>();
+ for (unsigned i = 0, e = allTUVars.size(); i != e; i++) {
+ DeclGroupRef DG = allTUVars[i].get();
for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
(*I)->setTopLevelDeclInObjCContainer();
Consumer.HandleTopLevelDeclInObjCContainer(DG);
@@ -2911,14 +3106,9 @@ Decl *Sema::ActOnMethodDeclaration(
if (ReturnType) {
resultDeclType = GetTypeFromParser(ReturnType, &ResultTInfo);
- // Methods cannot return interface types. All ObjC objects are
- // passed by reference.
- if (resultDeclType->isObjCObjectType()) {
- Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value)
- << 0 << resultDeclType;
+ if (CheckFunctionReturnType(resultDeclType, MethodLoc))
return 0;
- }
-
+
HasRelatedResultType = (resultDeclType == Context.getObjCInstanceType());
} else { // get the type for "id".
resultDeclType = Context.getObjCIdType();
@@ -2945,7 +3135,7 @@ Decl *Sema::ActOnMethodDeclaration(
QualType ArgType;
TypeSourceInfo *DI;
- if (ArgInfo[i].Type == 0) {
+ if (!ArgInfo[i].Type) {
ArgType = Context.getObjCIdType();
DI = 0;
} else {
@@ -3001,14 +3191,8 @@ Decl *Sema::ActOnMethodDeclaration(
else
// Perform the default array/function conversions (C99 6.7.5.3p[7,8]).
ArgType = Context.getAdjustedParameterType(ArgType);
- if (ArgType->isObjCObjectType()) {
- Diag(Param->getLocation(),
- diag::err_object_cannot_be_passed_returned_by_value)
- << 1 << ArgType;
- Param->setInvalidDecl();
- }
+
Param->setDeclContext(ObjCMethod);
-
Params.push_back(Param);
}
@@ -3034,6 +3218,12 @@ Decl *Sema::ActOnMethodDeclaration(
if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface())
IMD = IDecl->lookupMethod(ObjCMethod->getSelector(),
ObjCMethod->isInstanceMethod());
+ if (IMD && IMD->hasAttr<ObjCRequiresSuperAttr>() &&
+ !ObjCMethod->hasAttr<ObjCRequiresSuperAttr>()) {
+ // merge the attribute into implementation.
+ ObjCMethod->addAttr(
+ new (Context) ObjCRequiresSuperAttr(ObjCMethod->getLocation(), Context));
+ }
if (ObjCMethod->hasAttrs() &&
containsInvalidMethodImplAttribute(IMD, ObjCMethod->getAttrs())) {
SourceLocation MethodLoc = IMD->getLocation();
@@ -3052,6 +3242,8 @@ Decl *Sema::ActOnMethodDeclaration(
Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl)
<< ObjCMethod->getDeclName();
Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+ ObjCMethod->setInvalidDecl();
+ return ObjCMethod;
}
// If this Objective-C method does not have a related result type, but we
@@ -3290,6 +3482,8 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() {
ReferencedSelectors[Sels[I].first] = Sels[I].second;
}
+ DiagnoseMismatchedMethodsInGlobalPool();
+
// Warning will be issued only when selector table is
// generated (which means there is at lease one implementation
// in the TU). This is to match gcc's behavior.
@@ -3305,3 +3499,43 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() {
}
return;
}
+
+ObjCIvarDecl *
+Sema::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
+ const ObjCPropertyDecl *&PDecl) const {
+
+ const ObjCInterfaceDecl *IDecl = Method->getClassInterface();
+ if (!IDecl)
+ return 0;
+ Method = IDecl->lookupMethod(Method->getSelector(), true);
+ if (!Method || !Method->isPropertyAccessor())
+ return 0;
+ if ((PDecl = Method->findPropertyDecl())) {
+ if (!PDecl->getDeclContext())
+ return 0;
+ // Make sure property belongs to accessor's class and not to
+ // one of its super classes.
+ if (const ObjCInterfaceDecl *CID =
+ dyn_cast<ObjCInterfaceDecl>(PDecl->getDeclContext()))
+ if (CID != IDecl)
+ return 0;
+ return PDecl->getPropertyIvarDecl();
+ }
+ return 0;
+}
+
+void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S) {
+ if (S->hasUnrecoverableErrorOccurred() || !S->isInObjcMethodScope())
+ return;
+
+ const ObjCMethodDecl *CurMethod = getCurMethodDecl();
+ if (!CurMethod)
+ return;
+ const ObjCPropertyDecl *PDecl;
+ const ObjCIvarDecl *IV = GetIvarBackingPropertyAccessor(CurMethod, PDecl);
+ if (IV && !IV->getBackingIvarReferencedInAccessor()) {
+ Diag(getCurMethodDecl()->getLocation(), diag::warn_unused_property_backing_ivar)
+ << IV->getDeclName();
+ Diag(PDecl->getLocation(), diag::note_property_declare);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
index 1a5f4824d091..3e8f324027dc 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -181,13 +181,13 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
return false;
}
- // The failure was something other than an empty exception
+ // The failure was something other than an missing exception
// specification; return an error.
- if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification)
+ if (!MissingExceptionSpecification)
return true;
const FunctionProtoType *NewProto =
- New->getType()->getAs<FunctionProtoType>();
+ New->getType()->castAs<FunctionProtoType>();
// The new function declaration is only missing an empty exception
// specification "throw()". If the throw() specification came from a
@@ -203,123 +203,94 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
Old->isExternC()) {
FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
EPI.ExceptionSpecType = EST_DynamicNone;
- QualType NewType =
- Context.getFunctionType(NewProto->getResultType(),
- ArrayRef<QualType>(NewProto->arg_type_begin(),
- NewProto->getNumArgs()),
- EPI);
+ QualType NewType = Context.getFunctionType(NewProto->getResultType(),
+ NewProto->getArgTypes(), EPI);
New->setType(NewType);
return false;
}
- if (MissingExceptionSpecification && NewProto) {
- const FunctionProtoType *OldProto =
- Old->getType()->getAs<FunctionProtoType>();
-
- FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
- 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.
- QualType NewType =
- Context.getFunctionType(NewProto->getResultType(),
- ArrayRef<QualType>(NewProto->arg_type_begin(),
- NewProto->getNumArgs()),
- EPI);
- New->setType(NewType);
-
- // If exceptions are disabled, suppress the warning about missing
- // exception specifications for new and delete operators.
- if (!getLangOpts().CXXExceptions) {
- switch (New->getDeclName().getCXXOverloadedOperator()) {
- case OO_New:
- case OO_Array_New:
- case OO_Delete:
- case OO_Array_Delete:
- if (New->getDeclContext()->isTranslationUnit())
- return false;
- break;
-
- default:
- break;
- }
- }
-
- // Warn about the lack of exception specification.
- SmallString<128> ExceptionSpecString;
- llvm::raw_svector_ostream OS(ExceptionSpecString);
- switch (OldProto->getExceptionSpecType()) {
- case EST_DynamicNone:
- OS << "throw()";
- break;
+ const FunctionProtoType *OldProto =
+ Old->getType()->castAs<FunctionProtoType>();
+
+ FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
+ 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.
+ }
- 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(getPrintingPolicy());
- }
- OS << ")";
- break;
+ // Update the type of the function with the appropriate exception
+ // specification.
+ QualType NewType = Context.getFunctionType(NewProto->getResultType(),
+ NewProto->getArgTypes(), EPI);
+ New->setType(NewType);
+
+ // Warn about the lack of exception specification.
+ SmallString<128> ExceptionSpecString;
+ llvm::raw_svector_ostream OS(ExceptionSpecString);
+ 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(getPrintingPolicy());
}
+ OS << ")";
+ break;
+ }
- case EST_BasicNoexcept:
- OS << "noexcept";
- break;
-
- case EST_ComputedNoexcept:
- OS << "noexcept(";
- OldProto->getNoexceptExpr()->printPretty(OS, 0, getPrintingPolicy());
- OS << ")";
- break;
+ case EST_BasicNoexcept:
+ OS << "noexcept";
+ break;
- default:
- llvm_unreachable("This spec type is compatible with none.");
- }
- OS.flush();
+ case EST_ComputedNoexcept:
+ OS << "noexcept(";
+ OldProto->getNoexceptExpr()->printPretty(OS, 0, getPrintingPolicy());
+ OS << ")";
+ break;
- SourceLocation FixItLoc;
- if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
- TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
- if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>())
- FixItLoc = PP.getLocForEndOfToken(FTLoc.getLocalRangeEnd());
- }
-
- if (FixItLoc.isInvalid())
- Diag(New->getLocation(), diag::warn_missing_exception_specification)
- << New << OS.str();
- else {
- // FIXME: This will get more complicated with C++0x
- // late-specified return types.
- Diag(New->getLocation(), diag::warn_missing_exception_specification)
- << New << OS.str()
- << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str());
- }
+ default:
+ llvm_unreachable("This spec type is compatible with none.");
+ }
+ OS.flush();
- if (!Old->getLocation().isInvalid())
- Diag(Old->getLocation(), diag::note_previous_declaration);
+ SourceLocation FixItLoc;
+ if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
+ TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
+ if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>())
+ FixItLoc = PP.getLocForEndOfToken(FTLoc.getLocalRangeEnd());
+ }
- return false;
+ if (FixItLoc.isInvalid())
+ Diag(New->getLocation(), diag::warn_missing_exception_specification)
+ << New << OS.str();
+ else {
+ // FIXME: This will get more complicated with C++0x
+ // late-specified return types.
+ Diag(New->getLocation(), diag::warn_missing_exception_specification)
+ << New << OS.str()
+ << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str());
}
- Diag(New->getLocation(), DiagID);
- Diag(Old->getLocation(), diag::note_previous_declaration);
- return true;
+ if (!Old->getLocation().isInvalid())
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+
+ return false;
}
/// CheckEquivalentExceptionSpec - Check if the two types have equivalent
@@ -819,11 +790,8 @@ static CanThrowResult canSubExprsThrow(Sema &S, const Expr *CE) {
return R;
}
-static CanThrowResult canCalleeThrow(Sema &S, const Expr *E,
- const Decl *D,
- bool NullThrows = true) {
- if (!D)
- return NullThrows ? CT_Can : CT_Cannot;
+static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D) {
+ assert(D && "Expected decl");
// See if we can get a function type from the decl somehow.
const ValueDecl *VD = dyn_cast<ValueDecl>(D);
@@ -927,8 +895,10 @@ CanThrowResult Sema::canThrow(const Expr *E) {
CT = CT_Dependent;
else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
CT = CT_Cannot;
- else
+ else if (CE->getCalleeDecl())
CT = canCalleeThrow(*this, E, CE->getCalleeDecl());
+ else
+ CT = CT_Can;
if (CT == CT_Can)
return CT;
return mergeCanThrow(CT, canSubExprsThrow(*this, E));
@@ -974,7 +944,9 @@ CanThrowResult Sema::canThrow(const Expr *E) {
cast<CXXDeleteExpr>(E)->getOperatorDelete());
if (const RecordType *RT = DTy->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- CT = mergeCanThrow(CT, canCalleeThrow(*this, E, RD->getDestructor()));
+ const CXXDestructorDecl *DD = RD->getDestructor();
+ if (DD)
+ CT = mergeCanThrow(CT, canCalleeThrow(*this, E, DD));
}
if (CT == CT_Can)
return CT;
@@ -1012,6 +984,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::CompoundLiteralExprClass:
case Expr::CXXConstCastExprClass:
case Expr::CXXReinterpretCastExprClass:
+ case Expr::CXXStdInitializerListExprClass:
case Expr::DesignatedInitExprClass:
case Expr::ExprWithCleanupsClass:
case Expr::ExtVectorElementExprClass:
@@ -1022,6 +995,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::ParenExprClass:
case Expr::ParenListExprClass:
case Expr::ShuffleVectorExprClass:
+ case Expr::ConvertVectorExprClass:
case Expr::VAArgExprClass:
return canSubExprsThrow(*this, E);
@@ -1052,7 +1026,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::ChooseExprClass:
if (E->isTypeDependent() || E->isValueDependent())
return CT_Dependent;
- return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr(Context));
+ return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr());
case Expr::GenericSelectionExprClass:
if (cast<GenericSelectionExpr>(E)->isResultDependent())
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
index a9179fd48892..e1f65f4a4e1b 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
@@ -15,6 +15,7 @@
#include "TreeTransform.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
@@ -140,11 +141,13 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
return Result;
}
-/// \brief Emit a note explaining that this function is deleted or unavailable.
+/// \brief Emit a note explaining that this function is deleted.
void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
+ assert(Decl->isDeleted());
+
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Decl);
- if (Method && Method->isDeleted() && !Method->isDeletedAsWritten()) {
+ if (Method && Method->isDeleted() && Method->isDefaulted()) {
// If the method was explicitly defaulted, point at that declaration.
if (!Method->isImplicit())
Diag(Decl->getLocation(), diag::note_implicitly_deleted);
@@ -158,8 +161,23 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
return;
}
+ if (CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Decl)) {
+ if (CXXConstructorDecl *BaseCD =
+ const_cast<CXXConstructorDecl*>(CD->getInheritedConstructor())) {
+ Diag(Decl->getLocation(), diag::note_inherited_deleted_here);
+ if (BaseCD->isDeleted()) {
+ NoteDeletedFunction(BaseCD);
+ } else {
+ // FIXME: An explanation of why exactly it can't be inherited
+ // would be nice.
+ Diag(BaseCD->getLocation(), diag::note_cannot_inherit);
+ }
+ return;
+ }
+ }
+
Diag(Decl->getLocation(), diag::note_unavailable_here)
- << 1 << Decl->isDeleted();
+ << 1 << true;
}
/// \brief Determine whether a FunctionDecl was ever declared with an
@@ -197,11 +215,11 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S,
return;
if (!Current->isInlined())
return;
- if (Current->getLinkage() != ExternalLinkage)
+ if (!Current->isExternallyVisible())
return;
-
+
// Check if the decl has internal linkage.
- if (D->getLinkage() != InternalLinkage)
+ if (D->getFormalLinkage() != InternalLinkage)
return;
// Downgrade from ExtWarn to Extension if
@@ -212,7 +230,7 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S,
// This last can give us false negatives, but it's better than warning on
// wrappers for simple C library functions.
const FunctionDecl *UsedFn = dyn_cast<FunctionDecl>(D);
- bool DowngradeWarning = S.getSourceManager().isFromMainFile(Loc);
+ bool DowngradeWarning = S.getSourceManager().isInMainFile(Loc);
if (!DowngradeWarning && UsedFn)
DowngradeWarning = UsedFn->isInlined() || UsedFn->hasAttr<ConstAttr>();
@@ -228,7 +246,7 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S,
}
void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) {
- const FunctionDecl *First = Cur->getFirstDeclaration();
+ const FunctionDecl *First = Cur->getFirstDecl();
// Suggest "static" on the function, if possible.
if (!hasAnyExplicitStorageClass(First)) {
@@ -255,7 +273,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) {
// If there were any diagnostics suppressed by template argument deduction,
// emit them now.
- llvm::DenseMap<Decl *, SmallVector<PartialDiagnosticAt, 1> >::iterator
+ SuppressedDiagnosticsMap::iterator
Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
if (Pos != SuppressedDiagnostics.end()) {
SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second;
@@ -316,7 +334,7 @@ std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) {
/// if so, it checks that the requirements of the sentinel are
/// satisfied.
void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
- Expr **args, unsigned numArgs) {
+ ArrayRef<Expr *> Args) {
const SentinelAttr *attr = D->getAttr<SentinelAttr>();
if (!attr)
return;
@@ -370,14 +388,14 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
// If there aren't enough arguments for all the formal parameters,
// the sentinel, and the args after the sentinel, complain.
- if (numArgs < numFormalParams + numArgsAfterSentinel + 1) {
+ if (Args.size() < numFormalParams + numArgsAfterSentinel + 1) {
Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName();
- Diag(D->getLocation(), diag::note_sentinel_here) << calleeType;
+ Diag(D->getLocation(), diag::note_sentinel_here) << int(calleeType);
return;
}
// Otherwise, find the sentinel expression.
- Expr *sentinelExpr = args[numArgs - numArgsAfterSentinel - 1];
+ Expr *sentinelExpr = Args[Args.size() - numArgsAfterSentinel - 1];
if (!sentinelExpr) return;
if (sentinelExpr->isValueDependent()) return;
if (Context.isSentinelNullExpr(sentinelExpr)) return;
@@ -398,12 +416,12 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
NullValue = "(void*) 0";
if (MissingNilLoc.isInvalid())
- Diag(Loc, diag::warn_missing_sentinel) << calleeType;
+ Diag(Loc, diag::warn_missing_sentinel) << int(calleeType);
else
Diag(MissingNilLoc, diag::warn_missing_sentinel)
- << calleeType
+ << int(calleeType)
<< FixItHint::CreateInsertion(MissingNilLoc, ", " + NullValue);
- Diag(D->getLocation(), diag::note_sentinel_here) << calleeType;
+ Diag(D->getLocation(), diag::note_sentinel_here) << int(calleeType);
}
SourceRange Sema::getExprRange(Expr *E) const {
@@ -725,6 +743,17 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
/// when we're in an unevaluated context.
Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) {
if (Ty->isIncompleteType()) {
+ // C++11 [expr.call]p7:
+ // After these conversions, if the argument does not have arithmetic,
+ // enumeration, pointer, pointer to member, or class type, the program
+ // is ill-formed.
+ //
+ // Since we've already performed array-to-pointer and function-to-pointer
+ // decay, the only such type in C++ is cv void. This also handles
+ // initializer lists as variadic arguments.
+ if (Ty->isVoidType())
+ return VAK_Invalid;
+
if (Ty->isObjCObjectType())
return VAK_Invalid;
return VAK_Valid;
@@ -747,35 +776,50 @@ Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) {
if (getLangOpts().ObjCAutoRefCount && Ty->isObjCLifetimeType())
return VAK_Valid;
- return VAK_Invalid;
+
+ if (Ty->isObjCObjectType())
+ return VAK_Invalid;
+
+ // FIXME: In C++11, these cases are conditionally-supported, meaning we're
+ // permitted to reject them. We should consider doing so.
+ return VAK_Undefined;
}
-bool Sema::variadicArgumentPODCheck(const Expr *E, VariadicCallType CT) {
+void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) {
// Don't allow one to pass an Objective-C interface to a vararg.
- const QualType & Ty = E->getType();
+ const QualType &Ty = E->getType();
+ VarArgKind VAK = isValidVarArgType(Ty);
// Complain about passing non-POD types through varargs.
- switch (isValidVarArgType(Ty)) {
+ switch (VAK) {
case VAK_Valid:
break;
+
case VAK_ValidInCXX11:
- DiagRuntimeBehavior(E->getLocStart(), 0,
+ DiagRuntimeBehavior(
+ E->getLocStart(), 0,
PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg)
- << E->getType() << CT);
+ << E->getType() << CT);
break;
- case VAK_Invalid: {
- if (Ty->isObjCObjectType())
- return DiagRuntimeBehavior(E->getLocStart(), 0,
- PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
- << Ty << CT);
- return DiagRuntimeBehavior(E->getLocStart(), 0,
- PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
- << getLangOpts().CPlusPlus11 << Ty << CT);
- }
+ case VAK_Undefined:
+ DiagRuntimeBehavior(
+ E->getLocStart(), 0,
+ PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
+ << getLangOpts().CPlusPlus11 << Ty << CT);
+ break;
+
+ case VAK_Invalid:
+ if (Ty->isObjCObjectType())
+ DiagRuntimeBehavior(
+ E->getLocStart(), 0,
+ PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
+ << Ty << CT);
+ else
+ Diag(E->getLocStart(), diag::err_cannot_pass_to_vararg)
+ << isa<InitListExpr>(E) << Ty << CT;
+ break;
}
- // c++ rules are enforced elsewhere.
- return false;
}
/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
@@ -805,7 +849,7 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
// Diagnostics regarding non-POD argument types are
// emitted along with format string checking in Sema::CheckFunctionCall().
- if (isValidVarArgType(E->getType()) == VAK_Invalid) {
+ if (isValidVarArgType(E->getType()) == VAK_Undefined) {
// Turn this into a trap.
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
@@ -1230,25 +1274,23 @@ Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc,
SourceLocation DefaultLoc,
SourceLocation RParenLoc,
Expr *ControllingExpr,
- MultiTypeArg ArgTypes,
- MultiExprArg ArgExprs) {
+ ArrayRef<ParsedType> ArgTypes,
+ ArrayRef<Expr *> ArgExprs) {
unsigned NumAssocs = ArgTypes.size();
assert(NumAssocs == ArgExprs.size());
- ParsedType *ParsedTypes = ArgTypes.data();
- Expr **Exprs = ArgExprs.data();
-
TypeSourceInfo **Types = new TypeSourceInfo*[NumAssocs];
for (unsigned i = 0; i < NumAssocs; ++i) {
- if (ParsedTypes[i])
- (void) GetTypeFromParser(ParsedTypes[i], &Types[i]);
+ if (ArgTypes[i])
+ (void) GetTypeFromParser(ArgTypes[i], &Types[i]);
else
Types[i] = 0;
}
ExprResult ER = CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
- ControllingExpr, Types, Exprs,
- NumAssocs);
+ ControllingExpr,
+ llvm::makeArrayRef(Types, NumAssocs),
+ ArgExprs);
delete [] Types;
return ER;
}
@@ -1258,9 +1300,10 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
SourceLocation DefaultLoc,
SourceLocation RParenLoc,
Expr *ControllingExpr,
- TypeSourceInfo **Types,
- Expr **Exprs,
- unsigned NumAssocs) {
+ ArrayRef<TypeSourceInfo *> Types,
+ ArrayRef<Expr *> Exprs) {
+ unsigned NumAssocs = Types.size();
+ assert(NumAssocs == Exprs.size());
if (ControllingExpr->getType()->isPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(ControllingExpr);
if (result.isInvalid()) return ExprError();
@@ -1328,8 +1371,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
if (IsResultDependent)
return Owned(new (Context) GenericSelectionExpr(
Context, KeyLoc, ControllingExpr,
- llvm::makeArrayRef(Types, NumAssocs),
- llvm::makeArrayRef(Exprs, NumAssocs),
+ Types, Exprs,
DefaultLoc, RParenLoc, ContainsUnexpandedParameterPack));
SmallVector<unsigned, 1> CompatIndices;
@@ -1352,7 +1394,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match)
<< ControllingExpr->getSourceRange() << ControllingExpr->getType()
<< (unsigned) CompatIndices.size();
- for (SmallVector<unsigned, 1>::iterator I = CompatIndices.begin(),
+ for (SmallVectorImpl<unsigned>::iterator I = CompatIndices.begin(),
E = CompatIndices.end(); I != E; ++I) {
Diag(Types[*I]->getTypeLoc().getBeginLoc(),
diag::note_compat_assoc)
@@ -1384,8 +1426,7 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
return Owned(new (Context) GenericSelectionExpr(
Context, KeyLoc, ControllingExpr,
- llvm::makeArrayRef(Types, NumAssocs),
- llvm::makeArrayRef(Exprs, NumAssocs),
+ Types, Exprs,
DefaultLoc, RParenLoc, ContainsUnexpandedParameterPack,
ResultIndex));
}
@@ -1421,7 +1462,8 @@ static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope,
LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName);
if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()),
- /*AllowRawAndTemplate*/false) == Sema::LOLR_Error)
+ /*AllowRaw*/false, /*AllowTemplate*/false,
+ /*AllowStringTemplate*/false) == Sema::LOLR_Error)
return ExprError();
return S.BuildLiteralOperatorCall(R, OpNameInfo, Args, LitEndLoc);
@@ -1446,36 +1488,39 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks,
for (unsigned i = 0; i != NumStringToks; ++i)
StringTokLocs.push_back(StringToks[i].getLocation());
- QualType StrTy = Context.CharTy;
- if (Literal.isWide())
- StrTy = Context.getWCharType();
- else if (Literal.isUTF16())
- StrTy = Context.Char16Ty;
- else if (Literal.isUTF32())
- StrTy = Context.Char32Ty;
- else if (Literal.isPascal())
- StrTy = Context.UnsignedCharTy;
-
+ QualType CharTy = Context.CharTy;
StringLiteral::StringKind Kind = StringLiteral::Ascii;
- if (Literal.isWide())
+ if (Literal.isWide()) {
+ CharTy = Context.getWideCharType();
Kind = StringLiteral::Wide;
- else if (Literal.isUTF8())
+ } else if (Literal.isUTF8()) {
Kind = StringLiteral::UTF8;
- else if (Literal.isUTF16())
+ } else if (Literal.isUTF16()) {
+ CharTy = Context.Char16Ty;
Kind = StringLiteral::UTF16;
- else if (Literal.isUTF32())
+ } else if (Literal.isUTF32()) {
+ CharTy = Context.Char32Ty;
Kind = StringLiteral::UTF32;
+ } else if (Literal.isPascal()) {
+ CharTy = Context.UnsignedCharTy;
+ }
+ QualType CharTyConst = CharTy;
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
- StrTy.addConst();
+ CharTyConst.addConst();
// Get an array type for the string, according to C99 6.4.5. This includes
// the nul terminator character as well as the string length for pascal
// strings.
- StrTy = Context.getConstantArrayType(StrTy,
+ QualType StrTy = Context.getConstantArrayType(CharTyConst,
llvm::APInt(32, Literal.GetNumStringChars()+1),
- ArrayType::Normal, 0);
+ ArrayType::Normal, 0);
+
+ // OpenCL v1.1 s6.5.3: a string literal is in the constant address space.
+ if (getLangOpts().OpenCL) {
+ StrTy = Context.getAddrSpaceQualType(StrTy, LangAS::opencl_constant);
+ }
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(),
@@ -1498,12 +1543,57 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks,
// C++11 [lex.ext]p5: The literal L is treated as a call of the form
// operator "" X (str, len)
QualType SizeType = Context.getSizeType();
- llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars());
- IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType,
- StringTokLocs[0]);
- Expr *Args[] = { Lit, LenArg };
- return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc,
- Args, StringTokLocs.back());
+
+ DeclarationName OpName =
+ Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
+ DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
+ OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
+
+ QualType ArgTy[] = {
+ Context.getArrayDecayedType(StrTy), SizeType
+ };
+
+ LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
+ switch (LookupLiteralOperator(UDLScope, R, ArgTy,
+ /*AllowRaw*/false, /*AllowTemplate*/false,
+ /*AllowStringTemplate*/true)) {
+
+ case LOLR_Cooked: {
+ llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars());
+ IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType,
+ StringTokLocs[0]);
+ Expr *Args[] = { Lit, LenArg };
+
+ return BuildLiteralOperatorCall(R, OpNameInfo, Args, StringTokLocs.back());
+ }
+
+ case LOLR_StringTemplate: {
+ TemplateArgumentListInfo ExplicitArgs;
+
+ unsigned CharBits = Context.getIntWidth(CharTy);
+ bool CharIsUnsigned = CharTy->isUnsignedIntegerType();
+ llvm::APSInt Value(CharBits, CharIsUnsigned);
+
+ TemplateArgument TypeArg(CharTy);
+ TemplateArgumentLocInfo TypeArgInfo(Context.getTrivialTypeSourceInfo(CharTy));
+ ExplicitArgs.addArgument(TemplateArgumentLoc(TypeArg, TypeArgInfo));
+
+ for (unsigned I = 0, N = Lit->getLength(); I != N; ++I) {
+ Value = Lit->getCodeUnit(I);
+ TemplateArgument Arg(Context, Value, CharTy);
+ TemplateArgumentLocInfo ArgInfo;
+ ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo));
+ }
+ return BuildLiteralOperatorCall(R, OpNameInfo, None, StringTokLocs.back(),
+ &ExplicitArgs);
+ }
+ case LOLR_Raw:
+ case LOLR_Template:
+ llvm_unreachable("unexpected literal operator lookup result");
+ case LOLR_Error:
+ return ExprError();
+ }
+ llvm_unreachable("unexpected literal operator lookup result");
}
ExprResult
@@ -1519,7 +1609,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
ExprResult
Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
- const CXXScopeSpec *SS, NamedDecl *FoundD) {
+ const CXXScopeSpec *SS, NamedDecl *FoundD,
+ const TemplateArgumentListInfo *TemplateArgs) {
if (getLangOpts().CUDA)
if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext))
if (const FunctionDecl *Callee = dyn_cast<FunctionDecl>(D)) {
@@ -1536,14 +1627,28 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
bool refersToEnclosingScope =
(CurContext != D->getDeclContext() &&
- D->getDeclContext()->isFunctionOrMethod());
-
- DeclRefExpr *E = DeclRefExpr::Create(Context,
- SS ? SS->getWithLocInContext(Context)
- : NestedNameSpecifierLoc(),
- SourceLocation(),
- D, refersToEnclosingScope,
- NameInfo, Ty, VK, FoundD);
+ D->getDeclContext()->isFunctionOrMethod()) ||
+ (isa<VarDecl>(D) &&
+ cast<VarDecl>(D)->isInitCapture());
+
+ DeclRefExpr *E;
+ if (isa<VarTemplateSpecializationDecl>(D)) {
+ VarTemplateSpecializationDecl *VarSpec =
+ cast<VarTemplateSpecializationDecl>(D);
+
+ E = DeclRefExpr::Create(
+ Context,
+ SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
+ VarSpec->getTemplateKeywordLoc(), D, refersToEnclosingScope,
+ NameInfo.getLoc(), Ty, VK, FoundD, TemplateArgs);
+ } else {
+ assert(!TemplateArgs && "No template arguments for non-variable"
+ " template specialization referrences");
+ E = DeclRefExpr::Create(
+ Context,
+ SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
+ SourceLocation(), D, refersToEnclosingScope, NameInfo, Ty, VK, FoundD);
+ }
MarkDeclRefReferenced(E);
@@ -1553,7 +1658,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
E->getLocStart());
if (Level != DiagnosticsEngine::Ignored)
- getCurFunction()->recordUseOfWeak(E);
+ recordUseOfEvaluatedWeak(E);
}
// Just in case we're building an illegal pointer-to-member.
@@ -1602,7 +1707,7 @@ Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id,
bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
CorrectionCandidateCallback &CCC,
TemplateArgumentListInfo *ExplicitTemplateArgs,
- llvm::ArrayRef<Expr *> Args) {
+ ArrayRef<Expr *> Args) {
DeclarationName Name = R.getLookupName();
unsigned diagnostic = diag::err_undeclared_var_use;
@@ -1722,10 +1827,14 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(),
S, &SS, CCC))) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
- std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
+ bool DroppedSpecifier =
+ Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr;
R.setLookupName(Corrected.getCorrection());
- if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
+ bool AcceptableWithRecovery = false;
+ bool AcceptableWithoutRecovery = false;
+ NamedDecl *ND = Corrected.getCorrectionDecl();
+ if (ND) {
if (Corrected.isOverloaded()) {
OverloadCandidateSet OCS(R.getNameLoc());
OverloadCandidateSet::iterator Best;
@@ -1743,63 +1852,49 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
Args, OCS);
}
switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) {
- case OR_Success:
- ND = Best->Function;
- break;
- default:
- break;
+ case OR_Success:
+ ND = Best->Function;
+ Corrected.setCorrectionDecl(ND);
+ break;
+ default:
+ // FIXME: Arbitrarily pick the first declaration for the note.
+ Corrected.setCorrectionDecl(ND);
+ break;
}
}
R.addDecl(ND);
- if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
- if (SS.isEmpty())
- Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr
- << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
- else
- Diag(R.getNameLoc(), diag::err_no_member_suggest)
- << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
- << SS.getRange()
- << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
- CorrectedStr);
- unsigned diag = isa<ImplicitParamDecl>(ND)
- ? diag::note_implicit_param_decl
- : diag::note_previous_decl;
-
- Diag(ND->getLocation(), diag)
- << CorrectedQuotedStr;
-
- // Tell the callee to try to recover.
- return false;
- }
-
- if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) {
- // FIXME: If we ended up with a typo for a type name or
- // Objective-C class name, we're in trouble because the parser
- // is in the wrong place to recover. Suggest the typo
- // correction, but don't make it a fix-it since we're not going
- // to recover well anyway.
- if (SS.isEmpty())
- Diag(R.getNameLoc(), diagnostic_suggest)
- << Name << CorrectedQuotedStr;
- else
- Diag(R.getNameLoc(), diag::err_no_member_suggest)
- << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
- << SS.getRange();
-
- // Don't try to recover; it won't work.
- return true;
- }
+ AcceptableWithRecovery =
+ isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND);
+ // FIXME: If we ended up with a typo for a type name or
+ // Objective-C class name, we're in trouble because the parser
+ // is in the wrong place to recover. Suggest the typo
+ // correction, but don't make it a fix-it since we're not going
+ // to recover well anyway.
+ AcceptableWithoutRecovery =
+ isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
} else {
// FIXME: We found a keyword. Suggest it, but don't provide a fix-it
// because we aren't able to recover.
+ AcceptableWithoutRecovery = true;
+ }
+
+ if (AcceptableWithRecovery || AcceptableWithoutRecovery) {
+ unsigned NoteID = (Corrected.getCorrectionDecl() &&
+ isa<ImplicitParamDecl>(Corrected.getCorrectionDecl()))
+ ? diag::note_implicit_param_decl
+ : diag::note_previous_decl;
if (SS.isEmpty())
- Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr;
+ diagnoseTypo(Corrected, PDiag(diagnostic_suggest) << Name,
+ PDiag(NoteID), AcceptableWithRecovery);
else
- Diag(R.getNameLoc(), diag::err_no_member_suggest)
- << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
- << SS.getRange();
- return true;
+ diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest)
+ << Name << computeDeclContext(SS, false)
+ << DroppedSpecifier << SS.getRange(),
+ PDiag(NoteID), AcceptableWithRecovery);
+
+ // Tell the callee whether to try to recover.
+ return !AcceptableWithRecovery;
}
}
R.clear();
@@ -1824,10 +1919,10 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
UnqualifiedId &Id,
bool HasTrailingLParen,
bool IsAddressOfOperand,
- CorrectionCandidateCallback *CCC) {
+ CorrectionCandidateCallback *CCC,
+ bool IsInlineAsmIdentifier) {
assert(!(IsAddressOfOperand && HasTrailingLParen) &&
"cannot be direct & operand and have a trailing lparen");
-
if (SS.isInvalid())
return ExprError();
@@ -1918,6 +2013,7 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen);
if (R.empty() && !ADL) {
+
// Otherwise, this could be an implicitly declared function reference (legal
// in C90, extension in C99, forbidden in C++).
if (HasTrailingLParen && II && !getLangOpts().CPlusPlus) {
@@ -1930,16 +2026,32 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
if (R.empty()) {
// In Microsoft mode, if we are inside a template class member function
// whose parent class has dependent base classes, and we can't resolve
- // an identifier, then assume the identifier is type dependent. The
- // goal is to postpone name lookup to instantiation time to be able to
- // search into the type dependent base classes.
+ // an identifier, then assume the identifier is a member of a dependent
+ // base class. The goal is to postpone name lookup to instantiation time
+ // to be able to search into the type dependent base classes.
+ // FIXME: If we want 100% compatibility with MSVC, we will have delay all
+ // unqualified name lookup. Any name lookup during template parsing means
+ // clang might find something that MSVC doesn't. For now, we only handle
+ // the common case of members of a dependent base class.
if (getLangOpts().MicrosoftMode) {
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext);
- if (MD && MD->getParent()->hasAnyDependentBases())
- return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
- IsAddressOfOperand, TemplateArgs);
+ if (MD && MD->isInstance() && MD->getParent()->hasAnyDependentBases()) {
+ assert(SS.isEmpty() && "qualifiers should be already handled");
+ QualType ThisType = MD->getThisType(Context);
+ // Since the 'this' expression is synthesized, we don't need to
+ // perform the double-lookup check.
+ NamedDecl *FirstQualifierInScope = 0;
+ return Owned(CXXDependentScopeMemberExpr::Create(
+ Context, /*This=*/0, ThisType, /*IsArrow=*/true,
+ /*Op=*/SourceLocation(), SS.getWithLocInContext(Context),
+ TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs));
+ }
}
+ // Don't diagnose an empty lookup for inline assmebly.
+ if (IsInlineAsmIdentifier)
+ return ExprError();
+
CorrectionCandidateCallback DefaultValidator;
if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator))
return ExprError();
@@ -2001,15 +2113,27 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
MightBeImplicitMember = true;
else
MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) ||
- isa<IndirectFieldDecl>(R.getFoundDecl());
+ isa<IndirectFieldDecl>(R.getFoundDecl()) ||
+ isa<MSPropertyDecl>(R.getFoundDecl());
if (MightBeImplicitMember)
return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
R, TemplateArgs);
}
- if (TemplateArgs || TemplateKWLoc.isValid())
+ if (TemplateArgs || TemplateKWLoc.isValid()) {
+
+ // In C++1y, if this is a variable template id, then check it
+ // in BuildTemplateIdExpr().
+ // The single lookup result must be a variable template declaration.
+ if (Id.getKind() == UnqualifiedId::IK_TemplateId && Id.TemplateId &&
+ Id.TemplateId->Kind == TNK_Var_template) {
+ assert(R.getAsSingle<VarTemplateDecl>() &&
+ "There should only be one declaration found.");
+ }
+
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, ADL, TemplateArgs);
+ }
return BuildDeclarationNameExpr(SS, R, ADL);
}
@@ -2139,6 +2263,14 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
return ExprError();
MarkAnyDeclReferenced(Loc, IV, true);
+ if (!IV->getBackingIvarReferencedInAccessor()) {
+ // Mark this ivar 'referenced' in this method, if it is a backing ivar
+ // of a property and current method is one of its property accessor.
+ const ObjCPropertyDecl *PDecl;
+ const ObjCIvarDecl *BIV = GetIvarBackingPropertyAccessor(CurMethod, PDecl);
+ if (BIV && BIV == IV)
+ IV->setBackingIvarReferencedInAccessor(true);
+ }
ObjCMethodFamily MF = CurMethod->getMethodFamily();
if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&
@@ -2155,7 +2287,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
DiagnosticsEngine::Level Level =
Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc);
if (Level != DiagnosticsEngine::Ignored)
- getCurFunction()->recordUseOfWeak(Result);
+ recordUseOfEvaluatedWeak(Result);
}
if (CurContext->isClosure())
Diag(Loc, diag::warn_implicitly_retains_self)
@@ -2289,9 +2421,8 @@ Sema::PerformObjectMemberConversion(Expr *From,
// x = 17; // error: ambiguous base subobjects
// Derived1::x = 17; // okay, pick the Base subobject of Derived1
// }
- if (Qualifier) {
+ if (Qualifier && Qualifier->getAsType()) {
QualType QType = QualType(Qualifier->getAsType(), 0);
- assert(!QType.isNull() && "lookup done with dependent qualifier?");
assert(QType->isRecordType() && "lookup done with non-record type");
QualType QRecordType = QualType(QType->getAs<RecordType>(), 0);
@@ -2400,7 +2531,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
// turn off ADL anyway).
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
- else if (D->getDeclContext()->isFunctionOrMethod())
+ else if (D->getLexicalDeclContext()->isFunctionOrMethod())
return false;
// C++0x [basic.lookup.argdep]p3:
@@ -2477,10 +2608,9 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
}
/// \brief Complete semantic analysis for a reference to the given declaration.
-ExprResult
-Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
- const DeclarationNameInfo &NameInfo,
- NamedDecl *D, NamedDecl *FoundD) {
+ExprResult Sema::BuildDeclarationNameExpr(
+ const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
+ NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs) {
assert(D && "Cannot refer to a NULL declaration");
assert(!isa<FunctionTemplateDecl>(D) &&
"Cannot refer unambiguously to a function template");
@@ -2492,8 +2622,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
// Specifically diagnose references to class templates that are missing
// a template argument list.
- Diag(Loc, diag::err_template_decl_ref)
- << Template << SS.getRange();
+ Diag(Loc, diag::err_template_decl_ref) << (isa<VarTemplateDecl>(D) ? 1 : 0)
+ << Template << SS.getRange();
Diag(Template->getLocation(), diag::note_template_decl_here);
return ExprError();
}
@@ -2583,6 +2713,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
}
case Decl::Var:
+ case Decl::VarTemplateSpecialization:
+ case Decl::VarTemplatePartialSpecialization:
// In C, "extern void blah;" is valid and is an r-value.
if (!getLangOpts().CPlusPlus &&
!type.hasQualifiers() &&
@@ -2680,32 +2812,23 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
break;
}
- return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD);
+ return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD,
+ TemplateArgs);
}
}
-ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
- PredefinedExpr::IdentType IT;
-
- switch (Kind) {
- default: llvm_unreachable("Unknown simple primary expr!");
- case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
- case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
- case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break;
- case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
- }
-
- // Pre-defined identifiers are of type char[x], where x is the length of the
- // string.
-
- Decl *currentDecl = getCurFunctionOrMethodDecl();
- // Blocks and lambdas can occur at global scope. Don't emit a warning.
- if (!currentDecl) {
- if (const BlockScopeInfo *BSI = getCurBlock())
- currentDecl = BSI->TheDecl;
- else if (const LambdaScopeInfo *LSI = getCurLambda())
- currentDecl = LSI->CallOperator;
- }
+ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
+ PredefinedExpr::IdentType IT) {
+ // Pick the current block, lambda, captured statement or function.
+ Decl *currentDecl = 0;
+ if (const BlockScopeInfo *BSI = getCurBlock())
+ currentDecl = BSI->TheDecl;
+ else if (const LambdaScopeInfo *LSI = getCurLambda())
+ currentDecl = LSI->CallOperator;
+ else if (const CapturedRegionScopeInfo *CSI = getCurCapturedRegion())
+ currentDecl = CSI->TheCapturedDecl;
+ else
+ currentDecl = getCurFunctionOrMethodDecl();
if (!currentDecl) {
Diag(Loc, diag::ext_predef_outside_function);
@@ -2713,21 +2836,39 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
}
QualType ResTy;
- if (cast<DeclContext>(currentDecl)->isDependentContext()) {
+ if (cast<DeclContext>(currentDecl)->isDependentContext())
ResTy = Context.DependentTy;
- } else {
+ else {
+ // Pre-defined identifiers are of type char[x], where x is the length of
+ // the string.
unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
llvm::APInt LengthI(32, Length + 1);
if (IT == PredefinedExpr::LFunction)
- ResTy = Context.WCharTy.withConst();
+ ResTy = Context.WideCharTy.withConst();
else
ResTy = Context.CharTy.withConst();
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
}
+
return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT));
}
+ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
+ PredefinedExpr::IdentType IT;
+
+ switch (Kind) {
+ default: llvm_unreachable("Unknown simple primary expr!");
+ case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
+ case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
+ case tok::kw___FUNCDNAME__: IT = PredefinedExpr::FuncDName; break; // [MS]
+ case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break;
+ case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
+ }
+
+ return BuildPredefinedExpr(Loc, IT);
+}
+
ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
SmallString<16> CharBuffer;
bool Invalid = false;
@@ -2742,7 +2883,7 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
QualType Ty;
if (Literal.isWide())
- Ty = Context.WCharTy; // L'x' -> wchar_t in C and C++.
+ Ty = Context.WideCharTy; // L'x' -> wchar_t in C and C++.
else if (Literal.isUTF16())
Ty = Context.Char16Ty; // u'x' -> char16_t in C11 and C++11.
else if (Literal.isUTF32())
@@ -2872,11 +3013,14 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
+ SourceLocation TokLoc = Tok.getLocation();
+
// Perform literal operator lookup to determine if we're building a raw
// literal or a cooked one.
LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
switch (LookupLiteralOperator(UDLScope, R, CookedTy,
- /*AllowRawAndTemplate*/true)) {
+ /*AllowRaw*/true, /*AllowTemplate*/true,
+ /*AllowStringTemplate*/false)) {
case LOLR_Error:
return ExprError();
@@ -2887,19 +3031,17 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
} else {
llvm::APInt ResultVal(Context.getTargetInfo().getLongLongWidth(), 0);
if (Literal.GetIntegerValue(ResultVal))
- Diag(Tok.getLocation(), diag::warn_integer_too_large);
+ Diag(Tok.getLocation(), diag::err_integer_too_large);
Lit = IntegerLiteral::Create(Context, ResultVal, CookedTy,
Tok.getLocation());
}
- return BuildLiteralOperatorCall(R, OpNameInfo, Lit,
- Tok.getLocation());
+ return BuildLiteralOperatorCall(R, OpNameInfo, Lit, TokLoc);
}
case LOLR_Raw: {
// C++11 [lit.ext]p3, p4: If S contains a raw literal operator, the
// literal is treated as a call of the form
// operator "" X ("n")
- SourceLocation TokLoc = Tok.getLocation();
unsigned Length = Literal.getUDSuffixOffset();
QualType StrTy = Context.getConstantArrayType(
Context.CharTy.withConst(), llvm::APInt(32, Length + 1),
@@ -2910,7 +3052,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
return BuildLiteralOperatorCall(R, OpNameInfo, Lit, TokLoc);
}
- case LOLR_Template:
+ case LOLR_Template: {
// C++11 [lit.ext]p3, p4: Otherwise (S contains a literal operator
// template), L is treated as a call fo the form
// operator "" X <'c1', 'c2', ... 'ck'>()
@@ -2925,11 +3067,12 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
TemplateArgumentLocInfo ArgInfo;
ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo));
}
- return BuildLiteralOperatorCall(R, OpNameInfo, None, Tok.getLocation(),
+ return BuildLiteralOperatorCall(R, OpNameInfo, None, TokLoc,
&ExplicitArgs);
}
-
- llvm_unreachable("unexpected literal operator lookup result");
+ case LOLR_StringTemplate:
+ llvm_unreachable("unexpected literal operator lookup result");
+ }
}
Expr *Res;
@@ -2980,8 +3123,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
llvm::APInt ResultVal(MaxWidth, 0);
if (Literal.GetIntegerValue(ResultVal)) {
- // If this value didn't fit into uintmax_t, warn and force to ull.
- Diag(Tok.getLocation(), diag::warn_integer_too_large);
+ // If this value didn't fit into uintmax_t, error and force to ull.
+ Diag(Tok.getLocation(), diag::err_integer_too_large);
Ty = Context.UnsignedLongLongTy;
assert(Context.getTypeSize(Ty) == ResultVal.getBitWidth() &&
"long long is not intmax_t?");
@@ -3103,6 +3246,10 @@ static bool CheckExtensionTraitOperandType(Sema &S, QualType T,
SourceLocation Loc,
SourceRange ArgRange,
UnaryExprOrTypeTrait TraitKind) {
+ // Invalid types must be hard errors for SFINAE in C++.
+ if (S.LangOpts.CPlusPlus)
+ return true;
+
// C99 6.5.3.4p1:
if (T->isFunctionType() &&
(TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf)) {
@@ -3185,6 +3332,12 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
ExprTy = E->getType();
assert(!ExprTy->isReferenceType());
+ if (ExprTy->isFunctionType()) {
+ Diag(E->getExprLoc(), diag::err_sizeof_alignof_function_type)
+ << ExprKind << E->getSourceRange();
+ return true;
+ }
+
if (CheckObjCTraitOperandConstraints(*this, ExprTy, E->getExprLoc(),
E->getSourceRange(), ExprKind))
return true;
@@ -3258,6 +3411,12 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
ExprKind, ExprRange))
return true;
+ if (ExprType->isFunctionType()) {
+ Diag(OpLoc, diag::err_sizeof_alignof_function_type)
+ << ExprKind << ExprRange;
+ return true;
+ }
+
if (CheckObjCTraitOperandConstraints(*this, ExprType, OpLoc, ExprRange,
ExprKind))
return true;
@@ -3487,7 +3646,8 @@ static bool checkArithmeticOnObjCPointer(Sema &S,
SourceLocation opLoc,
Expr *op) {
assert(op->getType()->isObjCObjectPointerType());
- if (S.LangOpts.ObjCRuntime.allowsPointerArithmetic())
+ if (S.LangOpts.ObjCRuntime.allowsPointerArithmetic() &&
+ !S.LangOpts.ObjCSubscriptingLegacyRuntime)
return false;
S.Diag(opLoc, diag::err_arithmetic_nonfragile_interface)
@@ -3592,15 +3752,10 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
// Use custom logic if this should be the pseudo-object subscript
// expression.
- if (!LangOpts.ObjCRuntime.isSubscriptPointerArithmetic())
+ if (!LangOpts.isSubscriptPointerArithmetic())
return BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0);
ResultType = PTy->getPointeeType();
- if (!LangOpts.ObjCRuntime.allowsPointerArithmetic()) {
- Diag(LLoc, diag::err_subscript_nonfragile_interface)
- << ResultType << BaseExpr->getSourceRange();
- return ExprError();
- }
} else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) {
// Handle the uncommon case of "123[Ptr]".
BaseExpr = RHSExp;
@@ -3612,7 +3767,7 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
BaseExpr = RHSExp;
IndexExpr = LHSExp;
ResultType = PTy->getPointeeType();
- if (!LangOpts.ObjCRuntime.allowsPointerArithmetic()) {
+ if (!LangOpts.isSubscriptPointerArithmetic()) {
Diag(LLoc, diag::err_subscript_nonfragile_interface)
<< ResultType << BaseExpr->getSourceRange();
return ExprError();
@@ -3720,7 +3875,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
InstantiatingTemplate Inst(*this, CallLoc, Param,
MutiLevelArgList.getInnermost());
- if (Inst)
+ if (Inst.isInvalid())
return ExprError();
ExprResult Result;
@@ -3795,12 +3950,71 @@ Sema::getVariadicCallType(FunctionDecl *FDecl, const FunctionProtoType *Proto,
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl))
if (Method->isInstance())
return VariadicMethod;
- }
+ } else if (Fn && Fn->getType() == Context.BoundMemberTy)
+ return VariadicMethod;
return VariadicFunction;
}
return VariadicDoesNotApply;
}
+namespace {
+class FunctionCallCCC : public FunctionCallFilterCCC {
+public:
+ FunctionCallCCC(Sema &SemaRef, const IdentifierInfo *FuncName,
+ unsigned NumArgs, bool HasExplicitTemplateArgs)
+ : FunctionCallFilterCCC(SemaRef, NumArgs, HasExplicitTemplateArgs),
+ FunctionName(FuncName) {}
+
+ virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ if (!candidate.getCorrectionSpecifier() ||
+ candidate.getCorrectionAsIdentifierInfo() != FunctionName) {
+ return false;
+ }
+
+ return FunctionCallFilterCCC::ValidateCandidate(candidate);
+ }
+
+private:
+ const IdentifierInfo *const FunctionName;
+};
+}
+
+static TypoCorrection TryTypoCorrectionForCall(Sema &S,
+ DeclarationNameInfo FuncName,
+ ArrayRef<Expr *> Args) {
+ FunctionCallCCC CCC(S, FuncName.getName().getAsIdentifierInfo(),
+ Args.size(), false);
+ if (TypoCorrection Corrected =
+ S.CorrectTypo(FuncName, Sema::LookupOrdinaryName,
+ S.getScopeForContext(S.CurContext), NULL, CCC)) {
+ if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
+ if (Corrected.isOverloaded()) {
+ OverloadCandidateSet OCS(FuncName.getLoc());
+ OverloadCandidateSet::iterator Best;
+ for (TypoCorrection::decl_iterator CD = Corrected.begin(),
+ CDEnd = Corrected.end();
+ CD != CDEnd; ++CD) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*CD))
+ S.AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), Args,
+ OCS);
+ }
+ switch (OCS.BestViableFunction(S, FuncName.getLoc(), Best)) {
+ case OR_Success:
+ ND = Best->Function;
+ Corrected.setCorrectionDecl(ND);
+ break;
+ default:
+ break;
+ }
+ }
+ if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
+ return Corrected;
+ }
+ }
+ }
+ return TypoCorrection();
+}
+
/// ConvertArgumentsForCall - Converts the arguments specified in
/// Args/NumArgs to the parameter types of the function FDecl with
/// function prototype Proto. Call is the call expression itself, and
@@ -3811,7 +4025,7 @@ bool
Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
FunctionDecl *FDecl,
const FunctionProtoType *Proto,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RParenLoc,
bool IsExecConfig) {
// Bail out early if calling a builtin with custom typechecking.
@@ -3833,9 +4047,23 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
// If too few arguments are available (and we don't have default
// arguments for the remaining parameters), don't make the call.
- if (NumArgs < NumArgsInProto) {
- if (NumArgs < MinArgs) {
- if (MinArgs == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName())
+ if (Args.size() < NumArgsInProto) {
+ if (Args.size() < MinArgs) {
+ MemberExpr *ME = dyn_cast<MemberExpr>(Fn);
+ TypoCorrection TC;
+ if (FDecl && (TC = TryTypoCorrectionForCall(
+ *this, DeclarationNameInfo(FDecl->getDeclName(),
+ (ME ? ME->getMemberLoc()
+ : Fn->getLocStart())),
+ Args))) {
+ unsigned diag_id =
+ MinArgs == NumArgsInProto && !Proto->isVariadic()
+ ? diag::err_typecheck_call_too_few_args_suggest
+ : diag::err_typecheck_call_too_few_args_at_least_suggest;
+ diagnoseTypo(TC, PDiag(diag_id) << FnKind << MinArgs
+ << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange());
+ } else if (MinArgs == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName())
Diag(RParenLoc, MinArgs == NumArgsInProto && !Proto->isVariadic()
? diag::err_typecheck_call_too_few_args_one
: diag::err_typecheck_call_too_few_args_at_least_one)
@@ -3846,10 +4074,11 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
? diag::err_typecheck_call_too_few_args
: diag::err_typecheck_call_too_few_args_at_least)
<< FnKind
- << MinArgs << NumArgs << Fn->getSourceRange();
+ << MinArgs << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange();
// Emit the location of the prototype.
- if (FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
+ if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
Diag(FDecl->getLocStart(), diag::note_callee_decl)
<< FDecl;
@@ -3860,29 +4089,44 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
// If too many are passed and not variadic, error on the extras and drop
// them.
- if (NumArgs > NumArgsInProto) {
+ if (Args.size() > NumArgsInProto) {
if (!Proto->isVariadic()) {
- if (NumArgsInProto == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName())
+ TypoCorrection TC;
+ if (FDecl && (TC = TryTypoCorrectionForCall(
+ *this, DeclarationNameInfo(FDecl->getDeclName(),
+ Fn->getLocStart()),
+ Args))) {
+ unsigned diag_id =
+ MinArgs == NumArgsInProto && !Proto->isVariadic()
+ ? diag::err_typecheck_call_too_many_args_suggest
+ : diag::err_typecheck_call_too_many_args_at_most_suggest;
+ diagnoseTypo(TC, PDiag(diag_id) << FnKind << NumArgsInProto
+ << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange());
+ } else if (NumArgsInProto == 1 && FDecl &&
+ FDecl->getParamDecl(0)->getDeclName())
Diag(Args[NumArgsInProto]->getLocStart(),
MinArgs == NumArgsInProto
? diag::err_typecheck_call_too_many_args_one
: diag::err_typecheck_call_too_many_args_at_most_one)
<< FnKind
- << FDecl->getParamDecl(0) << NumArgs << Fn->getSourceRange()
+ << FDecl->getParamDecl(0) << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange()
<< SourceRange(Args[NumArgsInProto]->getLocStart(),
- Args[NumArgs-1]->getLocEnd());
+ Args.back()->getLocEnd());
else
Diag(Args[NumArgsInProto]->getLocStart(),
MinArgs == NumArgsInProto
? diag::err_typecheck_call_too_many_args
: diag::err_typecheck_call_too_many_args_at_most)
<< FnKind
- << NumArgsInProto << NumArgs << Fn->getSourceRange()
+ << NumArgsInProto << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange()
<< SourceRange(Args[NumArgsInProto]->getLocStart(),
- Args[NumArgs-1]->getLocEnd());
+ Args.back()->getLocEnd());
// Emit the location of the prototype.
- if (FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
+ if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
Diag(FDecl->getLocStart(), diag::note_callee_decl)
<< FDecl;
@@ -3895,7 +4139,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
VariadicCallType CallType = getVariadicCallType(FDecl, Proto, Fn);
Invalid = GatherArgumentsForCall(Call->getLocStart(), FDecl,
- Proto, 0, Args, NumArgs, AllArgs, CallType);
+ Proto, 0, Args, AllArgs, CallType);
if (Invalid)
return true;
unsigned TotalNumArgs = AllArgs.size();
@@ -3909,15 +4153,15 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
FunctionDecl *FDecl,
const FunctionProtoType *Proto,
unsigned FirstProtoArg,
- Expr **Args, unsigned NumArgs,
- SmallVector<Expr *, 8> &AllArgs,
+ ArrayRef<Expr *> Args,
+ SmallVectorImpl<Expr *> &AllArgs,
VariadicCallType CallType,
bool AllowExplicit,
bool IsListInitialization) {
unsigned NumArgsInProto = Proto->getNumArgs();
- unsigned NumArgsToCheck = NumArgs;
+ unsigned NumArgsToCheck = Args.size();
bool Invalid = false;
- if (NumArgs != NumArgsInProto)
+ if (Args.size() != NumArgsInProto)
// Use default arguments for missing arguments
NumArgsToCheck = NumArgsInProto;
unsigned ArgIx = 0;
@@ -3927,7 +4171,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
Expr *Arg;
ParmVarDecl *Param;
- if (ArgIx < NumArgs) {
+ if (ArgIx < Args.size()) {
Arg = Args[ArgIx++];
if (RequireCompleteType(Arg->getLocStart(),
@@ -3941,15 +4185,25 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
Param = FDecl->getParamDecl(i);
// Strip the unbridged-cast placeholder expression off, if applicable.
+ bool CFAudited = false;
if (Arg->getType() == Context.ARCUnbridgedCastTy &&
FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() &&
(!Param || !Param->hasAttr<CFConsumedAttr>()))
Arg = stripARCUnbridgedCast(Arg);
+ else if (getLangOpts().ObjCAutoRefCount &&
+ FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() &&
+ (!Param || !Param->hasAttr<CFConsumedAttr>()))
+ CFAudited = true;
InitializedEntity Entity = Param ?
InitializedEntity::InitializeParameter(Context, Param, ProtoArgType)
: InitializedEntity::InitializeParameter(Context, ProtoArgType,
Proto->isArgConsumed(i));
+
+ // Remember that parameter belongs to a CF audited API.
+ if (CFAudited)
+ Entity.setParameterCFAudited();
+
ExprResult ArgE = PerformCopyInitialization(Entity,
SourceLocation(),
Owned(Arg),
@@ -3988,7 +4242,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
// return __unknown_anytype aren't *really* variadic.
if (Proto->getResultType() == Context.UnknownAnyTy &&
FDecl && FDecl->isExternC()) {
- for (unsigned i = ArgIx; i != NumArgs; ++i) {
+ for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) {
QualType paramType; // ignored
ExprResult arg = checkUnknownAnyArg(CallLoc, Args[i], paramType);
Invalid |= arg.isInvalid();
@@ -3997,7 +4251,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
// Otherwise do argument promotion, (C99 6.5.2.2p7).
} else {
- for (unsigned i = ArgIx; i != NumArgs; ++i) {
+ for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) {
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType,
FDecl);
Invalid |= Arg.isInvalid();
@@ -4006,7 +4260,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
}
// Check for array bounds violations.
- for (unsigned i = ArgIx; i != NumArgs; ++i)
+ for (unsigned i = ArgIx, e = Args.size(); i != e; ++i)
CheckArrayAccess(Args[i]);
}
return Invalid;
@@ -4014,6 +4268,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) {
TypeLoc TL = PVD->getTypeSourceInfo()->getTypeLoc();
+ if (DecayedTypeLoc DTL = TL.getAs<DecayedTypeLoc>())
+ TL = DTL.getOriginalLoc();
if (ArrayTypeLoc ATL = TL.getAs<ArrayTypeLoc>())
S.Diag(PVD->getLocation(), diag::note_callee_static_array)
<< ATL.getLocalSourceRange();
@@ -4188,8 +4444,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
// Determine whether this is a call to an object (C++ [over.call.object]).
if (Fn->getType()->isRecordType())
return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc,
- ArgExprs.data(),
- ArgExprs.size(), RParenLoc));
+ ArgExprs, RParenLoc));
if (Fn->getType() == Context.UnknownAnyTy) {
ExprResult result = rebuildUnknownAnyFunction(*this, Fn);
@@ -4198,8 +4453,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
}
if (Fn->getType() == Context.BoundMemberTy) {
- return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs.data(),
- ArgExprs.size(), RParenLoc);
+ return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs, RParenLoc);
}
}
@@ -4212,11 +4466,11 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
OverloadExpr *ovl = find.Expression;
if (isa<UnresolvedLookupExpr>(ovl)) {
UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl);
- return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, ArgExprs.data(),
- ArgExprs.size(), RParenLoc, ExecConfig);
+ return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, ArgExprs,
+ RParenLoc, ExecConfig);
} else {
- return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs.data(),
- ArgExprs.size(), RParenLoc);
+ return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs,
+ RParenLoc);
}
}
}
@@ -4240,9 +4494,8 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
else if (isa<MemberExpr>(NakedFn))
NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
- return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs.data(),
- ArgExprs.size(), RParenLoc, ExecConfig,
- IsExecConfig);
+ return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc,
+ ExecConfig, IsExecConfig);
}
ExprResult
@@ -4283,6 +4536,19 @@ ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
RParenLoc));
}
+/// ActOnConvertVectorExpr - create a new convert-vector expression from the
+/// provided arguments.
+///
+/// __builtin_convertvector( value, dst type )
+///
+ExprResult Sema::ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc) {
+ TypeSourceInfo *TInfo;
+ GetTypeFromParser(ParsedDestTy, &TInfo);
+ return SemaConvertVectorExpr(E, TInfo, BuiltinLoc, RParenLoc);
+}
+
/// BuildResolvedCallExpr - Build a call to a resolved expression,
/// i.e. an expression not of \p OverloadTy. The expression should
/// unary-convert to an expression of function-pointer or
@@ -4292,7 +4558,7 @@ ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
ExprResult
Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RParenLoc,
Expr *Config, bool IsExecConfig) {
FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl);
@@ -4318,17 +4584,12 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
CallExpr *TheCall;
if (Config)
TheCall = new (Context) CUDAKernelCallExpr(Context, Fn,
- cast<CallExpr>(Config),
- llvm::makeArrayRef(Args,NumArgs),
- Context.BoolTy,
- VK_RValue,
+ cast<CallExpr>(Config), Args,
+ Context.BoolTy, VK_RValue,
RParenLoc);
else
- TheCall = new (Context) CallExpr(Context, Fn,
- llvm::makeArrayRef(Args, NumArgs),
- Context.BoolTy,
- VK_RValue,
- RParenLoc);
+ TheCall = new (Context) CallExpr(Context, Fn, Args, Context.BoolTy,
+ VK_RValue, RParenLoc);
// Bail out early if calling a builtin with custom typechecking.
if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
@@ -4391,8 +4652,8 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT);
if (Proto) {
- if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, NumArgs,
- RParenLoc, IsExecConfig))
+ if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, RParenLoc,
+ IsExecConfig))
return ExprError();
} else {
assert(isa<FunctionNoProtoType>(FuncT) && "Unknown FunctionType!");
@@ -4401,11 +4662,11 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// Check if we have too few/too many template arguments, based
// on our knowledge of the function definition.
const FunctionDecl *Def = 0;
- if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) {
+ if (FDecl->hasBody(Def) && Args.size() != Def->param_size()) {
Proto = Def->getType()->getAs<FunctionProtoType>();
- if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size()))
+ if (!Proto || !(Proto->isVariadic() && Args.size() >= Def->param_size()))
Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments)
- << (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange();
+ << (Args.size() > Def->param_size()) << FDecl << Fn->getSourceRange();
}
// If the function we're calling isn't a function prototype, but we have
@@ -4415,7 +4676,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
}
// Promote the arguments (C99 6.5.2.2p6).
- for (unsigned i = 0; i != NumArgs; i++) {
+ for (unsigned i = 0, e = Args.size(); i != e; i++) {
Expr *Arg = Args[i];
if (Proto && i < Proto->getNumArgs()) {
@@ -4456,7 +4717,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// Check for sentinels
if (NDecl)
- DiagnoseSentinelCalls(NDecl, LParenLoc, Args, NumArgs);
+ DiagnoseSentinelCalls(NDecl, LParenLoc, Args);
// Do special checking on direct calls to functions.
if (FDecl) {
@@ -4466,7 +4727,10 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (BuiltinID)
return CheckBuiltinFunctionCall(BuiltinID, TheCall);
} else if (NDecl) {
- if (CheckBlockCall(NDecl, TheCall, Proto))
+ if (CheckPointerCall(NDecl, TheCall, Proto))
+ return ExprError();
+ } else {
+ if (CheckOtherCall(TheCall, Proto))
return ExprError();
}
@@ -4476,7 +4740,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
ExprResult
Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
SourceLocation RParenLoc, Expr *InitExpr) {
- assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
+ assert(Ty && "ActOnCompoundLiteral(): missing type");
// FIXME: put back this assert when initializers are worked out.
//assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
@@ -4522,7 +4786,10 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
LiteralExpr = Result.get();
bool isFileScope = getCurFunctionOrMethodDecl() == 0;
- if (isFileScope) { // 6.5.2.5p3
+ if (isFileScope &&
+ !LiteralExpr->isTypeDependent() &&
+ !LiteralExpr->isValueDependent() &&
+ !literalType->isDependentType()) { // 6.5.2.5p3
if (CheckForConstantInitializer(LiteralExpr, literalType))
return ExprError();
}
@@ -5108,9 +5375,11 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
QualType lhptee, rhptee;
// Get the pointee types.
+ bool IsBlockPointer = false;
if (const BlockPointerType *LHSBTy = LHSTy->getAs<BlockPointerType>()) {
lhptee = LHSBTy->getPointeeType();
rhptee = RHSTy->castAs<BlockPointerType>()->getPointeeType();
+ IsBlockPointer = true;
} else {
lhptee = LHSTy->castAs<PointerType>()->getPointeeType();
rhptee = RHSTy->castAs<PointerType>()->getPointeeType();
@@ -5152,7 +5421,10 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
// The pointer types are compatible.
QualType ResultTy = CompositeTy.withCVRQualifiers(MergedCVRQual);
- ResultTy = S.Context.getPointerType(ResultTy);
+ if (IsBlockPointer)
+ ResultTy = S.Context.getBlockPointerType(ResultTy);
+ else
+ ResultTy = S.Context.getPointerType(ResultTy);
LHS = S.ImpCastExprToType(LHS.take(), ResultTy, CK_BitCast);
RHS = S.ImpCastExprToType(RHS.take(), ResultTy, CK_BitCast);
@@ -5266,28 +5538,26 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
VK = VK_RValue;
OK = OK_Ordinary;
+ // First, check the condition.
Cond = UsualUnaryConversions(Cond.take());
if (Cond.isInvalid())
return QualType();
- LHS = UsualUnaryConversions(LHS.take());
- if (LHS.isInvalid())
+ if (checkCondition(*this, Cond.get()))
return QualType();
- RHS = UsualUnaryConversions(RHS.take());
- if (RHS.isInvalid())
+
+ // Now check the two expressions.
+ if (LHS.get()->getType()->isVectorType() ||
+ RHS.get()->getType()->isVectorType())
+ return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false);
+
+ UsualArithmeticConversions(LHS, RHS);
+ if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
QualType CondTy = Cond.get()->getType();
QualType LHSTy = LHS.get()->getType();
QualType RHSTy = RHS.get()->getType();
- // first, check the condition.
- if (checkCondition(*this, Cond.get()))
- return QualType();
-
- // Now check the two expressions.
- if (LHSTy->isVectorType() || RHSTy->isVectorType())
- return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false);
-
// If the condition is a vector, and both operands are scalar,
// attempt to implicity convert them to the vector type to act like the
// built in select. (OpenCL v1.1 s6.3.i)
@@ -5297,12 +5567,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// 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);
- if (LHS.isInvalid() || RHS.isInvalid())
- return QualType();
+ if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType())
return LHS.get()->getType();
- }
// If both operands are the same structure or union type, the result is that
// type.
@@ -5638,7 +5904,14 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
Expr *commonExpr = 0;
if (LHSExpr == 0) {
commonExpr = CondExpr;
-
+ // Lower out placeholder types first. This is important so that we don't
+ // try to capture a placeholder. This happens in few cases in C++; such
+ // as Objective-C++'s dictionary subscripting syntax.
+ if (commonExpr->hasPlaceholderType()) {
+ ExprResult result = CheckPlaceholderExpr(commonExpr);
+ if (!result.isUsable()) return ExprError();
+ commonExpr = result.take();
+ }
// We usually want to apply unary conversions *before* saving, except
// in the special case of a C++ l-value conditional.
if (!(getLangOpts().CPlusPlus
@@ -6248,7 +6521,8 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType,
Sema::AssignConvertType
Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
- bool Diagnose) {
+ bool Diagnose,
+ bool DiagnoseCFAudited) {
if (getLangOpts().CPlusPlus) {
if (!LHSType->isRecordType() && !LHSType->isAtomicType()) {
// C++ 5.17p3: If the left operand is not of class type, the
@@ -6290,12 +6564,14 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// C99 6.5.16.1p1: the left operand is a pointer and the right is
// a null pointer constant.
- if ((LHSType->isPointerType() ||
- LHSType->isObjCObjectPointerType() ||
- LHSType->isBlockPointerType())
- && RHS.get()->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNull)) {
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_NullToPointer);
+ if ((LHSType->isPointerType() || LHSType->isObjCObjectPointerType() ||
+ LHSType->isBlockPointerType()) &&
+ RHS.get()->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNull)) {
+ CastKind Kind;
+ CXXCastPath Path;
+ CheckPointerConversion(RHS.get(), LHSType, Kind, Path, false);
+ RHS = ImpCastExprToType(RHS.take(), LHSType, Kind, VK_RValue, &Path);
return Compatible;
}
@@ -6321,9 +6597,14 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// 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 && RHS.get()->getType() != LHSType)
- RHS = ImpCastExprToType(RHS.take(),
- LHSType.getNonLValueExprType(Context), Kind);
+ if (result != Incompatible && RHS.get()->getType() != LHSType) {
+ QualType Ty = LHSType.getNonLValueExprType(Context);
+ Expr *E = RHS.take();
+ if (getLangOpts().ObjCAutoRefCount)
+ CheckObjCARCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion,
+ DiagnoseCFAudited);
+ RHS = ImpCastExprToType(E, Ty, Kind);
+ }
return result;
}
@@ -6402,12 +6683,19 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
return LHSType;
}
}
- if (EltTy->isRealFloatingType() && RHSType->isScalarType() &&
- RHSType->isRealFloatingType()) {
- int order = Context.getFloatingTypeOrder(EltTy, RHSType);
- if (order > 0)
- RHS = ImpCastExprToType(RHS.take(), EltTy, CK_FloatingCast);
- if (order >= 0) {
+ if (EltTy->isRealFloatingType() && RHSType->isScalarType()) {
+ if (RHSType->isRealFloatingType()) {
+ int order = Context.getFloatingTypeOrder(EltTy, RHSType);
+ if (order > 0)
+ RHS = ImpCastExprToType(RHS.take(), EltTy, CK_FloatingCast);
+ if (order >= 0) {
+ RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat);
+ if (swapped) std::swap(RHS, LHS);
+ return LHSType;
+ }
+ }
+ if (RHSType->isIntegralType(Context)) {
+ RHS = ImpCastExprToType(RHS.take(), EltTy, CK_IntegralToFloating);
RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat);
if (swapped) std::swap(RHS, LHS);
return LHSType;
@@ -6480,11 +6768,12 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
return InvalidOperands(Loc, LHS, RHS);
// Check for division by zero.
- if (IsDiv &&
- RHS.get()->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNotNull))
- DiagRuntimeBehavior(Loc, RHS.get(), PDiag(diag::warn_division_by_zero)
- << RHS.get()->getSourceRange());
+ llvm::APSInt RHSValue;
+ if (IsDiv && !RHS.get()->isValueDependent() &&
+ RHS.get()->EvaluateAsInt(RHSValue, Context) && RHSValue == 0)
+ DiagRuntimeBehavior(Loc, RHS.get(),
+ PDiag(diag::warn_division_by_zero)
+ << RHS.get()->getSourceRange());
return compType;
}
@@ -6509,10 +6798,12 @@ QualType Sema::CheckRemainderOperands(
return InvalidOperands(Loc, LHS, RHS);
// Check for remainder by zero.
- if (RHS.get()->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNotNull))
- DiagRuntimeBehavior(Loc, RHS.get(), PDiag(diag::warn_remainder_by_zero)
- << RHS.get()->getSourceRange());
+ llvm::APSInt RHSValue;
+ if (!RHS.get()->isValueDependent() &&
+ RHS.get()->EvaluateAsInt(RHSValue, Context) && RHSValue == 0)
+ DiagRuntimeBehavior(Loc, RHS.get(),
+ PDiag(diag::warn_remainder_by_zero)
+ << RHS.get()->getSourceRange());
return compType;
}
@@ -6685,12 +6976,63 @@ static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc,
// Only print a fixit for "str" + int, not for int + "str".
if (IndexExpr == RHSExpr) {
SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd());
- Self.Diag(OpLoc, diag::note_string_plus_int_silence)
+ Self.Diag(OpLoc, diag::note_string_plus_scalar_silence)
<< FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&")
<< FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
<< FixItHint::CreateInsertion(EndLoc, "]");
} else
- Self.Diag(OpLoc, diag::note_string_plus_int_silence);
+ Self.Diag(OpLoc, diag::note_string_plus_scalar_silence);
+}
+
+/// \brief Emit a warning when adding a char literal to a string.
+static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
+ Expr *LHSExpr, Expr *RHSExpr) {
+ const DeclRefExpr *StringRefExpr =
+ dyn_cast<DeclRefExpr>(LHSExpr->IgnoreImpCasts());
+ const CharacterLiteral *CharExpr =
+ dyn_cast<CharacterLiteral>(RHSExpr->IgnoreImpCasts());
+ if (!StringRefExpr) {
+ StringRefExpr = dyn_cast<DeclRefExpr>(RHSExpr->IgnoreImpCasts());
+ CharExpr = dyn_cast<CharacterLiteral>(LHSExpr->IgnoreImpCasts());
+ }
+
+ if (!CharExpr || !StringRefExpr)
+ return;
+
+ const QualType StringType = StringRefExpr->getType();
+
+ // Return if not a PointerType.
+ if (!StringType->isAnyPointerType())
+ return;
+
+ // Return if not a CharacterType.
+ if (!StringType->getPointeeType()->isAnyCharacterType())
+ return;
+
+ ASTContext &Ctx = Self.getASTContext();
+ SourceRange DiagRange(LHSExpr->getLocStart(), RHSExpr->getLocEnd());
+
+ const QualType CharType = CharExpr->getType();
+ if (!CharType->isAnyCharacterType() &&
+ CharType->isIntegerType() &&
+ llvm::isUIntN(Ctx.getCharWidth(), CharExpr->getValue())) {
+ Self.Diag(OpLoc, diag::warn_string_plus_char)
+ << DiagRange << Ctx.CharTy;
+ } else {
+ Self.Diag(OpLoc, diag::warn_string_plus_char)
+ << DiagRange << CharExpr->getType();
+ }
+
+ // Only print a fixit for str + char, not for char + str.
+ if (isa<CharacterLiteral>(RHSExpr->IgnoreImpCasts())) {
+ SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd());
+ Self.Diag(OpLoc, diag::note_string_plus_scalar_silence)
+ << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&")
+ << FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
+ << FixItHint::CreateInsertion(EndLoc, "]");
+ } else {
+ Self.Diag(OpLoc, diag::note_string_plus_scalar_silence);
+ }
}
/// \brief Emit error when two pointers are incompatible.
@@ -6719,9 +7061,11 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
- // Diagnose "string literal" '+' int.
- if (Opc == BO_Add)
+ // Diagnose "string literal" '+' int and string '+' "char literal".
+ if (Opc == BO_Add) {
diagnoseStringPlusInt(*this, Loc, LHS.get(), RHS.get());
+ diagnoseStringPlusChar(*this, Loc, LHS.get(), RHS.get());
+ }
// handle the common case first (both operands are arithmetic).
if (!compType.isNull() && compType->isArithmeticType()) {
@@ -6846,6 +7190,18 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
LHS.get(), RHS.get()))
return QualType();
+ // The pointee type may have zero size. As an extension, a structure or
+ // union may have zero size or an array may have zero length. In this
+ // case subtraction does not make sense.
+ if (!rpointee->isVoidType() && !rpointee->isFunctionType()) {
+ CharUnits ElementSize = Context.getTypeSizeInChars(rpointee);
+ if (ElementSize.isZero()) {
+ Diag(Loc,diag::warn_sub_ptr_zero_size_types)
+ << rpointee.getUnqualifiedType()
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ }
+ }
+
if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
return Context.getPointerDiffType();
}
@@ -7234,6 +7590,65 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
}
}
+static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS,
+ ExprResult &RHS,
+ SourceLocation Loc,
+ unsigned OpaqueOpc) {
+ // This checking requires bools.
+ if (!S.getLangOpts().Bool) return;
+
+ // Check that left hand side is !something.
+ UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS.get()->IgnoreImpCasts());
+ if (!UO || UO->getOpcode() != UO_LNot) return;
+
+ // Only check if the right hand side is non-bool arithmetic type.
+ if (RHS.get()->getType()->isBooleanType()) return;
+
+ // Make sure that the something in !something is not bool.
+ Expr *SubExpr = UO->getSubExpr()->IgnoreImpCasts();
+ if (SubExpr->getType()->isBooleanType()) return;
+
+ // Emit warning.
+ S.Diag(UO->getOperatorLoc(), diag::warn_logical_not_on_lhs_of_comparison)
+ << Loc;
+
+ // First note suggest !(x < y)
+ SourceLocation FirstOpen = SubExpr->getLocStart();
+ SourceLocation FirstClose = RHS.get()->getLocEnd();
+ FirstClose = S.getPreprocessor().getLocForEndOfToken(FirstClose);
+ if (FirstClose.isInvalid())
+ FirstOpen = SourceLocation();
+ S.Diag(UO->getOperatorLoc(), diag::note_logical_not_fix)
+ << FixItHint::CreateInsertion(FirstOpen, "(")
+ << FixItHint::CreateInsertion(FirstClose, ")");
+
+ // Second note suggests (!x) < y
+ SourceLocation SecondOpen = LHS.get()->getLocStart();
+ SourceLocation SecondClose = LHS.get()->getLocEnd();
+ SecondClose = S.getPreprocessor().getLocForEndOfToken(SecondClose);
+ if (SecondClose.isInvalid())
+ SecondOpen = SourceLocation();
+ S.Diag(UO->getOperatorLoc(), diag::note_logical_not_silence_with_parens)
+ << FixItHint::CreateInsertion(SecondOpen, "(")
+ << FixItHint::CreateInsertion(SecondClose, ")");
+}
+
+// Get the decl for a simple expression: a reference to a variable,
+// an implicit C++ field reference, or an implicit ObjC ivar reference.
+static ValueDecl *getCompareDecl(Expr *E) {
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
+ return DR->getDecl();
+ if (ObjCIvarRefExpr* Ivar = dyn_cast<ObjCIvarRefExpr>(E)) {
+ if (Ivar->isFreeIvar())
+ return Ivar->getDecl();
+ }
+ if (MemberExpr* Mem = dyn_cast<MemberExpr>(E)) {
+ if (Mem->isImplicitAccess())
+ return Mem->getMemberDecl();
+ }
+ return 0;
+}
+
// C99 6.5.8, C++ [expr.rel]
QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, unsigned OpaqueOpc,
@@ -7254,11 +7669,13 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts();
checkEnumComparison(*this, Loc, LHS.get(), RHS.get());
+ diagnoseLogicalNotOnLHSofComparison(*this, LHS, RHS, Loc, OpaqueOpc);
if (!LHSType->hasFloatingRepresentation() &&
!(LHSType->isBlockPointerType() && IsRelational) &&
!LHS.get()->getLocStart().isMacroID() &&
- !RHS.get()->getLocStart().isMacroID()) {
+ !RHS.get()->getLocStart().isMacroID() &&
+ ActiveTemplateInstantiations.empty()) {
// 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.
@@ -7269,37 +7686,34 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
// obvious cases in the definition of the template anyways. The idea is to
// warn when the typed comparison operator will always evaluate to the same
// result.
- if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped)) {
- if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) {
- if (DRL->getDecl() == DRR->getDecl() &&
- !IsWithinTemplateSpecialization(DRL->getDecl())) {
- DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
- << 0 // self-
- << (Opc == BO_EQ
- || Opc == BO_LE
- || Opc == BO_GE));
- } else if (LHSType->isArrayType() && RHSType->isArrayType() &&
- !DRL->getDecl()->getType()->isReferenceType() &&
- !DRR->getDecl()->getType()->isReferenceType()) {
- // what is it always going to eval to?
- char always_evals_to;
- switch(Opc) {
- case BO_EQ: // e.g. array1 == array2
- always_evals_to = 0; // false
- break;
- case BO_NE: // e.g. array1 != array2
- always_evals_to = 1; // true
- break;
- default:
- // best we can say is 'a constant'
- always_evals_to = 2; // e.g. array1 <= array2
- break;
- }
- DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
- << 1 // array
- << always_evals_to);
+ ValueDecl *DL = getCompareDecl(LHSStripped);
+ ValueDecl *DR = getCompareDecl(RHSStripped);
+ if (DL && DR && DL == DR && !IsWithinTemplateSpecialization(DL)) {
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ << 0 // self-
+ << (Opc == BO_EQ
+ || Opc == BO_LE
+ || Opc == BO_GE));
+ } else if (DL && DR && LHSType->isArrayType() && RHSType->isArrayType() &&
+ !DL->getType()->isReferenceType() &&
+ !DR->getType()->isReferenceType()) {
+ // what is it always going to eval to?
+ char always_evals_to;
+ switch(Opc) {
+ case BO_EQ: // e.g. array1 == array2
+ always_evals_to = 0; // false
+ break;
+ case BO_NE: // e.g. array1 != array2
+ always_evals_to = 1; // true
+ break;
+ default:
+ // best we can say is 'a constant'
+ always_evals_to = 2; // e.g. array1 <= array2
+ break;
}
- }
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ << 1 // array
+ << always_evals_to);
}
if (isa<CastExpr>(LHSStripped))
@@ -7333,21 +7747,9 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
}
// C99 6.5.8p3 / C99 6.5.9p4
- if (LHS.get()->getType()->isArithmeticType() &&
- RHS.get()->getType()->isArithmeticType()) {
- UsualArithmeticConversions(LHS, RHS);
- if (LHS.isInvalid() || RHS.isInvalid())
- return QualType();
- }
- else {
- LHS = UsualUnaryConversions(LHS.take());
- if (LHS.isInvalid())
- return QualType();
-
- RHS = UsualUnaryConversions(RHS.take());
- if (RHS.isInvalid())
- return QualType();
- }
+ UsualArithmeticConversions(LHS, RHS);
+ if (LHS.isInvalid() || RHS.isInvalid())
+ return QualType();
LHSType = LHS.get()->getType();
RHSType = RHS.get()->getType();
@@ -7534,12 +7936,20 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS,
/*isError*/false);
}
- if (LHSIsNull && !RHSIsNull)
- LHS = ImpCastExprToType(LHS.take(), RHSType,
+ if (LHSIsNull && !RHSIsNull) {
+ Expr *E = LHS.take();
+ if (getLangOpts().ObjCAutoRefCount)
+ CheckObjCARCConversion(SourceRange(), RHSType, E, CCK_ImplicitConversion);
+ LHS = ImpCastExprToType(E, RHSType,
RPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
- else
- RHS = ImpCastExprToType(RHS.take(), LHSType,
+ }
+ else {
+ Expr *E = RHS.take();
+ if (getLangOpts().ObjCAutoRefCount)
+ CheckObjCARCConversion(SourceRange(), LHSType, E, CCK_ImplicitConversion);
+ RHS = ImpCastExprToType(E, LHSType,
LPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
+ }
return ResultTy;
}
if (LHSType->isObjCObjectPointerType() &&
@@ -7651,7 +8061,8 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
// 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 (!LHSType->hasFloatingRepresentation()) {
+ if (!LHSType->hasFloatingRepresentation() &&
+ ActiveTemplateInstantiations.empty()) {
if (DeclRefExpr* DRL
= dyn_cast<DeclRefExpr>(LHS.get()->IgnoreParenImpCasts()))
if (DeclRefExpr* DRR
@@ -7806,28 +8217,6 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
return Context.BoolTy;
}
-/// IsReadonlyProperty - Verify that otherwise a valid l-value expression
-/// is a read-only property; return true if so. A readonly property expression
-/// depends on various declarations and thus must be treated specially.
-///
-static bool IsReadonlyProperty(Expr *E, Sema &S) {
- const ObjCPropertyRefExpr *PropExpr = dyn_cast<ObjCPropertyRefExpr>(E);
- if (!PropExpr) return false;
- if (PropExpr->isImplicitProperty()) return false;
-
- ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
- QualType BaseType = PropExpr->isSuperReceiver() ?
- PropExpr->getSuperReceiverType() :
- PropExpr->getBase()->getType();
-
- if (const ObjCObjectPointerType *OPT =
- BaseType->getAsObjCInterfacePointerType())
- if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl())
- if (S.isPropertyReadonly(PDecl, IFace))
- return true;
- return false;
-}
-
static bool IsReadonlyMessage(Expr *E, Sema &S) {
const MemberExpr *ME = dyn_cast<MemberExpr>(E);
if (!ME) return false;
@@ -7858,9 +8247,14 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
assert(var->hasLocalStorage() && "capture added 'const' to non-local?");
// Decide whether the first capture was for a block or a lambda.
- DeclContext *DC = S.CurContext;
- while (DC->getParent() != var->getDeclContext())
+ DeclContext *DC = S.CurContext, *Prev = 0;
+ while (DC != var->getDeclContext()) {
+ Prev = DC;
DC = DC->getParent();
+ }
+ // Unless we have an init-capture, we've gone one step too far.
+ if (!var->isInitCapture())
+ DC = Prev;
return (isa<BlockDecl>(DC) ? NCCK_Block : NCCK_Lambda);
}
@@ -7871,9 +8265,7 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
SourceLocation OrigLoc = Loc;
Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context,
&Loc);
- if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S))
- IsLV = Expr::MLV_ReadonlyProperty;
- else if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S))
+ if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S))
IsLV = Expr::MLV_InvalidMessageExpression;
if (IsLV == Expr::MLV_Valid)
return false;
@@ -7956,7 +8348,6 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
case Expr::MLV_DuplicateVectorComponents:
Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
break;
- case Expr::MLV_ReadonlyProperty:
case Expr::MLV_NoSetterProperty:
llvm_unreachable("readonly properties should be processed differently");
case Expr::MLV_InvalidMessageExpression:
@@ -8163,6 +8554,10 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
}
// Increment of bool sets it to true, but is deprecated.
S.Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange();
+ } else if (S.getLangOpts().CPlusPlus && ResType->isEnumeralType()) {
+ // Error on enum increments and decrements in C++ mode
+ S.Diag(OpLoc, diag::err_increment_decrement_enum) << IsInc << ResType;
+ return QualType();
} else if (ResType->isRealType()) {
// OK!
} else if (ResType->isPointerType()) {
@@ -8186,6 +8581,9 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
IsInc, IsPrefix);
} else if (S.getLangOpts().AltiVec && ResType->isVectorType()) {
// OK! ( C/C++ Language Extensions for CBEA(Version 2.6) 10.3 )
+ } else if(S.getLangOpts().OpenCL && ResType->isVectorType() &&
+ ResType->getAs<VectorType>()->getElementType()->isIntegerType()) {
+ // OpenCL V1.2 6.3 says dec/inc ops operate on integer vector types.
} else {
S.Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement)
<< ResType << int(IsInc) << Op->getSourceRange();
@@ -8289,43 +8687,50 @@ static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc,
/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
/// In C++, the operand might be an overloaded function name, in which case
/// we allow the '&' but retain the overloaded-function type.
-static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
- SourceLocation OpLoc) {
+QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){
if (PTy->getKind() == BuiltinType::Overload) {
- if (!isa<OverloadExpr>(OrigOp.get()->IgnoreParens())) {
- assert(cast<UnaryOperator>(OrigOp.get()->IgnoreParens())->getOpcode()
- == UO_AddrOf);
- S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof_addrof_function)
+ Expr *E = OrigOp.get()->IgnoreParens();
+ if (!isa<OverloadExpr>(E)) {
+ assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf);
+ Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof_addrof_function)
<< OrigOp.get()->getSourceRange();
return QualType();
}
-
- return S.Context.OverloadTy;
+
+ OverloadExpr *Ovl = cast<OverloadExpr>(E);
+ if (isa<UnresolvedMemberExpr>(Ovl))
+ if (!ResolveSingleFunctionTemplateSpecialization(Ovl)) {
+ Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+ << OrigOp.get()->getSourceRange();
+ return QualType();
+ }
+
+ return Context.OverloadTy;
}
if (PTy->getKind() == BuiltinType::UnknownAny)
- return S.Context.UnknownAnyTy;
+ return Context.UnknownAnyTy;
if (PTy->getKind() == BuiltinType::BoundMember) {
- S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+ Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
<< OrigOp.get()->getSourceRange();
return QualType();
}
- OrigOp = S.CheckPlaceholderExpr(OrigOp.take());
+ OrigOp = CheckPlaceholderExpr(OrigOp.take());
if (OrigOp.isInvalid()) return QualType();
}
if (OrigOp.get()->isTypeDependent())
- return S.Context.DependentTy;
+ return Context.DependentTy;
assert(!OrigOp.get()->getType()->isPlaceholderType());
// Make sure to ignore parentheses in subsequent checks
Expr *op = OrigOp.get()->IgnoreParens();
- if (S.getLangOpts().C99) {
+ if (getLangOpts().C99) {
// Implement C99-only parts of addressof rules.
if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
if (uOp->getOpcode() == UO_Deref)
@@ -8337,28 +8742,28 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
// expressions here, but the result of one is always an lvalue anyway.
}
ValueDecl *dcl = getPrimaryDecl(op);
- Expr::LValueClassification lval = op->ClassifyLValue(S.Context);
+ Expr::LValueClassification lval = op->ClassifyLValue(Context);
unsigned AddressOfError = AO_No_Error;
if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) {
- bool sfinae = (bool)S.isSFINAEContext();
- S.Diag(OpLoc, S.isSFINAEContext() ? diag::err_typecheck_addrof_temporary
- : diag::ext_typecheck_addrof_temporary)
+ bool sfinae = (bool)isSFINAEContext();
+ Diag(OpLoc, isSFINAEContext() ? diag::err_typecheck_addrof_temporary
+ : diag::ext_typecheck_addrof_temporary)
<< op->getType() << op->getSourceRange();
if (sfinae)
return QualType();
// Materialize the temporary as an lvalue so that we can take its address.
- OrigOp = op = new (S.Context)
- MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true);
+ OrigOp = op = new (Context)
+ MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true, 0);
} else if (isa<ObjCSelectorExpr>(op)) {
- return S.Context.getPointerType(op->getType());
+ return Context.getPointerType(op->getType());
} else if (lval == Expr::LV_MemberFunction) {
// If it's an instance method, make a member pointer.
// The expression must have exactly the form &A::foo.
// If the underlying expression isn't a decl ref, give up.
if (!isa<DeclRefExpr>(op)) {
- S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+ Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
<< OrigOp.get()->getSourceRange();
return QualType();
}
@@ -8367,25 +8772,29 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
// The id-expression was parenthesized.
if (OrigOp.get() != DRE) {
- S.Diag(OpLoc, diag::err_parens_pointer_member_function)
+ Diag(OpLoc, diag::err_parens_pointer_member_function)
<< OrigOp.get()->getSourceRange();
// The method was named without a qualifier.
} else if (!DRE->getQualifier()) {
if (MD->getParent()->getName().empty())
- S.Diag(OpLoc, diag::err_unqualified_pointer_member_function)
+ Diag(OpLoc, diag::err_unqualified_pointer_member_function)
<< op->getSourceRange();
else {
SmallString<32> Str;
StringRef Qual = (MD->getParent()->getName() + "::").toStringRef(Str);
- S.Diag(OpLoc, diag::err_unqualified_pointer_member_function)
+ Diag(OpLoc, diag::err_unqualified_pointer_member_function)
<< op->getSourceRange()
<< FixItHint::CreateInsertion(op->getSourceRange().getBegin(), Qual);
}
}
- return S.Context.getMemberPointerType(op->getType(),
- S.Context.getTypeDeclType(MD->getParent()).getTypePtr());
+ // Taking the address of a dtor is illegal per C++ [class.dtor]p2.
+ if (isa<CXXDestructorDecl>(MD))
+ Diag(OpLoc, diag::err_typecheck_addrof_dtor) << op->getSourceRange();
+
+ return Context.getMemberPointerType(op->getType(),
+ Context.getTypeDeclType(MD->getParent()).getTypePtr());
} else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
// C99 6.5.3.2p1
// The operand must be either an l-value or a function designator
@@ -8394,7 +8803,7 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
if (isa<PseudoObjectExpr>(op)) {
AddressOfError = AO_Property_Expansion;
} else {
- S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
+ Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
<< op->getType() << op->getSourceRange();
return QualType();
}
@@ -8412,11 +8821,11 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
// in C++ it is not error to take address of a register
// variable (c++03 7.1.1P3)
if (vd->getStorageClass() == SC_Register &&
- !S.getLangOpts().CPlusPlus) {
+ !getLangOpts().CPlusPlus) {
AddressOfError = AO_Register_Variable;
}
} else if (isa<FunctionTemplateDecl>(dcl)) {
- return S.Context.OverloadTy;
+ return Context.OverloadTy;
} else if (isa<FieldDecl>(dcl) || isa<IndirectFieldDecl>(dcl)) {
// Okay: we can take the address of a field.
// Could be a pointer to member, though, if there is an explicit
@@ -8425,16 +8834,16 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
DeclContext *Ctx = dcl->getDeclContext();
if (Ctx && Ctx->isRecord()) {
if (dcl->getType()->isReferenceType()) {
- S.Diag(OpLoc,
- diag::err_cannot_form_pointer_to_member_of_reference_type)
+ Diag(OpLoc,
+ diag::err_cannot_form_pointer_to_member_of_reference_type)
<< dcl->getDeclName() << dcl->getType();
return QualType();
}
while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion())
Ctx = Ctx->getParent();
- return S.Context.getMemberPointerType(op->getType(),
- S.Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+ return Context.getMemberPointerType(op->getType(),
+ Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
}
}
} else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl))
@@ -8442,7 +8851,7 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
}
if (AddressOfError != AO_No_Error) {
- diagnoseAddressOfInvalidType(S, OpLoc, op, AddressOfError);
+ diagnoseAddressOfInvalidType(*this, OpLoc, op, AddressOfError);
return QualType();
}
@@ -8450,13 +8859,13 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
// Taking the address of a void variable is technically illegal, but we
// allow it in cases which are otherwise valid.
// Example: "extern void x; void* y = &x;".
- S.Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange();
+ Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange();
}
// If the operand has type "type", the result has type "pointer to type".
if (op->getType()->isObjCObjectType())
- return S.Context.getObjCObjectPointerType(op->getType());
- return S.Context.getPointerType(op->getType());
+ return Context.getObjCObjectPointerType(op->getType());
+ return Context.getPointerType(op->getType());
}
/// CheckIndirectionOperand - Type check unary indirection (prefix '*').
@@ -8630,7 +9039,20 @@ static void checkObjCPointerIntrospection(Sema &S, ExprResult &L, ExprResult &R,
// looks for code trying to introspect into tagged pointers, which
// code should generally never do.
if (ObjCPointerExpr && isa<IntegerLiteral>(OtherExpr->IgnoreParenCasts())) {
- S.Diag(OpLoc, diag::warn_objc_pointer_masking)
+ unsigned Diag = diag::warn_objc_pointer_masking;
+ // Determine if we are introspecting the result of performSelectorXXX.
+ const Expr *Ex = ObjCPointerExpr->IgnoreParenCasts();
+ // Special case messages to -performSelector and friends, which
+ // can return non-pointer values boxed in a pointer value.
+ // Some clients may wish to silence warnings in this subcase.
+ if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(Ex)) {
+ Selector S = ME->getSelector();
+ StringRef SelArg0 = S.getNameForSlot(0);
+ if (SelArg0.startswith("performSelector"))
+ Diag = diag::warn_objc_pointer_masking_performSelector;
+ }
+
+ S.Diag(OpLoc, Diag)
<< ObjCPointerExpr->getSourceRange();
}
}
@@ -9149,7 +9571,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
Opc == UO_PreDec);
break;
case UO_AddrOf:
- resultType = CheckAddressOfOperand(*this, Input, OpLoc);
+ resultType = CheckAddressOfOperand(Input, OpLoc);
break;
case UO_Deref: {
Input = DefaultFunctionArrayLvalueConversion(Input.take());
@@ -9167,9 +9589,6 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
if (resultType->isArithmeticType() || // C99 6.5.3.3p1
resultType->isVectorType())
break;
- else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6-7
- resultType->isEnumeralType())
- break;
else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6
Opc == UO_Plus &&
resultType->isPointerType())
@@ -9392,7 +9811,7 @@ ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
LabelDecl *TheDecl) {
- TheDecl->setUsed();
+ TheDecl->markUsed(Context);
// Create the AST node. The address of a label always has type 'void*'.
return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl,
Context.getPointerType(Context.VoidTy)));
@@ -9657,9 +10076,15 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// If the member was found in a base class, introduce OffsetOfNodes for
// the base class indirections.
- CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
- /*DetectVirtual=*/false);
+ CXXBasePaths Paths;
if (IsDerivedFrom(CurrentType, Context.getTypeDeclType(Parent), Paths)) {
+ if (Paths.getDetectedVirtual()) {
+ Diag(OC.LocEnd, diag::err_offsetof_field_of_virtual_base)
+ << MemberDecl->getDeclName()
+ << SourceRange(BuiltinLoc, RParenLoc);
+ return ExprError();
+ }
+
CXXBasePath &Path = Paths.front();
for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end();
B != BEnd; ++B)
@@ -9715,6 +10140,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
ExprObjectKind OK = OK_Ordinary;
QualType resType;
bool ValueDependent = false;
+ bool CondIsTrue = false;
if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) {
resType = Context.DependentTy;
ValueDependent = true;
@@ -9727,9 +10153,10 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
if (CondICE.isInvalid())
return ExprError();
CondExpr = CondICE.take();
+ CondIsTrue = condEval.getZExtValue();
// If the condition is > zero, then the AST type is the same as the LSHExpr.
- Expr *ActiveExpr = condEval.getZExtValue() ? LHSExpr : RHSExpr;
+ Expr *ActiveExpr = CondIsTrue ? LHSExpr : RHSExpr;
resType = ActiveExpr->getType();
ValueDependent = ActiveExpr->isValueDependent();
@@ -9738,7 +10165,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
}
return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr,
- resType, VK, OK, RPLoc,
+ resType, VK, OK, RPLoc, CondIsTrue,
resType->isDependentType(),
ValueDependent));
}
@@ -9750,6 +10177,17 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
/// ActOnBlockStart - This callback is invoked when a block literal is started.
void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {
BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc);
+
+ if (LangOpts.CPlusPlus) {
+ Decl *ManglingContextDecl;
+ if (MangleNumberingContext *MCtx =
+ getCurrentMangleNumberContext(Block->getDeclContext(),
+ ManglingContextDecl)) {
+ unsigned ManglingNumber = MCtx->getManglingNumber(Block);
+ Block->setBlockMangling(ManglingNumber, ManglingContextDecl);
+ }
+ }
+
PushBlockScope(CurScope, Block);
CurContext->addDecl(Block);
if (CurScope)
@@ -9822,13 +10260,6 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
CurBlock->TheDecl->setIsVariadic(isVariadic);
- // Don't allow returning a objc interface by value.
- if (RetTy->isObjCObjectType()) {
- Diag(ParamInfo.getLocStart(),
- diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
- return;
- }
-
// Context.DependentTy is used as a placeholder for a missing block
// return type. TODO: what should we do with declarators like:
// ^ * { ... }
@@ -9876,11 +10307,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
// Finally we can process decl attributes.
ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
- // Put the parameter variables in scope. We can bail out immediately
- // if we don't have any.
- if (Params.empty())
- return;
-
+ // Put the parameter variables in scope.
for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
E = CurBlock->TheDecl->param_end(); AI != E; ++AI) {
(*AI)->setOwningFunction(CurBlock->TheDecl);
@@ -9942,7 +10369,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
if (Cap.isThisCapture())
continue;
BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(),
- Cap.isNested(), Cap.getCopyExpr());
+ Cap.isNested(), Cap.getInitExpr());
Captures.push_back(NewCap);
}
BSI->TheDecl->setCaptures(Context, Captures.begin(), Captures.end(),
@@ -9973,11 +10400,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals = 0; // FIXME: silently?
EPI.ExtInfo = Ext;
- BlockTy =
- Context.getFunctionType(RetTy,
- ArrayRef<QualType>(FPT->arg_type_begin(),
- FPT->getNumArgs()),
- EPI);
+ BlockTy = Context.getFunctionType(RetTy, FPT->getArgTypes(), EPI);
}
// If we don't have a function type, just build one from nothing.
@@ -10007,7 +10430,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
computeNRVO(Body, getCurBlock());
BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
- const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy();
+ AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result);
// If the block isn't obviously global, i.e. it captures anything at
@@ -10145,7 +10568,8 @@ ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
}
static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
- Expr *SrcExpr, FixItHint &Hint) {
+ Expr *SrcExpr, FixItHint &Hint,
+ bool &IsNSString) {
if (!SemaRef.getLangOpts().ObjC1)
return;
@@ -10159,6 +10583,7 @@ static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
if (!ID || !ID->getIdentifier()->isStr("NSString"))
return;
+ IsNSString = true;
}
// Ignore any parens, implicit casts (should only be
@@ -10192,6 +10617,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
ConversionFixItGenerator ConvHints;
bool MayHaveConvFixit = false;
bool MayHaveFunctionDiff = false;
+ bool IsNSString = false;
switch (ConvTy) {
case Compatible:
@@ -10209,8 +10635,11 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
MayHaveConvFixit = true;
break;
case IncompatiblePointer:
- MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint);
- DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
+ MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint, IsNSString);
+ DiagKind =
+ (Action == AA_Passing_CFAudited ?
+ diag::err_arc_typecheck_convert_incompatible_pointer :
+ diag::ext_typecheck_convert_incompatible_pointer);
CheckInferredResultType = DstType->isObjCObjectPointerType() &&
SrcType->isObjCObjectPointerType();
if (Hint.isNull() && !CheckInferredResultType) {
@@ -10220,6 +10649,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
SrcType = SrcType.getUnqualifiedType();
DstType = DstType.getUnqualifiedType();
}
+ else if (IsNSString && !Hint.isNull())
+ DiagKind = diag::warn_missing_atsign_prefix;
MayHaveConvFixit = true;
break;
case IncompatiblePointerSign:
@@ -10302,6 +10733,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
case AA_Returning:
case AA_Passing:
+ case AA_Passing_CFAudited:
case AA_Converting:
case AA_Sending:
case AA_Casting:
@@ -10312,7 +10744,10 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
}
PartialDiagnostic FDiag = PDiag(DiagKind);
- FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange();
+ if (Action == AA_Passing_CFAudited)
+ FDiag << FirstType << SecondType << SrcExpr->getSourceRange();
+ else
+ FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange();
// If we can fix the conversion, suggest the FixIts.
assert(ConvHints.isNull() || Hint.isNull());
@@ -10394,112 +10829,52 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
// have a single non-explicit conversion function to an integral or
// unscoped enumeration type
ExprResult Converted;
- if (!Diagnoser.Suppress) {
- class CXX11ConvertDiagnoser : public ICEConvertDiagnoser {
- public:
- CXX11ConvertDiagnoser() : ICEConvertDiagnoser(false, true) { }
-
- virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
- QualType T) {
- return S.Diag(Loc, diag::err_ice_not_integral) << T;
- }
-
- virtual DiagnosticBuilder diagnoseIncomplete(Sema &S,
- SourceLocation Loc,
- QualType T) {
- return S.Diag(Loc, diag::err_ice_incomplete_type) << T;
- }
-
- virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S,
- SourceLocation Loc,
- QualType T,
- QualType ConvTy) {
- return S.Diag(Loc, diag::err_ice_explicit_conversion) << T << ConvTy;
- }
-
- virtual DiagnosticBuilder noteExplicitConv(Sema &S,
- CXXConversionDecl *Conv,
- QualType ConvTy) {
- return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
- << ConvTy->isEnumeralType() << ConvTy;
- }
-
- virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
- QualType T) {
- return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T;
- }
-
- virtual DiagnosticBuilder noteAmbiguous(Sema &S,
- CXXConversionDecl *Conv,
- QualType ConvTy) {
- return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
- << ConvTy->isEnumeralType() << ConvTy;
- }
-
- virtual DiagnosticBuilder diagnoseConversion(Sema &S,
- SourceLocation Loc,
- QualType T,
- QualType ConvTy) {
- return DiagnosticBuilder::getEmpty();
- }
- } ConvertDiagnoser;
+ class CXX11ConvertDiagnoser : public ICEConvertDiagnoser {
+ public:
+ CXX11ConvertDiagnoser(bool Silent)
+ : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false,
+ Silent, true) {}
+
+ virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) {
+ return S.Diag(Loc, diag::err_ice_not_integral) << T;
+ }
- Converted = ConvertToIntegralOrEnumerationType(DiagLoc, E,
- ConvertDiagnoser,
- /*AllowScopedEnumerations*/ false);
- } else {
- // The caller wants to silently enquire whether this is an ICE. Don't
- // produce any diagnostics if it isn't.
- class SilentICEConvertDiagnoser : public ICEConvertDiagnoser {
- public:
- SilentICEConvertDiagnoser() : ICEConvertDiagnoser(true, true) { }
-
- virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
- QualType T) {
- return DiagnosticBuilder::getEmpty();
- }
-
- virtual DiagnosticBuilder diagnoseIncomplete(Sema &S,
- SourceLocation Loc,
- QualType T) {
- return DiagnosticBuilder::getEmpty();
- }
-
- virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S,
- SourceLocation Loc,
- QualType T,
- QualType ConvTy) {
- return DiagnosticBuilder::getEmpty();
- }
-
- virtual DiagnosticBuilder noteExplicitConv(Sema &S,
- CXXConversionDecl *Conv,
- QualType ConvTy) {
- return DiagnosticBuilder::getEmpty();
- }
-
- virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
- QualType T) {
- return DiagnosticBuilder::getEmpty();
- }
-
- virtual DiagnosticBuilder noteAmbiguous(Sema &S,
- CXXConversionDecl *Conv,
- QualType ConvTy) {
- return DiagnosticBuilder::getEmpty();
- }
-
- virtual DiagnosticBuilder diagnoseConversion(Sema &S,
- SourceLocation Loc,
- QualType T,
- QualType ConvTy) {
- return DiagnosticBuilder::getEmpty();
- }
- } ConvertDiagnoser;
-
- Converted = ConvertToIntegralOrEnumerationType(DiagLoc, E,
- ConvertDiagnoser, false);
- }
+ virtual SemaDiagnosticBuilder diagnoseIncomplete(
+ Sema &S, SourceLocation Loc, QualType T) {
+ return S.Diag(Loc, diag::err_ice_incomplete_type) << T;
+ }
+
+ virtual SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ return S.Diag(Loc, diag::err_ice_explicit_conversion) << T << ConvTy;
+ }
+
+ virtual SemaDiagnosticBuilder noteExplicitConv(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
+ << ConvTy->isEnumeralType() << ConvTy;
+ }
+
+ virtual SemaDiagnosticBuilder diagnoseAmbiguous(
+ Sema &S, SourceLocation Loc, QualType T) {
+ return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T;
+ }
+
+ virtual SemaDiagnosticBuilder noteAmbiguous(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
+ << ConvTy->isEnumeralType() << ConvTy;
+ }
+
+ virtual SemaDiagnosticBuilder diagnoseConversion(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ llvm_unreachable("conversion functions are permitted");
+ }
+ } ConvertDiagnoser(Diagnoser.Suppress);
+
+ Converted = PerformContextualImplicitConversion(DiagLoc, E,
+ ConvertDiagnoser);
if (Converted.isInvalid())
return Converted;
E = Converted.take();
@@ -10647,21 +11022,30 @@ void
Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
ReuseLambdaContextDecl_t,
bool IsDecltype) {
- Decl *LambdaContextDecl = ExprEvalContexts.back().LambdaContextDecl;
- PushExpressionEvaluationContext(NewContext, LambdaContextDecl, IsDecltype);
+ Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl;
+ PushExpressionEvaluationContext(NewContext, ClosureContextDecl, IsDecltype);
}
void Sema::PopExpressionEvaluationContext() {
ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
if (!Rec.Lambdas.empty()) {
- if (Rec.isUnevaluated()) {
- // C++11 [expr.prim.lambda]p2:
- // A lambda-expression shall not appear in an unevaluated operand
- // (Clause 5).
+ if (Rec.isUnevaluated() || Rec.Context == ConstantEvaluated) {
+ unsigned D;
+ if (Rec.isUnevaluated()) {
+ // C++11 [expr.prim.lambda]p2:
+ // A lambda-expression shall not appear in an unevaluated operand
+ // (Clause 5).
+ D = diag::err_lambda_unevaluated_operand;
+ } else {
+ // C++1y [expr.const]p2:
+ // A conditional-expression e is a core constant expression unless the
+ // evaluation of e, following the rules of the abstract machine, would
+ // evaluate [...] a lambda-expression.
+ D = diag::err_lambda_in_constant_expression;
+ }
for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I)
- Diag(Rec.Lambdas[I]->getLocStart(),
- diag::err_lambda_unevaluated_operand);
+ Diag(Rec.Lambdas[I]->getLocStart(), D);
} else {
// Mark the capture expressions odr-used. This was deferred
// during lambda expression creation.
@@ -10874,7 +11258,8 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
if (!AlreadyInstantiated || Func->isConstexpr()) {
if (isa<CXXRecordDecl>(Func->getDeclContext()) &&
- cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass())
+ cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass() &&
+ ActiveTemplateInstantiations.size())
PendingLocalImplicitInstantiations.push_back(
std::make_pair(Func, PointOfInstantiation));
else if (Func->isConstexpr())
@@ -10908,14 +11293,14 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
}
- // Normally the must current decl is marked used while processing the use and
+ // Normally the most current decl is marked used while processing the use and
// any subsequent decls are marked used by decl merging. This fails with
// template instantiation since marking can happen at the end of the file
// and, because of the two phase lookup, this function is called with at
// decl in the middle of a decl chain. We loop to maintain the invariant
// that once a decl is used, all decls after it are also used.
for (FunctionDecl *F = Func->getMostRecentDecl();; F = F->getPreviousDecl()) {
- F->setUsed(true);
+ F->markUsed(Context);
if (F == Func)
break;
}
@@ -10967,36 +11352,251 @@ diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
// capture.
}
-/// \brief Capture the given variable in the captured region.
-static ExprResult captureInCapturedRegion(Sema &S, CapturedRegionScopeInfo *RSI,
- VarDecl *Var, QualType FieldType,
- QualType DeclRefType,
- SourceLocation Loc,
- bool RefersToEnclosingLocal) {
- // The current implemention assumes that all variables are captured
- // by references. Since there is no capture by copy, no expression evaluation
- // will be needed.
- //
- RecordDecl *RD = RSI->TheRecordDecl;
+
+static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDecl *Var,
+ bool &SubCapturesAreNested,
+ QualType &CaptureType,
+ QualType &DeclRefType) {
+ // Check whether we've already captured it.
+ if (CSI->CaptureMap.count(Var)) {
+ // If we found a capture, any subcaptures are nested.
+ SubCapturesAreNested = true;
+
+ // Retrieve the capture type for this variable.
+ CaptureType = CSI->getCapture(Var).getCaptureType();
+
+ // Compute the type of an expression that refers to this variable.
+ DeclRefType = CaptureType.getNonReferenceType();
+
+ const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var);
+ if (Cap.isCopyCapture() &&
+ !(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable))
+ DeclRefType.addConst();
+ return true;
+ }
+ return false;
+}
- FieldDecl *Field
- = FieldDecl::Create(S.Context, RD, Loc, Loc, 0, FieldType,
- S.Context.getTrivialTypeSourceInfo(FieldType, Loc),
- 0, false, ICIS_NoInit);
- Field->setImplicit(true);
- Field->setAccess(AS_private);
- RD->addDecl(Field);
+// Only block literals, captured statements, and lambda expressions can
+// capture; other scopes don't work.
+static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *Var,
+ SourceLocation Loc,
+ const bool Diagnose, Sema &S) {
+ if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC) || isLambdaCallOperator(DC))
+ return getLambdaAwareParentOfDeclContext(DC);
+ else {
+ if (Diagnose)
+ diagnoseUncapturableValueReference(S, Loc, Var, DC);
+ }
+ return 0;
+}
- Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal,
- DeclRefType, VK_LValue, Loc);
- Var->setReferenced(true);
- Var->setUsed(true);
+// Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
+// certain types of variables (unnamed, variably modified types etc.)
+// so check for eligibility.
+static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
+ SourceLocation Loc,
+ const bool Diagnose, Sema &S) {
+
+ bool IsBlock = isa<BlockScopeInfo>(CSI);
+ bool IsLambda = isa<LambdaScopeInfo>(CSI);
+
+ // Lambdas are not allowed to capture unnamed variables
+ // (e.g. anonymous unions).
+ // FIXME: The C++11 rule don't actually state this explicitly, but I'm
+ // assuming that's the intent.
+ if (IsLambda && !Var->getDeclName()) {
+ if (Diagnose) {
+ S.Diag(Loc, diag::err_lambda_capture_anonymous_var);
+ S.Diag(Var->getLocation(), diag::note_declared_at);
+ }
+ return false;
+ }
+
+ // Prohibit variably-modified types; they're difficult to deal with.
+ if (Var->getType()->isVariablyModifiedType()) {
+ if (Diagnose) {
+ if (IsBlock)
+ S.Diag(Loc, diag::err_ref_vm_type);
+ else
+ S.Diag(Loc, diag::err_lambda_capture_vm_type) << Var->getDeclName();
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ }
+ return false;
+ }
+ // Prohibit structs with flexible array members too.
+ // We cannot capture what is in the tail end of the struct.
+ if (const RecordType *VTTy = Var->getType()->getAs<RecordType>()) {
+ if (VTTy->getDecl()->hasFlexibleArrayMember()) {
+ if (Diagnose) {
+ if (IsBlock)
+ S.Diag(Loc, diag::err_ref_flexarray_type);
+ else
+ S.Diag(Loc, diag::err_lambda_capture_flexarray_type)
+ << Var->getDeclName();
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ }
+ return false;
+ }
+ }
+ const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
+ // Lambdas and captured statements are not allowed to capture __block
+ // variables; they don't support the expected semantics.
+ if (HasBlocksAttr && (IsLambda || isa<CapturedRegionScopeInfo>(CSI))) {
+ if (Diagnose) {
+ S.Diag(Loc, diag::err_capture_block_variable)
+ << Var->getDeclName() << !IsLambda;
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ }
+ return false;
+ }
- return Ref;
+ return true;
}
-/// \brief Capture the given variable in the given lambda expression.
-static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
+// Returns true if the capture by block was successful.
+static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
+ SourceLocation Loc,
+ const bool BuildAndDiagnose,
+ QualType &CaptureType,
+ QualType &DeclRefType,
+ const bool Nested,
+ Sema &S) {
+ Expr *CopyExpr = 0;
+ bool ByRef = false;
+
+ // Blocks are not allowed to capture arrays.
+ if (CaptureType->isArrayType()) {
+ if (BuildAndDiagnose) {
+ S.Diag(Loc, diag::err_ref_array_type);
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ }
+ return false;
+ }
+
+ // Forbid the block-capture of autoreleasing variables.
+ if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
+ if (BuildAndDiagnose) {
+ S.Diag(Loc, diag::err_arc_autoreleasing_capture)
+ << /*block*/ 0;
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ }
+ return false;
+ }
+ const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
+ if (HasBlocksAttr || CaptureType->isReferenceType()) {
+ // Block capture by reference does not change the capture or
+ // declaration reference types.
+ ByRef = true;
+ } else {
+ // Block capture by copy introduces 'const'.
+ CaptureType = CaptureType.getNonReferenceType().withConst();
+ DeclRefType = CaptureType;
+
+ if (S.getLangOpts().CPlusPlus && BuildAndDiagnose) {
+ if (const RecordType *Record = DeclRefType->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, Record);
+
+ // Enter a new evaluation context to insulate the copy
+ // full-expression.
+ EnterExpressionEvaluationContext scope(S, S.PotentiallyEvaluated);
+
+ // 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.
+ Expr *DeclRef = new (S.Context) DeclRefExpr(Var, Nested,
+ DeclRefType.withConst(),
+ VK_LValue, Loc);
+
+ ExprResult Result
+ = S.PerformCopyInitialization(
+ InitializedEntity::InitializeBlock(Var->getLocation(),
+ CaptureType, false),
+ Loc, S.Owned(DeclRef));
+
+ // Build a full-expression copy expression if initialization
+ // succeeded and used a non-trivial constructor. Recover from
+ // errors by pretending that the copy isn't necessary.
+ if (!Result.isInvalid() &&
+ !cast<CXXConstructExpr>(Result.get())->getConstructor()
+ ->isTrivial()) {
+ Result = S.MaybeCreateExprWithCleanups(Result);
+ CopyExpr = Result.take();
+ }
+ }
+ }
+ }
+
+ // Actually capture the variable.
+ if (BuildAndDiagnose)
+ BSI->addCapture(Var, HasBlocksAttr, ByRef, Nested, Loc,
+ SourceLocation(), CaptureType, CopyExpr);
+
+ return true;
+
+}
+
+
+/// \brief Capture the given variable in the captured region.
+static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
+ VarDecl *Var,
+ SourceLocation Loc,
+ const bool BuildAndDiagnose,
+ QualType &CaptureType,
+ QualType &DeclRefType,
+ const bool RefersToEnclosingLocal,
+ Sema &S) {
+
+ // By default, capture variables by reference.
+ bool ByRef = true;
+ // Using an LValue reference type is consistent with Lambdas (see below).
+ CaptureType = S.Context.getLValueReferenceType(DeclRefType);
+ Expr *CopyExpr = 0;
+ if (BuildAndDiagnose) {
+ // The current implementation assumes that all variables are captured
+ // by references. Since there is no capture by copy, no expression evaluation
+ // will be needed.
+ //
+ RecordDecl *RD = RSI->TheRecordDecl;
+
+ FieldDecl *Field
+ = FieldDecl::Create(S.Context, RD, Loc, Loc, 0, CaptureType,
+ S.Context.getTrivialTypeSourceInfo(CaptureType, Loc),
+ 0, false, ICIS_NoInit);
+ Field->setImplicit(true);
+ Field->setAccess(AS_private);
+ RD->addDecl(Field);
+
+ CopyExpr = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal,
+ DeclRefType, VK_LValue, Loc);
+ Var->setReferenced(true);
+ Var->markUsed(S.Context);
+ }
+
+ // Actually capture the variable.
+ if (BuildAndDiagnose)
+ RSI->addCapture(Var, /*isBlock*/false, ByRef, RefersToEnclosingLocal, Loc,
+ SourceLocation(), CaptureType, CopyExpr);
+
+
+ return true;
+}
+
+/// \brief Create a field within the lambda class for the variable
+/// being captured. Handle Array captures.
+static ExprResult addAsFieldToClosureType(Sema &S,
+ LambdaScopeInfo *LSI,
VarDecl *Var, QualType FieldType,
QualType DeclRefType,
SourceLocation Loc,
@@ -11032,7 +11632,7 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal,
DeclRefType, VK_LValue, Loc);
Var->setReferenced(true);
- Var->setUsed(true);
+ Var->markUsed(S.Context);
// When the field has array type, create index variables for each
// dimension of the array. We use these index variables to subscript
@@ -11088,7 +11688,8 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
SmallVector<InitializedEntity, 4> Entities;
Entities.reserve(1 + IndexVariables.size());
Entities.push_back(
- InitializedEntity::InitializeLambdaCapture(Var, Field, Loc));
+ InitializedEntity::InitializeLambdaCapture(Var->getIdentifier(),
+ Field->getType(), Loc));
for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
Entities.push_back(InitializedEntity::InitializeElement(S.Context,
0,
@@ -11113,127 +11714,207 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
return Result;
}
-bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
+
+
+/// \brief Capture the given variable in the lambda.
+static bool captureInLambda(LambdaScopeInfo *LSI,
+ VarDecl *Var,
+ SourceLocation Loc,
+ const bool BuildAndDiagnose,
+ QualType &CaptureType,
+ QualType &DeclRefType,
+ const bool RefersToEnclosingLocal,
+ const Sema::TryCaptureKind Kind,
+ SourceLocation EllipsisLoc,
+ const bool IsTopScope,
+ Sema &S) {
+
+ // Determine whether we are capturing by reference or by value.
+ bool ByRef = false;
+ if (IsTopScope && Kind != Sema::TryCapture_Implicit) {
+ ByRef = (Kind == Sema::TryCapture_ExplicitByRef);
+ } else {
+ ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref);
+ }
+
+ // Compute the type of the field that will capture this variable.
+ if (ByRef) {
+ // C++11 [expr.prim.lambda]p15:
+ // An entity is captured by reference if it is implicitly or
+ // explicitly captured but not captured by copy. It is
+ // unspecified whether additional unnamed non-static data
+ // members are declared in the closure type for entities
+ // captured by reference.
+ //
+ // FIXME: It is not clear whether we want to build an lvalue reference
+ // to the DeclRefType or to CaptureType.getNonReferenceType(). GCC appears
+ // to do the former, while EDG does the latter. Core issue 1249 will
+ // clarify, but for now we follow GCC because it's a more permissive and
+ // easily defensible position.
+ CaptureType = S.Context.getLValueReferenceType(DeclRefType);
+ } else {
+ // C++11 [expr.prim.lambda]p14:
+ // For each entity captured by copy, an unnamed non-static
+ // data member is declared in the closure type. The
+ // declaration order of these members is unspecified. The type
+ // of such a data member is the type of the corresponding
+ // captured entity if the entity is not a reference to an
+ // object, or the referenced type otherwise. [Note: If the
+ // captured entity is a reference to a function, the
+ // corresponding data member is also a reference to a
+ // function. - end note ]
+ if (const ReferenceType *RefType = CaptureType->getAs<ReferenceType>()){
+ if (!RefType->getPointeeType()->isFunctionType())
+ CaptureType = RefType->getPointeeType();
+ }
+
+ // Forbid the lambda copy-capture of autoreleasing variables.
+ if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
+ if (BuildAndDiagnose) {
+ S.Diag(Loc, diag::err_arc_autoreleasing_capture) << /*lambda*/ 1;
+ S.Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ }
+ return false;
+ }
+
+ if (S.RequireNonAbstractType(Loc, CaptureType,
+ diag::err_capture_of_abstract_type))
+ return false;
+ }
+
+ // Capture this variable in the lambda.
+ Expr *CopyExpr = 0;
+ if (BuildAndDiagnose) {
+ ExprResult Result = addAsFieldToClosureType(S, LSI, Var,
+ CaptureType, DeclRefType, Loc,
+ RefersToEnclosingLocal);
+ if (!Result.isInvalid())
+ CopyExpr = Result.take();
+ }
+
+ // Compute the type of a reference to this captured variable.
+ if (ByRef)
+ DeclRefType = CaptureType.getNonReferenceType();
+ else {
+ // C++ [expr.prim.lambda]p5:
+ // The closure type for a lambda-expression has a public inline
+ // function call operator [...]. This function call operator is
+ // declared const (9.3.1) if and only if the lambda-expression’s
+ // parameter-declaration-clause is not followed by mutable.
+ DeclRefType = CaptureType.getNonReferenceType();
+ if (!LSI->Mutable && !CaptureType->isReferenceType())
+ DeclRefType.addConst();
+ }
+
+ // Add the capture.
+ if (BuildAndDiagnose)
+ LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToEnclosingLocal,
+ Loc, EllipsisLoc, CaptureType, CopyExpr);
+
+ return true;
+}
+
+
+bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
TryCaptureKind Kind, SourceLocation EllipsisLoc,
bool BuildAndDiagnose,
QualType &CaptureType,
- QualType &DeclRefType) {
+ QualType &DeclRefType,
+ const unsigned *const FunctionScopeIndexToStopAt) {
bool Nested = false;
DeclContext *DC = CurContext;
- if (Var->getDeclContext() == DC) return true;
- if (!Var->hasLocalStorage()) return true;
+ const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
+ ? *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;
+ // We need to sync up the Declaration Context with the
+ // FunctionScopeIndexToStopAt
+ if (FunctionScopeIndexToStopAt) {
+ unsigned FSIndex = FunctionScopes.size() - 1;
+ while (FSIndex != MaxFunctionScopesIndex) {
+ DC = getLambdaAwareParentOfDeclContext(DC);
+ --FSIndex;
+ }
+ }
- bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
+
+ // If the variable is declared in the current context (and is not an
+ // init-capture), there is no need to capture it.
+ if (!Var->isInitCapture() && Var->getDeclContext() == DC) return true;
+ if (!Var->hasLocalStorage()) return true;
// Walk up the stack to determine whether we can capture the variable,
// performing the "simple" checks that don't depend on type. We stop when
// we've either hit the declared scope of the variable or find an existing
- // capture of that variable.
+ // capture of that variable. We start from the innermost capturing-entity
+ // (the DC) and ensure that all intervening capturing-entities
+ // (blocks/lambdas etc.) between the innermost capturer and the variable`s
+ // declcontext can either capture the variable or have already captured
+ // the variable.
CaptureType = Var->getType();
DeclRefType = CaptureType.getNonReferenceType();
bool Explicit = (Kind != TryCapture_Implicit);
- unsigned FunctionScopesIndex = FunctionScopes.size() - 1;
+ unsigned FunctionScopesIndex = MaxFunctionScopesIndex;
do {
// Only block literals, captured statements, and lambda expressions can
// capture; other scopes don't work.
- DeclContext *ParentDC;
- if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC))
- ParentDC = DC->getParent();
- else if (isa<CXXMethodDecl>(DC) &&
- cast<CXXMethodDecl>(DC)->getOverloadedOperator() == OO_Call &&
- cast<CXXRecordDecl>(DC->getParent())->isLambda())
- ParentDC = DC->getParent()->getParent();
- else {
- if (BuildAndDiagnose)
- diagnoseUncapturableValueReference(*this, Loc, Var, DC);
- return true;
- }
+ DeclContext *ParentDC = getParentOfCapturingContextOrNull(DC, Var,
+ ExprLoc,
+ BuildAndDiagnose,
+ *this);
+ if (!ParentDC) return true;
+
+ FunctionScopeInfo *FSI = FunctionScopes[FunctionScopesIndex];
+ CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FSI);
- CapturingScopeInfo *CSI =
- cast<CapturingScopeInfo>(FunctionScopes[FunctionScopesIndex]);
// Check whether we've already captured it.
- if (CSI->CaptureMap.count(Var)) {
- // If we found a capture, any subcaptures are nested.
- Nested = true;
-
- // Retrieve the capture type for this variable.
- CaptureType = CSI->getCapture(Var).getCaptureType();
-
- // Compute the type of an expression that refers to this variable.
- DeclRefType = CaptureType.getNonReferenceType();
-
- const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var);
- if (Cap.isCopyCapture() &&
- !(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable))
- DeclRefType.addConst();
+ if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,
+ DeclRefType))
break;
- }
-
- bool IsBlock = isa<BlockScopeInfo>(CSI);
- bool IsLambda = isa<LambdaScopeInfo>(CSI);
-
- // Lambdas are not allowed to capture unnamed variables
- // (e.g. anonymous unions).
- // FIXME: The C++11 rule don't actually state this explicitly, but I'm
- // assuming that's the intent.
- if (IsLambda && !Var->getDeclName()) {
+ // If we are instantiating a generic lambda call operator body,
+ // we do not want to capture new variables. What was captured
+ // during either a lambdas transformation or initial parsing
+ // should be used.
+ if (isGenericLambdaCallOperatorSpecialization(DC)) {
if (BuildAndDiagnose) {
- Diag(Loc, diag::err_lambda_capture_anonymous_var);
- Diag(Var->getLocation(), diag::note_declared_at);
- }
- return true;
- }
-
- // Prohibit variably-modified types; they're difficult to deal with.
- if (Var->getType()->isVariablyModifiedType()) {
- if (BuildAndDiagnose) {
- if (IsBlock)
- Diag(Loc, diag::err_ref_vm_type);
- else
- Diag(Loc, diag::err_lambda_capture_vm_type) << Var->getDeclName();
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
- }
- return true;
- }
- // Prohibit structs with flexible array members too.
- // We cannot capture what is in the tail end of the struct.
- if (const RecordType *VTTy = Var->getType()->getAs<RecordType>()) {
- if (VTTy->getDecl()->hasFlexibleArrayMember()) {
- if (BuildAndDiagnose) {
- if (IsBlock)
- Diag(Loc, diag::err_ref_flexarray_type);
- else
- Diag(Loc, diag::err_lambda_capture_flexarray_type)
- << Var->getDeclName();
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
- }
- return true;
- }
- }
- // Lambdas are not allowed to capture __block variables; they don't
- // support the expected semantics.
- if (IsLambda && HasBlocksAttr) {
- if (BuildAndDiagnose) {
- Diag(Loc, diag::err_lambda_capture_block)
- << Var->getDeclName();
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
+ LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
+ if (LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None) {
+ Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName();
+ Diag(Var->getLocation(), diag::note_previous_decl)
+ << Var->getDeclName();
+ Diag(LSI->Lambda->getLocStart(), diag::note_lambda_decl);
+ } else
+ diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC);
}
return true;
}
-
+ // Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
+ // certain types of variables (unnamed, variably modified types etc.)
+ // so check for eligibility.
+ if (!isVariableCapturable(CSI, Var, ExprLoc, BuildAndDiagnose, *this))
+ return true;
+
if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None && !Explicit) {
- // No capture-default
+ // No capture-default, and this is not an explicit capture
+ // so cannot capture this variable.
if (BuildAndDiagnose) {
- Diag(Loc, diag::err_lambda_impcap) << Var->getDeclName();
+ Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName();
Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getLocStart(),
diag::note_lambda_decl);
+ // FIXME: If we error out because an outer lambda can not implicitly
+ // capture a variable that an inner lambda explicitly captures, we
+ // should have the inner lambda do the explicit capture - because
+ // it makes for cleaner diagnostics later. This would purely be done
+ // so that the diagnostic does not misleadingly claim that a variable
+ // can not be captured by a lambda implicitly even though it is captured
+ // explicitly. Suggestion:
+ // - create const bool VariableCaptureWasInitiallyExplicit = Explicit
+ // at the function head
+ // - cache the StartingDeclContext - this must be a lambda
+ // - captureInLambda in the innermost lambda the variable.
}
return true;
}
@@ -11243,203 +11924,37 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
Explicit = false;
} while (!Var->getDeclContext()->Equals(DC));
- // Walk back down the scope stack, computing the type of the capture at
- // each step, checking type-specific requirements, and adding captures if
- // requested.
- for (unsigned I = ++FunctionScopesIndex, N = FunctionScopes.size(); I != N;
+ // Walk back down the scope stack, (e.g. from outer lambda to inner lambda)
+ // computing the type of the capture at each step, checking type-specific
+ // requirements, and adding captures if requested.
+ // If the variable had already been captured previously, we start capturing
+ // at the lambda nested within that one.
+ for (unsigned I = ++FunctionScopesIndex, N = MaxFunctionScopesIndex + 1; I != N;
++I) {
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[I]);
- // Compute the type of the capture and of a reference to the capture within
- // this scope.
- if (isa<BlockScopeInfo>(CSI)) {
- Expr *CopyExpr = 0;
- bool ByRef = false;
-
- // Blocks are not allowed to capture arrays.
- if (CaptureType->isArrayType()) {
- if (BuildAndDiagnose) {
- Diag(Loc, diag::err_ref_array_type);
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
- }
- return true;
- }
-
- // Forbid the block-capture of autoreleasing variables.
- if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
- if (BuildAndDiagnose) {
- Diag(Loc, diag::err_arc_autoreleasing_capture)
- << /*block*/ 0;
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
- }
+ if (BlockScopeInfo *BSI = dyn_cast<BlockScopeInfo>(CSI)) {
+ if (!captureInBlock(BSI, Var, ExprLoc,
+ BuildAndDiagnose, CaptureType,
+ DeclRefType, Nested, *this))
return true;
- }
-
- if (HasBlocksAttr || CaptureType->isReferenceType()) {
- // Block capture by reference does not change the capture or
- // declaration reference types.
- ByRef = true;
- } else {
- // Block capture by copy introduces 'const'.
- CaptureType = CaptureType.getNonReferenceType().withConst();
- DeclRefType = CaptureType;
-
- if (getLangOpts().CPlusPlus && BuildAndDiagnose) {
- if (const RecordType *Record = DeclRefType->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))
- FinalizeVarWithDestructor(Var, Record);
-
- // Enter a new evaluation context to insulate the copy
- // full-expression.
- EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated);
-
- // 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.
- Expr *DeclRef = new (Context) DeclRefExpr(Var, Nested,
- DeclRefType.withConst(),
- VK_LValue, Loc);
-
- ExprResult Result
- = PerformCopyInitialization(
- InitializedEntity::InitializeBlock(Var->getLocation(),
- CaptureType, false),
- Loc, Owned(DeclRef));
-
- // Build a full-expression copy expression if initialization
- // succeeded and used a non-trivial constructor. Recover from
- // errors by pretending that the copy isn't necessary.
- if (!Result.isInvalid() &&
- !cast<CXXConstructExpr>(Result.get())->getConstructor()
- ->isTrivial()) {
- Result = MaybeCreateExprWithCleanups(Result);
- CopyExpr = Result.take();
- }
- }
- }
- }
-
- // Actually capture the variable.
- if (BuildAndDiagnose)
- CSI->addCapture(Var, HasBlocksAttr, ByRef, Nested, Loc,
- SourceLocation(), CaptureType, CopyExpr);
Nested = true;
- continue;
- }
-
- if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
- // By default, capture variables by reference.
- bool ByRef = true;
- // Using an LValue reference type is consistent with Lambdas (see below).
- CaptureType = Context.getLValueReferenceType(DeclRefType);
-
- Expr *CopyExpr = 0;
- if (BuildAndDiagnose) {
- ExprResult Result = captureInCapturedRegion(*this, RSI, Var,
- CaptureType, DeclRefType,
- Loc, Nested);
- if (!Result.isInvalid())
- CopyExpr = Result.take();
- }
-
- // Actually capture the variable.
- if (BuildAndDiagnose)
- CSI->addCapture(Var, /*isBlock*/false, ByRef, Nested, Loc,
- SourceLocation(), CaptureType, CopyExpr);
+ } else if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
+ if (!captureInCapturedRegion(RSI, Var, ExprLoc,
+ BuildAndDiagnose, CaptureType,
+ DeclRefType, Nested, *this))
+ return true;
Nested = true;
- continue;
- }
-
- LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
-
- // Determine whether we are capturing by reference or by value.
- bool ByRef = false;
- if (I == N - 1 && Kind != TryCapture_Implicit) {
- ByRef = (Kind == TryCapture_ExplicitByRef);
- } else {
- ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref);
- }
-
- // Compute the type of the field that will capture this variable.
- if (ByRef) {
- // C++11 [expr.prim.lambda]p15:
- // An entity is captured by reference if it is implicitly or
- // explicitly captured but not captured by copy. It is
- // unspecified whether additional unnamed non-static data
- // members are declared in the closure type for entities
- // captured by reference.
- //
- // FIXME: It is not clear whether we want to build an lvalue reference
- // to the DeclRefType or to CaptureType.getNonReferenceType(). GCC appears
- // to do the former, while EDG does the latter. Core issue 1249 will
- // clarify, but for now we follow GCC because it's a more permissive and
- // easily defensible position.
- CaptureType = Context.getLValueReferenceType(DeclRefType);
} else {
- // C++11 [expr.prim.lambda]p14:
- // For each entity captured by copy, an unnamed non-static
- // data member is declared in the closure type. The
- // declaration order of these members is unspecified. The type
- // of such a data member is the type of the corresponding
- // captured entity if the entity is not a reference to an
- // object, or the referenced type otherwise. [Note: If the
- // captured entity is a reference to a function, the
- // corresponding data member is also a reference to a
- // function. - end note ]
- if (const ReferenceType *RefType = CaptureType->getAs<ReferenceType>()){
- if (!RefType->getPointeeType()->isFunctionType())
- CaptureType = RefType->getPointeeType();
- }
-
- // Forbid the lambda copy-capture of autoreleasing variables.
- if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
- if (BuildAndDiagnose) {
- Diag(Loc, diag::err_arc_autoreleasing_capture) << /*lambda*/ 1;
- Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
- }
+ LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
+ if (!captureInLambda(LSI, Var, ExprLoc,
+ BuildAndDiagnose, CaptureType,
+ DeclRefType, Nested, Kind, EllipsisLoc,
+ /*IsTopScope*/I == N - 1, *this))
return true;
- }
- }
-
- // Capture this variable in the lambda.
- Expr *CopyExpr = 0;
- if (BuildAndDiagnose) {
- ExprResult Result = captureInLambda(*this, LSI, Var, CaptureType,
- DeclRefType, Loc,
- Nested);
- if (!Result.isInvalid())
- CopyExpr = Result.take();
- }
-
- // Compute the type of a reference to this captured variable.
- if (ByRef)
- DeclRefType = CaptureType.getNonReferenceType();
- else {
- // C++ [expr.prim.lambda]p5:
- // The closure type for a lambda-expression has a public inline
- // function call operator [...]. This function call operator is
- // declared const (9.3.1) if and only if the lambda-expression’s
- // parameter-declaration-clause is not followed by mutable.
- DeclRefType = CaptureType.getNonReferenceType();
- if (!LSI->Mutable && !CaptureType->isReferenceType())
- DeclRefType.addConst();
+ Nested = true;
}
-
- // Add the capture.
- if (BuildAndDiagnose)
- CSI->addCapture(Var, /*IsBlock=*/false, ByRef, Nested, Loc,
- EllipsisLoc, CaptureType, CopyExpr);
- Nested = true;
}
-
return false;
}
@@ -11449,7 +11964,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
QualType DeclRefType;
return tryCaptureVariable(Var, Loc, Kind, EllipsisLoc,
/*BuildAndDiagnose=*/true, CaptureType,
- DeclRefType);
+ DeclRefType, 0);
}
QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
@@ -11458,28 +11973,36 @@ QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
// Determine whether we can capture this variable.
if (tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(),
- /*BuildAndDiagnose=*/false, CaptureType, DeclRefType))
+ /*BuildAndDiagnose=*/false, CaptureType,
+ DeclRefType, 0))
return QualType();
return DeclRefType;
}
-static void MarkVarDeclODRUsed(Sema &SemaRef, VarDecl *Var,
- SourceLocation Loc) {
- // Keep track of used but undefined variables.
- // FIXME: We shouldn't suppress this warning for static data members.
- if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&
- Var->getLinkage() != ExternalLinkage &&
- !(Var->isStaticDataMember() && Var->hasInit())) {
- SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()];
- if (old.isInvalid()) old = Loc;
- }
- SemaRef.tryCaptureVariable(Var, Loc);
- Var->setUsed(true);
+// If either the type of the variable or the initializer is dependent,
+// return false. Otherwise, determine whether the variable is a constant
+// expression. Use this if you need to know if a variable that might or
+// might not be dependent is truly a constant expression.
+static inline bool IsVariableNonDependentAndAConstantExpression(VarDecl *Var,
+ ASTContext &Context) {
+
+ if (Var->getType()->isDependentType())
+ return false;
+ const VarDecl *DefVD = 0;
+ Var->getAnyInitializer(DefVD);
+ if (!DefVD)
+ return false;
+ EvaluatedStmt *Eval = DefVD->ensureEvaluatedStmt();
+ Expr *Init = cast<Expr>(Eval->Value);
+ if (Init->isValueDependent())
+ return false;
+ return IsVariableAConstantExpression(Var, Context);
}
+
void Sema::UpdateMarkingForLValueToRValue(Expr *E) {
// Per C++11 [basic.def.odr], a variable is odr-used "unless it is
// an object that satisfies the requirements for appearing in a
@@ -11487,6 +12010,22 @@ void Sema::UpdateMarkingForLValueToRValue(Expr *E) {
// is immediately applied." This function handles the lvalue-to-rvalue
// conversion part.
MaybeODRUseExprs.erase(E->IgnoreParens());
+
+ // If we are in a lambda, check if this DeclRefExpr or MemberExpr refers
+ // to a variable that is a constant expression, and if so, identify it as
+ // a reference to a variable that does not involve an odr-use of that
+ // variable.
+ if (LambdaScopeInfo *LSI = getCurLambda()) {
+ Expr *SansParensExpr = E->IgnoreParens();
+ VarDecl *Var = 0;
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SansParensExpr))
+ Var = dyn_cast<VarDecl>(DRE->getFoundDecl());
+ else if (MemberExpr *ME = dyn_cast<MemberExpr>(SansParensExpr))
+ Var = dyn_cast<VarDecl>(ME->getMemberDecl());
+
+ if (Var && IsVariableNonDependentAndAConstantExpression(Var, Context))
+ LSI->markVariableExprAsNonODRUsed(SansParensExpr);
+ }
}
ExprResult Sema::ActOnConstantExpression(ExprResult Res) {
@@ -11517,46 +12056,105 @@ void Sema::CleanupVarDeclMarking() {
llvm_unreachable("Unexpcted expression");
}
- MarkVarDeclODRUsed(*this, Var, Loc);
+ MarkVarDeclODRUsed(Var, Loc, *this, /*MaxFunctionScopeIndex Pointer*/ 0);
}
MaybeODRUseExprs.clear();
}
-// Mark a VarDecl referenced, and perform the necessary handling to compute
-// odr-uses.
+
static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
VarDecl *Var, Expr *E) {
+ assert((!E || isa<DeclRefExpr>(E) || isa<MemberExpr>(E)) &&
+ "Invalid Expr argument to DoMarkVarDeclReferenced");
Var->setReferenced();
- if (!IsPotentiallyEvaluatedContext(SemaRef))
- return;
-
- // Implicit instantiation of static data members of class templates.
- if (Var->isStaticDataMember() && Var->getInstantiatedFromStaticDataMember()) {
- MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
- assert(MSInfo && "Missing member specialization information?");
- bool AlreadyInstantiated = !MSInfo->getPointOfInstantiation().isInvalid();
- if (MSInfo->getTemplateSpecializationKind() == TSK_ImplicitInstantiation &&
- (!AlreadyInstantiated ||
- Var->isUsableInConstantExpressions(SemaRef.Context))) {
- if (!AlreadyInstantiated) {
+ // If the context is not PotentiallyEvaluated and not Unevaluated
+ // (i.e PotentiallyEvaluatedIfUsed) do not bother to consider variables
+ // in this context for odr-use unless we are within a lambda.
+ // If we don't know whether the context is potentially evaluated or not
+ // (for e.g., if we're in a generic lambda), we want to add a potential
+ // capture and eventually analyze for odr-use.
+ // We should also be able to analyze certain constructs in a non-generic
+ // lambda setting for potential odr-use and capture violation:
+ // template<class T> void foo(T t) {
+ // auto L = [](int i) { return t; };
+ // }
+ //
+ if (!IsPotentiallyEvaluatedContext(SemaRef)) {
+
+ if (SemaRef.isUnevaluatedContext()) return;
+
+ const bool refersToEnclosingScope =
+ (SemaRef.CurContext != Var->getDeclContext() &&
+ Var->getDeclContext()->isFunctionOrMethod());
+ if (!refersToEnclosingScope) return;
+
+ if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) {
+ // If a variable could potentially be odr-used, defer marking it so
+ // until we finish analyzing the full expression for any lvalue-to-rvalue
+ // or discarded value conversions that would obviate odr-use.
+ // Add it to the list of potential captures that will be analyzed
+ // later (ActOnFinishFullExpr) for eventual capture and odr-use marking
+ // unless the variable is a reference that was initialized by a constant
+ // expression (this will never need to be captured or odr-used).
+ const bool IsConstantExpr = IsVariableNonDependentAndAConstantExpression(
+ Var, SemaRef.Context);
+ assert(E && "Capture variable should be used in an expression.");
+ if (!IsConstantExpr || !Var->getType()->isReferenceType())
+ LSI->addPotentialCapture(E->IgnoreParens());
+ }
+ return;
+ }
+
+ VarTemplateSpecializationDecl *VarSpec =
+ dyn_cast<VarTemplateSpecializationDecl>(Var);
+ assert(!isa<VarTemplatePartialSpecializationDecl>(Var) &&
+ "Can't instantiate a partial template specialization.");
+
+ // Implicit instantiation of static data members, static data member
+ // templates of class templates, and variable template specializations.
+ // Delay instantiations of variable templates, except for those
+ // that could be used in a constant expression.
+ TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
+ if (isTemplateInstantiation(TSK)) {
+ bool TryInstantiating = TSK == TSK_ImplicitInstantiation;
+
+ if (TryInstantiating && !isa<VarTemplateSpecializationDecl>(Var)) {
+ if (Var->getPointOfInstantiation().isInvalid()) {
// This is a modification of an existing AST node. Notify listeners.
if (ASTMutationListener *L = SemaRef.getASTMutationListener())
L->StaticDataMemberInstantiated(Var);
- MSInfo->setPointOfInstantiation(Loc);
+ } else if (!Var->isUsableInConstantExpressions(SemaRef.Context))
+ // Don't bother trying to instantiate it again, unless we might need
+ // its initializer before we get to the end of the TU.
+ TryInstantiating = false;
+ }
+
+ if (Var->getPointOfInstantiation().isInvalid())
+ Var->setTemplateSpecializationKind(TSK, Loc);
+
+ if (TryInstantiating) {
+ SourceLocation PointOfInstantiation = Var->getPointOfInstantiation();
+ bool InstantiationDependent = false;
+ bool IsNonDependent =
+ VarSpec ? !TemplateSpecializationType::anyDependentTemplateArguments(
+ VarSpec->getTemplateArgsInfo(), InstantiationDependent)
+ : true;
+
+ // Do not instantiate specializations that are still type-dependent.
+ if (IsNonDependent) {
+ if (Var->isUsableInConstantExpressions(SemaRef.Context)) {
+ // Do not defer instantiations of variables which could be used in a
+ // constant expression.
+ SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var);
+ } else {
+ SemaRef.PendingInstantiations
+ .push_back(std::make_pair(Var, PointOfInstantiation));
+ }
}
- SourceLocation PointOfInstantiation = MSInfo->getPointOfInstantiation();
- if (Var->isUsableInConstantExpressions(SemaRef.Context))
- // Do not defer instantiations of variables which could be used in a
- // constant expression.
- SemaRef.InstantiateStaticDataMemberDefinition(PointOfInstantiation,Var);
- else
- SemaRef.PendingInstantiations.push_back(
- std::make_pair(Var, PointOfInstantiation));
}
}
-
// Per C++11 [basic.def.odr], a variable is odr-used "unless it satisfies
// the requirements for appearing in a constant expression (5.19) and, if
// it is an object, the lvalue-to-rvalue conversion (4.1)
@@ -11565,14 +12163,16 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
// Note that we use the C++11 definition everywhere because nothing in
// C++03 depends on whether we get the C++03 version correct. The second
// part does not apply to references, since they are not objects.
- const VarDecl *DefVD;
- if (E && !isa<ParmVarDecl>(Var) &&
- Var->isUsableInConstantExpressions(SemaRef.Context) &&
- Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE()) {
+ if (E && IsVariableAConstantExpression(Var, SemaRef.Context)) {
+ // A reference initialized by a constant expression can never be
+ // odr-used, so simply ignore it.
+ // But a non-reference might get odr-used if it doesn't undergo
+ // an lvalue-to-rvalue or is discarded, so track it.
if (!Var->getType()->isReferenceType())
SemaRef.MaybeODRUseExprs.insert(E);
- } else
- MarkVarDeclODRUsed(SemaRef, Var, Loc);
+ }
+ else
+ MarkVarDeclODRUsed(Var, Loc, SemaRef, /*MaxFunctionScopeIndex ptr*/0);
}
/// \brief Mark a variable referenced, and check whether it is odr-used
@@ -11889,7 +12489,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
Selector Sel = ME->getSelector();
// self = [<foo> init...]
- if (isSelfExpr(Op->getLHS()) && Sel.getNameForSlot(0).startswith("init"))
+ if (isSelfExpr(Op->getLHS()) && ME->getMethodFamily() == OMF_init)
diagnostic = diag::warn_condition_is_idiomatic_assignment;
// <foo> = [<bar> nextObject]
@@ -12204,15 +12804,49 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) {
assert(E->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,
- ArrayRef<QualType>(Proto->arg_type_begin(),
- Proto->getNumArgs()),
- Proto->getExtProtoInfo());
- else
+ const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType);
+ if (Proto) {
+ // __unknown_anytype(...) is a special case used by the debugger when
+ // it has no idea what a function's signature is.
+ //
+ // We want to build this call essentially under the K&R
+ // unprototyped rules, but making a FunctionNoProtoType in C++
+ // would foul up all sorts of assumptions. However, we cannot
+ // simply pass all arguments as variadic arguments, nor can we
+ // portably just call the function under a non-variadic type; see
+ // the comment on IR-gen's TargetInfo::isNoProtoCallVariadic.
+ // However, it turns out that in practice it is generally safe to
+ // call a function declared as "A foo(B,C,D);" under the prototype
+ // "A foo(B,C,D,...);". The only known exception is with the
+ // Windows ABI, where any variadic function is implicitly cdecl
+ // regardless of its normal CC. Therefore we change the parameter
+ // types to match the types of the arguments.
+ //
+ // This is a hack, but it is far superior to moving the
+ // corresponding target-specific code from IR-gen to Sema/AST.
+
+ ArrayRef<QualType> ParamTypes = Proto->getArgTypes();
+ SmallVector<QualType, 8> ArgTypes;
+ if (ParamTypes.empty() && Proto->isVariadic()) { // the special case
+ ArgTypes.reserve(E->getNumArgs());
+ for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
+ Expr *Arg = E->getArg(i);
+ QualType ArgType = Arg->getType();
+ if (E->isLValue()) {
+ ArgType = S.Context.getLValueReferenceType(ArgType);
+ } else if (E->isXValue()) {
+ ArgType = S.Context.getRValueReferenceType(ArgType);
+ }
+ ArgTypes.push_back(ArgType);
+ }
+ ParamTypes = ArgTypes;
+ }
+ DestType = S.Context.getFunctionType(DestType, ParamTypes,
+ Proto->getExtProtoInfo());
+ } else {
DestType = S.Context.getFunctionNoProtoType(DestType,
FnType->getExtInfo());
+ }
// Rebuild the appropriate pointer-to-function type.
switch (Kind) {
@@ -12345,6 +12979,8 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
return ExprError();
}
+ // Modifying the declaration like this is friendly to IR-gen but
+ // also really dangerous.
VD->setType(DestType);
E->setType(Type);
E->setValueKind(ValueKind);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
index 27032a911147..07e465766b74 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
@@ -31,6 +32,7 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaLambda.h"
#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/STLExtras.h"
@@ -305,7 +307,7 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
SemaDiagnosticBuilder DtorDiag = Diag(NameLoc,
diag::err_destructor_class_name);
if (S) {
- const DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+ const DeclContext *Ctx = S->getEntity();
if (const CXXRecordDecl *Class = dyn_cast_or_null<CXXRecordDecl>(Ctx))
DtorDiag << FixItHint::CreateReplacement(SourceRange(NameLoc),
Class->getNameAsString());
@@ -462,11 +464,16 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
TypeSourceInfo *Operand,
SourceLocation RParenLoc) {
if (!Operand->getType()->isDependentType()) {
- if (!CXXUuidofExpr::GetUuidAttrOfType(Operand->getType()))
- return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
+ bool HasMultipleGUIDs = false;
+ if (!CXXUuidofExpr::GetUuidAttrOfType(Operand->getType(),
+ &HasMultipleGUIDs)) {
+ if (HasMultipleGUIDs)
+ return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids));
+ else
+ return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
+ }
}
- // FIXME: add __uuidof semantic analysis for type operand.
return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(),
Operand,
SourceRange(TypeidLoc, RParenLoc)));
@@ -478,11 +485,16 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
Expr *E,
SourceLocation RParenLoc) {
if (!E->getType()->isDependentType()) {
- if (!CXXUuidofExpr::GetUuidAttrOfType(E->getType()) &&
- !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
- return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
+ bool HasMultipleGUIDs = false;
+ if (!CXXUuidofExpr::GetUuidAttrOfType(E->getType(), &HasMultipleGUIDs) &&
+ !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+ if (HasMultipleGUIDs)
+ return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids));
+ else
+ return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
+ }
}
- // FIXME: add __uuidof semantic analysis for type operand.
+
return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(),
E,
SourceRange(TypeidLoc, RParenLoc)));
@@ -741,21 +753,30 @@ static Expr *captureThis(ASTContext &Context, RecordDecl *RD,
return new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit*/true);
}
-void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) {
+bool Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit,
+ bool BuildAndDiagnose, const unsigned *const FunctionScopeIndexToStopAt) {
// We don't need to capture this in an unevaluated context.
if (isUnevaluatedContext() && !Explicit)
- return;
+ return true;
- // Otherwise, check that we can capture 'this'.
+ const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt ?
+ *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;
+ // Otherwise, check that we can capture 'this'.
unsigned NumClosures = 0;
- for (unsigned idx = FunctionScopes.size() - 1; idx != 0; idx--) {
+ for (unsigned idx = MaxFunctionScopesIndex; idx != 0; idx--) {
if (CapturingScopeInfo *CSI =
dyn_cast<CapturingScopeInfo>(FunctionScopes[idx])) {
if (CSI->CXXThisCaptureIndex != 0) {
// 'this' is already being captured; there isn't anything more to do.
break;
}
-
+ LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI);
+ if (LSI && isGenericLambdaCallOperatorSpecialization(LSI->CallOperator)) {
+ // This context can't implicitly capture 'this'; fail out.
+ if (BuildAndDiagnose)
+ Diag(Loc, diag::err_this_capture) << Explicit;
+ return true;
+ }
if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByref ||
CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByval ||
CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_Block ||
@@ -767,17 +788,18 @@ void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) {
continue;
}
// This context can't implicitly capture 'this'; fail out.
- Diag(Loc, diag::err_this_capture) << Explicit;
- return;
+ if (BuildAndDiagnose)
+ Diag(Loc, diag::err_this_capture) << Explicit;
+ return true;
}
break;
}
-
+ if (!BuildAndDiagnose) return false;
// Mark that we're implicitly capturing 'this' in all the scopes we skipped.
// FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated
// contexts.
- for (unsigned idx = FunctionScopes.size() - 1;
- NumClosures; --idx, --NumClosures) {
+ for (unsigned idx = MaxFunctionScopesIndex; NumClosures;
+ --idx, --NumClosures) {
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]);
Expr *ThisExpr = 0;
QualType ThisTy = getCurrentThisType();
@@ -791,6 +813,7 @@ void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) {
bool isNested = NumClosures > 1;
CSI->addThisCapture(isNested, Loc, ThisTy, ThisExpr);
}
+ return false;
}
ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
@@ -893,17 +916,21 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
InitializationSequence InitSeq(*this, Entity, Kind, Exprs);
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Exprs);
- if (!Result.isInvalid() && ListInitialization &&
- isa<InitListExpr>(Result.get())) {
+ if (Result.isInvalid() || !ListInitialization)
+ return Result;
+
+ Expr *Inner = Result.get();
+ if (CXXBindTemporaryExpr *BTE = dyn_cast_or_null<CXXBindTemporaryExpr>(Inner))
+ Inner = BTE->getSubExpr();
+ if (isa<InitListExpr>(Inner)) {
// If the list-initialization doesn't involve a constructor call, we'll get
// the initializer-list (with corrected type) back, but that's not what we
// want, since it will be treated as an initializer list in further
// processing. Explicitly insert a cast here.
- InitListExpr *List = cast<InitListExpr>(Result.take());
- Result = Owned(CXXFunctionalCastExpr::Create(Context, List->getType(),
- Expr::getValueKindForType(TInfo->getType()),
- TInfo, TyBeginLoc, CK_NoOp,
- List, /*Path=*/0, RParenLoc));
+ QualType ResultType = Result.get()->getType();
+ Result = Owned(CXXFunctionalCastExpr::Create(
+ Context, ResultType, Expr::getValueKindForType(TInfo->getType()), TInfo,
+ CK_NoOp, Result.take(), /*Path=*/ 0, LParenLoc, RParenLoc));
}
// FIXME: Improve AST representation?
@@ -1017,10 +1044,23 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr;
if (Expr *NumElts = (Expr *)Array.NumElts) {
if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) {
- Array.NumElts
- = VerifyIntegerConstantExpression(NumElts, 0,
- diag::err_new_array_nonconst)
- .take();
+ if (getLangOpts().CPlusPlus1y) {
+ // C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator
+ // shall be a converted constant expression (5.19) of type std::size_t
+ // and shall evaluate to a strictly positive value.
+ unsigned IntWidth = Context.getTargetInfo().getIntWidth();
+ assert(IntWidth && "Builtin type of size 0?");
+ llvm::APSInt Value(IntWidth);
+ Array.NumElts
+ = CheckConvertedConstantExpression(NumElts, Context.getSizeType(), Value,
+ CCEK_NewExpr)
+ .take();
+ } else {
+ Array.NumElts
+ = VerifyIntegerConstantExpression(NumElts, 0,
+ diag::err_new_array_nonconst)
+ .take();
+ }
if (!Array.NumElts)
return ExprError();
}
@@ -1180,70 +1220,85 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// C++11 [expr.new]p6: The expression [...] shall be of integral or unscoped
// enumeration type, or a class type for which a single non-explicit
// conversion function to integral or unscoped enumeration type exists.
+ // C++1y [expr.new]p6: The expression [...] is implicitly converted to
+ // std::size_t.
if (ArraySize && !ArraySize->isTypeDependent()) {
- class SizeConvertDiagnoser : public ICEConvertDiagnoser {
- Expr *ArraySize;
-
- public:
- SizeConvertDiagnoser(Expr *ArraySize)
- : ICEConvertDiagnoser(false, false), ArraySize(ArraySize) { }
-
- virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
- QualType T) {
- return S.Diag(Loc, diag::err_array_size_not_integral)
- << S.getLangOpts().CPlusPlus11 << T;
- }
-
- virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
- QualType T) {
- return S.Diag(Loc, diag::err_array_size_incomplete_type)
- << T << ArraySize->getSourceRange();
- }
-
- virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S,
- SourceLocation Loc,
- QualType T,
- QualType ConvTy) {
- return S.Diag(Loc, diag::err_array_size_explicit_conversion) << T << ConvTy;
- }
-
- virtual DiagnosticBuilder noteExplicitConv(Sema &S,
- CXXConversionDecl *Conv,
- QualType ConvTy) {
- return S.Diag(Conv->getLocation(), diag::note_array_size_conversion)
- << ConvTy->isEnumeralType() << ConvTy;
- }
-
- virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
- QualType T) {
- return S.Diag(Loc, diag::err_array_size_ambiguous_conversion) << T;
- }
-
- virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
- QualType ConvTy) {
- return S.Diag(Conv->getLocation(), diag::note_array_size_conversion)
- << ConvTy->isEnumeralType() << ConvTy;
- }
-
- virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,
- QualType T,
- QualType ConvTy) {
- return S.Diag(Loc,
- S.getLangOpts().CPlusPlus11
- ? diag::warn_cxx98_compat_array_size_conversion
- : diag::ext_array_size_conversion)
- << T << ConvTy->isEnumeralType() << ConvTy;
- }
- } SizeDiagnoser(ArraySize);
+ ExprResult ConvertedSize;
+ if (getLangOpts().CPlusPlus1y) {
+ unsigned IntWidth = Context.getTargetInfo().getIntWidth();
+ assert(IntWidth && "Builtin type of size 0?");
+ llvm::APSInt Value(IntWidth);
+ ConvertedSize = PerformImplicitConversion(ArraySize, Context.getSizeType(),
+ AA_Converting);
+
+ if (!ConvertedSize.isInvalid() &&
+ ArraySize->getType()->getAs<RecordType>())
+ // Diagnose the compatibility of this conversion.
+ Diag(StartLoc, diag::warn_cxx98_compat_array_size_conversion)
+ << ArraySize->getType() << 0 << "'size_t'";
+ } else {
+ class SizeConvertDiagnoser : public ICEConvertDiagnoser {
+ protected:
+ Expr *ArraySize;
+
+ public:
+ SizeConvertDiagnoser(Expr *ArraySize)
+ : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false, false, false),
+ ArraySize(ArraySize) {}
+
+ virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) {
+ return S.Diag(Loc, diag::err_array_size_not_integral)
+ << S.getLangOpts().CPlusPlus11 << T;
+ }
+
+ virtual SemaDiagnosticBuilder diagnoseIncomplete(
+ Sema &S, SourceLocation Loc, QualType T) {
+ return S.Diag(Loc, diag::err_array_size_incomplete_type)
+ << T << ArraySize->getSourceRange();
+ }
+
+ virtual SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ return S.Diag(Loc, diag::err_array_size_explicit_conversion) << T << ConvTy;
+ }
+
+ virtual SemaDiagnosticBuilder noteExplicitConv(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ return S.Diag(Conv->getLocation(), diag::note_array_size_conversion)
+ << ConvTy->isEnumeralType() << ConvTy;
+ }
+
+ virtual SemaDiagnosticBuilder diagnoseAmbiguous(
+ Sema &S, SourceLocation Loc, QualType T) {
+ return S.Diag(Loc, diag::err_array_size_ambiguous_conversion) << T;
+ }
+
+ virtual SemaDiagnosticBuilder noteAmbiguous(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ return S.Diag(Conv->getLocation(), diag::note_array_size_conversion)
+ << ConvTy->isEnumeralType() << ConvTy;
+ }
+
+ virtual SemaDiagnosticBuilder diagnoseConversion(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ return S.Diag(Loc,
+ S.getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_array_size_conversion
+ : diag::ext_array_size_conversion)
+ << T << ConvTy->isEnumeralType() << ConvTy;
+ }
+ } SizeDiagnoser(ArraySize);
- ExprResult ConvertedSize
- = ConvertToIntegralOrEnumerationType(StartLoc, ArraySize, SizeDiagnoser,
- /*AllowScopedEnumerations*/ false);
+ ConvertedSize = PerformContextualImplicitConversion(StartLoc, ArraySize,
+ SizeDiagnoser);
+ }
if (ConvertedSize.isInvalid())
return ExprError();
ArraySize = ConvertedSize.take();
QualType SizeType = ArraySize->getType();
+
if (!SizeType->isIntegralOrUnscopedEnumerationType())
return ExprError();
@@ -1306,16 +1361,13 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
FunctionDecl *OperatorNew = 0;
FunctionDecl *OperatorDelete = 0;
- Expr **PlaceArgs = PlacementArgs.data();
- unsigned NumPlaceArgs = PlacementArgs.size();
if (!AllocType->isDependentType() &&
- !Expr::hasAnyTypeDependentArguments(
- llvm::makeArrayRef(PlaceArgs, NumPlaceArgs)) &&
+ !Expr::hasAnyTypeDependentArguments(PlacementArgs) &&
FindAllocationFunctions(StartLoc,
SourceRange(PlacementLParen, PlacementRParen),
- UseGlobal, AllocType, ArraySize, PlaceArgs,
- NumPlaceArgs, OperatorNew, OperatorDelete))
+ UseGlobal, AllocType, ArraySize, PlacementArgs,
+ OperatorNew, OperatorDelete))
return ExprError();
// If this is an array allocation, compute whether the usual array
@@ -1333,24 +1385,21 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
VariadicCallType CallType =
Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply;
- if (GatherArgumentsForCall(PlacementLParen, OperatorNew,
- Proto, 1, PlaceArgs, NumPlaceArgs,
- AllPlaceArgs, CallType))
+ if (GatherArgumentsForCall(PlacementLParen, OperatorNew, Proto, 1,
+ PlacementArgs, AllPlaceArgs, CallType))
return ExprError();
- NumPlaceArgs = AllPlaceArgs.size();
- if (NumPlaceArgs > 0)
- PlaceArgs = &AllPlaceArgs[0];
+ if (!AllPlaceArgs.empty())
+ PlacementArgs = AllPlaceArgs;
- DiagnoseSentinelCalls(OperatorNew, PlacementLParen,
- PlaceArgs, NumPlaceArgs);
+ DiagnoseSentinelCalls(OperatorNew, PlacementLParen, PlacementArgs);
// FIXME: Missing call to CheckFunctionCall or equivalent
}
// Warn if the type is over-aligned and is being allocated by global operator
// new.
- if (NumPlaceArgs == 0 && OperatorNew &&
+ if (PlacementArgs.empty() && OperatorNew &&
(OperatorNew->isImplicit() ||
getSourceManager().isInSystemHeader(OperatorNew->getLocStart()))) {
if (unsigned Align = Context.getPreferredTypeAlign(AllocType.getTypePtr())){
@@ -1458,8 +1507,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew,
OperatorDelete,
UsualArrayDeleteWantsSize,
- llvm::makeArrayRef(PlaceArgs, NumPlaceArgs),
- TypeIdParens,
+ PlacementArgs, TypeIdParens,
ArraySize, initStyle, Initializer,
ResultType, AllocTypeInfo,
Range, DirectInitRange));
@@ -1504,24 +1552,30 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
/// \brief Determine whether the given function is a non-placement
/// deallocation function.
-static bool isNonPlacementDeallocationFunction(FunctionDecl *FD) {
+static bool isNonPlacementDeallocationFunction(Sema &S, FunctionDecl *FD) {
if (FD->isInvalidDecl())
return false;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))
return Method->isUsualDeallocationFunction();
- return ((FD->getOverloadedOperator() == OO_Delete ||
- FD->getOverloadedOperator() == OO_Array_Delete) &&
- FD->getNumParams() == 1);
+ if (FD->getOverloadedOperator() != OO_Delete &&
+ FD->getOverloadedOperator() != OO_Array_Delete)
+ return false;
+
+ if (FD->getNumParams() == 1)
+ return true;
+
+ return S.getLangOpts().SizedDeallocation && FD->getNumParams() == 2 &&
+ S.Context.hasSameUnqualifiedType(FD->getParamDecl(1)->getType(),
+ S.Context.getSizeType());
}
/// FindAllocationFunctions - Finds the overloads of operator new and delete
/// that are appropriate for the allocation.
bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
bool UseGlobal, QualType AllocType,
- bool IsArray, Expr **PlaceArgs,
- unsigned NumPlaceArgs,
+ bool IsArray, MultiExprArg PlaceArgs,
FunctionDecl *&OperatorNew,
FunctionDecl *&OperatorDelete) {
// --- Choosing an allocation function ---
@@ -1533,7 +1587,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// 3) The first argument is always size_t. Append the arguments from the
// placement form.
- SmallVector<Expr*, 8> AllocArgs(1 + NumPlaceArgs);
+ SmallVector<Expr*, 8> AllocArgs(1 + PlaceArgs.size());
// We don't care about the actual value of this argument.
// FIXME: Should the Sema create the expression and embed it in the syntax
// tree? Or should the consumer just recalculate the value?
@@ -1542,7 +1596,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
Context.getSizeType(),
SourceLocation());
AllocArgs[0] = &Size;
- std::copy(PlaceArgs, PlaceArgs + NumPlaceArgs, AllocArgs.begin() + 1);
+ std::copy(PlaceArgs.begin(), PlaceArgs.end(), AllocArgs.begin() + 1);
// C++ [expr.new]p8:
// If the allocated type is a non-array type, the allocation
@@ -1560,19 +1614,32 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
if (AllocElemType->isRecordType() && !UseGlobal) {
CXXRecordDecl *Record
= cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl());
- if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0],
- AllocArgs.size(), Record, /*AllowMissing=*/true,
- OperatorNew))
+ if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, Record,
+ /*AllowMissing=*/true, OperatorNew))
return true;
}
+
if (!OperatorNew) {
// Didn't find a member overload. Look for a global one.
DeclareGlobalNewDelete();
DeclContext *TUDecl = Context.getTranslationUnitDecl();
- if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0],
- AllocArgs.size(), TUDecl, /*AllowMissing=*/false,
- OperatorNew))
+ bool FallbackEnabled = IsArray && Context.getLangOpts().MicrosoftMode;
+ if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, TUDecl,
+ /*AllowMissing=*/FallbackEnabled, OperatorNew,
+ /*Diagnose=*/!FallbackEnabled)) {
+ if (!FallbackEnabled)
+ return true;
+
+ // MSVC will fall back on trying to find a matching global operator new
+ // if operator new[] cannot be found. Also, MSVC will leak by not
+ // generating a call to operator delete or operator delete[], but we
+ // will not replicate that bug.
+ NewName = Context.DeclarationNames.getCXXOperatorName(OO_New);
+ DeleteName = Context.DeclarationNames.getCXXOperatorName(OO_Delete);
+ if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, TUDecl,
+ /*AllowMissing=*/false, OperatorNew))
return true;
+ }
}
// We don't need an operator delete if we're running under
@@ -1584,8 +1651,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// FindAllocationOverload can change the passed in arguments, so we need to
// copy them back.
- if (NumPlaceArgs > 0)
- std::copy(&AllocArgs[1], AllocArgs.end(), PlaceArgs);
+ if (!PlaceArgs.empty())
+ std::copy(AllocArgs.begin() + 1, AllocArgs.end(), PlaceArgs.data());
// C++ [expr.new]p19:
//
@@ -1619,7 +1686,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// we had explicit placement arguments. This matters for things like
// struct A { void *operator new(size_t, int = 0); ... };
// A *a = new A()
- bool isPlacementNew = (NumPlaceArgs > 0 || OperatorNew->param_size() != 1);
+ bool isPlacementNew = (!PlaceArgs.empty() || OperatorNew->param_size() != 1);
if (isPlacementNew) {
// C++ [expr.new]p20:
@@ -1676,9 +1743,28 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
DEnd = FoundDelete.end();
D != DEnd; ++D) {
if (FunctionDecl *Fn = dyn_cast<FunctionDecl>((*D)->getUnderlyingDecl()))
- if (isNonPlacementDeallocationFunction(Fn))
+ if (isNonPlacementDeallocationFunction(*this, Fn))
Matches.push_back(std::make_pair(D.getPair(), Fn));
}
+
+ // C++1y [expr.new]p22:
+ // For a non-placement allocation function, the normal deallocation
+ // function lookup is used
+ // C++1y [expr.delete]p?:
+ // If [...] deallocation function lookup finds both a usual deallocation
+ // function with only a pointer parameter and a usual deallocation
+ // function with both a pointer parameter and a size parameter, then the
+ // selected deallocation function shall be the one with two parameters.
+ // Otherwise, the selected deallocation function shall be the function
+ // with one parameter.
+ if (getLangOpts().SizedDeallocation && Matches.size() == 2) {
+ if (Matches[0].second->getNumParams() == 1)
+ Matches.erase(Matches.begin());
+ else
+ Matches.erase(Matches.begin() + 1);
+ assert(Matches[0].second->getNumParams() == 2 &&
+ "found an unexpected uusal deallocation function");
+ }
}
// C++ [expr.new]p20:
@@ -1694,13 +1780,14 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// as a placement deallocation function, would have been
// selected as a match for the allocation function, the program
// is ill-formed.
- if (NumPlaceArgs && getLangOpts().CPlusPlus11 &&
- isNonPlacementDeallocationFunction(OperatorDelete)) {
+ if (!PlaceArgs.empty() && getLangOpts().CPlusPlus11 &&
+ isNonPlacementDeallocationFunction(*this, OperatorDelete)) {
Diag(StartLoc, diag::err_placement_new_non_placement_delete)
- << SourceRange(PlaceArgs[0]->getLocStart(),
- PlaceArgs[NumPlaceArgs - 1]->getLocEnd());
- Diag(OperatorDelete->getLocation(), diag::note_previous_decl)
- << DeleteName;
+ << SourceRange(PlaceArgs.front()->getLocStart(),
+ PlaceArgs.back()->getLocEnd());
+ if (!OperatorDelete->isImplicit())
+ Diag(OperatorDelete->getLocation(), diag::note_previous_decl)
+ << DeleteName;
} else {
CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(),
Matches[0].first);
@@ -1713,8 +1800,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
/// FindAllocationOverload - Find an fitting overload for the allocation
/// function in the specified scope.
bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
- DeclarationName Name, Expr** Args,
- unsigned NumArgs, DeclContext *Ctx,
+ DeclarationName Name, MultiExprArg Args,
+ DeclContext *Ctx,
bool AllowMissing, FunctionDecl *&Operator,
bool Diagnose) {
LookupResult R(*this, Name, StartLoc, LookupOrdinaryName);
@@ -1741,15 +1828,13 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) {
AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(),
/*ExplicitTemplateArgs=*/0,
- llvm::makeArrayRef(Args, NumArgs),
- Candidates,
+ Args, Candidates,
/*SuppressUserConversions=*/false);
continue;
}
FunctionDecl *Fn = cast<FunctionDecl>(D);
- AddOverloadCandidate(Fn, Alloc.getPair(),
- llvm::makeArrayRef(Args, NumArgs), Candidates,
+ AddOverloadCandidate(Fn, Alloc.getPair(), Args, Candidates,
/*SuppressUserConversions=*/false);
}
@@ -1765,7 +1850,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
// asserted on, though, since invalid decls are left in there.)
// Watch out for variadic allocator function.
unsigned NumArgsInFnDecl = FnDecl->getNumParams();
- for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) {
+ for (unsigned i = 0; (i < Args.size() && i < NumArgsInFnDecl); ++i) {
InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
FnDecl->getParamDecl(i));
@@ -1793,8 +1878,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
if (Diagnose) {
Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
<< Name << Range;
- Candidates.NoteCandidates(*this, OCD_AllCandidates,
- llvm::makeArrayRef(Args, NumArgs));
+ Candidates.NoteCandidates(*this, OCD_AllCandidates, Args);
}
return true;
@@ -1802,8 +1886,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
if (Diagnose) {
Diag(StartLoc, diag::err_ovl_ambiguous_call)
<< Name << Range;
- Candidates.NoteCandidates(*this, OCD_ViableCandidates,
- llvm::makeArrayRef(Args, NumArgs));
+ Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args);
}
return true;
@@ -1814,8 +1897,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
<< Name
<< getDeletedOrUnavailableSuffix(Best->Function)
<< Range;
- Candidates.NoteCandidates(*this, OCD_AllCandidates,
- llvm::makeArrayRef(Args, NumArgs));
+ Candidates.NoteCandidates(*this, OCD_AllCandidates, Args);
}
return true;
}
@@ -1832,13 +1914,19 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
/// void* operator new[](std::size_t) throw(std::bad_alloc);
/// void operator delete(void *) throw();
/// void operator delete[](void *) throw();
-/// // C++0x:
+/// // C++11:
+/// void* operator new(std::size_t);
+/// void* operator new[](std::size_t);
+/// void operator delete(void *) noexcept;
+/// void operator delete[](void *) noexcept;
+/// // C++1y:
/// void* operator new(std::size_t);
/// void* operator new[](std::size_t);
-/// void operator delete(void *);
-/// void operator delete[](void *);
+/// void operator delete(void *) noexcept;
+/// void operator delete[](void *) noexcept;
+/// void operator delete(void *, std::size_t) noexcept;
+/// void operator delete[](void *, std::size_t) noexcept;
/// @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() {
@@ -1855,11 +1943,18 @@ void Sema::DeclareGlobalNewDelete() {
// void* operator new[](std::size_t) throw(std::bad_alloc);
// void operator delete(void*) throw();
// void operator delete[](void*) throw();
- // C++0x:
+ // C++11:
+ // void* operator new(std::size_t);
+ // void* operator new[](std::size_t);
+ // void operator delete(void*) noexcept;
+ // void operator delete[](void*) noexcept;
+ // C++1y:
// void* operator new(std::size_t);
// void* operator new[](std::size_t);
- // void operator delete(void*);
- // void operator delete[](void*);
+ // void operator delete(void*) noexcept;
+ // void operator delete[](void*) noexcept;
+ // void operator delete(void*, std::size_t) noexcept;
+ // void operator delete[](void*, std::size_t) noexcept;
//
// These implicit declarations introduce only the function names operator
// new, operator new[], operator delete, operator delete[].
@@ -1868,8 +1963,6 @@ 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.
- // Note that the C++0x versions of operator delete are deallocation functions,
- // and thus are implicitly noexcept.
if (!StdBadAlloc && !getLangOpts().CPlusPlus11) {
// The "std::bad_alloc" class has not yet been declared, so build it
// implicitly.
@@ -1889,40 +1982,61 @@ void Sema::DeclareGlobalNewDelete() {
DeclareGlobalAllocationFunction(
Context.DeclarationNames.getCXXOperatorName(OO_New),
- VoidPtr, SizeT, AssumeSaneOperatorNew);
+ VoidPtr, SizeT, QualType(), AssumeSaneOperatorNew);
DeclareGlobalAllocationFunction(
Context.DeclarationNames.getCXXOperatorName(OO_Array_New),
- VoidPtr, SizeT, AssumeSaneOperatorNew);
+ VoidPtr, SizeT, QualType(), AssumeSaneOperatorNew);
DeclareGlobalAllocationFunction(
Context.DeclarationNames.getCXXOperatorName(OO_Delete),
Context.VoidTy, VoidPtr);
DeclareGlobalAllocationFunction(
Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete),
Context.VoidTy, VoidPtr);
+ if (getLangOpts().SizedDeallocation) {
+ DeclareGlobalAllocationFunction(
+ Context.DeclarationNames.getCXXOperatorName(OO_Delete),
+ Context.VoidTy, VoidPtr, Context.getSizeType());
+ DeclareGlobalAllocationFunction(
+ Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete),
+ Context.VoidTy, VoidPtr, Context.getSizeType());
+ }
}
/// DeclareGlobalAllocationFunction - Declares a single implicit global
/// allocation function if it doesn't already exist.
void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
- QualType Return, QualType Argument,
+ QualType Return,
+ QualType Param1, QualType Param2,
bool AddMallocAttr) {
DeclContext *GlobalCtx = Context.getTranslationUnitDecl();
+ unsigned NumParams = Param2.isNull() ? 1 : 2;
// Check if this function is already declared.
- {
- DeclContext::lookup_result R = GlobalCtx->lookup(Name);
- for (DeclContext::lookup_iterator Alloc = R.begin(), AllocEnd = R.end();
- Alloc != AllocEnd; ++Alloc) {
- // Only look at non-template functions, as it is the predefined,
- // non-templated allocation function we are trying to declare here.
- if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) {
- QualType InitialParamType =
- Context.getCanonicalType(
- Func->getParamDecl(0)->getType().getUnqualifiedType());
+ DeclContext::lookup_result R = GlobalCtx->lookup(Name);
+ for (DeclContext::lookup_iterator Alloc = R.begin(), AllocEnd = R.end();
+ Alloc != AllocEnd; ++Alloc) {
+ // Only look at non-template functions, as it is the predefined,
+ // non-templated allocation function we are trying to declare here.
+ if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) {
+ if (Func->getNumParams() == NumParams) {
+ QualType InitialParam1Type =
+ Context.getCanonicalType(Func->getParamDecl(0)
+ ->getType().getUnqualifiedType());
+ QualType InitialParam2Type =
+ NumParams == 2
+ ? Context.getCanonicalType(Func->getParamDecl(1)
+ ->getType().getUnqualifiedType())
+ : QualType();
// FIXME: Do we need to check for default arguments here?
- if (Func->getNumParams() == 1 && InitialParamType == Argument) {
- if(AddMallocAttr && !Func->hasAttr<MallocAttr>())
- Func->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
+ if (InitialParam1Type == Param1 &&
+ (NumParams == 1 || InitialParam2Type == Param2)) {
+ if (AddMallocAttr && !Func->hasAttr<MallocAttr>())
+ Func->addAttr(::new (Context) MallocAttr(SourceLocation(),
+ Context));
+ // Make the function visible to name lookup, even if we found it in
+ // an unimported module. It either is an implicitly-declared global
+ // allocation function, or is suppressing that function.
+ Func->setHidden(false);
return;
}
}
@@ -1950,7 +2064,10 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
EST_BasicNoexcept : EST_DynamicNone;
}
- QualType FnType = Context.getFunctionType(Return, Argument, EPI);
+ QualType Params[] = { Param1, Param2 };
+
+ QualType FnType = Context.getFunctionType(
+ Return, ArrayRef<QualType>(Params, NumParams), EPI);
FunctionDecl *Alloc =
FunctionDecl::Create(Context, GlobalCtx, SourceLocation(),
SourceLocation(), Name,
@@ -1960,11 +2077,13 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
if (AddMallocAttr)
Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
- ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
- SourceLocation(), 0,
- Argument, /*TInfo=*/0,
- SC_None, 0);
- Alloc->setParams(Param);
+ ParmVarDecl *ParamDecls[2];
+ for (unsigned I = 0; I != NumParams; ++I)
+ ParamDecls[I] = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
+ SourceLocation(), 0,
+ Params[I], /*TInfo=*/0,
+ SC_None, 0);
+ Alloc->setParams(ArrayRef<ParmVarDecl*>(ParamDecls, NumParams));
// FIXME: Also add this declaration to the IdentifierResolver, but
// make sure it is at the end of the chain to coincide with the
@@ -1972,6 +2091,48 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
Context.getTranslationUnitDecl()->addDecl(Alloc);
}
+FunctionDecl *Sema::FindUsualDeallocationFunction(SourceLocation StartLoc,
+ bool CanProvideSize,
+ DeclarationName Name) {
+ DeclareGlobalNewDelete();
+
+ LookupResult FoundDelete(*this, Name, StartLoc, LookupOrdinaryName);
+ LookupQualifiedName(FoundDelete, Context.getTranslationUnitDecl());
+
+ // C++ [expr.new]p20:
+ // [...] Any non-placement deallocation function matches a
+ // non-placement allocation function. [...]
+ llvm::SmallVector<FunctionDecl*, 2> Matches;
+ for (LookupResult::iterator D = FoundDelete.begin(),
+ DEnd = FoundDelete.end();
+ D != DEnd; ++D) {
+ if (FunctionDecl *Fn = dyn_cast<FunctionDecl>(*D))
+ if (isNonPlacementDeallocationFunction(*this, Fn))
+ Matches.push_back(Fn);
+ }
+
+ // C++1y [expr.delete]p?:
+ // If the type is complete and deallocation function lookup finds both a
+ // usual deallocation function with only a pointer parameter and a usual
+ // deallocation function with both a pointer parameter and a size
+ // parameter, then the selected deallocation function shall be the one
+ // with two parameters. Otherwise, the selected deallocation function
+ // shall be the function with one parameter.
+ if (getLangOpts().SizedDeallocation && Matches.size() == 2) {
+ unsigned NumArgs = CanProvideSize ? 2 : 1;
+ if (Matches[0]->getNumParams() != NumArgs)
+ Matches.erase(Matches.begin());
+ else
+ Matches.erase(Matches.begin() + 1);
+ assert(Matches[0]->getNumParams() == NumArgs &&
+ "found an unexpected uusal deallocation function");
+ }
+
+ assert(Matches.size() == 1 &&
+ "unexpectedly have multiple usual deallocation functions");
+ return Matches.front();
+}
+
bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
DeclarationName Name,
FunctionDecl* &Operator, bool Diagnose) {
@@ -2045,19 +2206,7 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
return true;
}
- // Look for a global declaration.
- DeclareGlobalNewDelete();
- DeclContext *TUDecl = Context.getTranslationUnitDecl();
-
- CXXNullPtrLiteralExpr Null(Context.VoidPtrTy, SourceLocation());
- Expr* DeallocArgs[1];
- DeallocArgs[0] = &Null;
- if (FindAllocationOverload(StartLoc, SourceRange(), Name,
- DeallocArgs, 1, TUDecl, !Diagnose,
- Operator, Diagnose))
- return true;
-
- assert(Operator && "Did not find a deallocation function!");
+ Operator = 0;
return false;
}
@@ -2070,7 +2219,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
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.
+ // non-explicit conversion function to a pointer type. The result has type
+ // void.
//
// DR599 amends "pointer type" to "pointer to object type" in both cases.
@@ -2087,59 +2237,65 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
QualType Type = Ex.get()->getType();
- if (const RecordType *Record = Type->getAs<RecordType>()) {
- if (RequireCompleteType(StartLoc, Type,
- diag::err_delete_incomplete_class_type))
- return ExprError();
+ class DeleteConverter : public ContextualImplicitConverter {
+ public:
+ DeleteConverter() : ContextualImplicitConverter(false, true) {}
- SmallVector<CXXConversionDecl*, 4> ObjectPtrConversions;
+ bool match(QualType ConvType) {
+ // FIXME: If we have an operator T* and an operator void*, we must pick
+ // the operator T*.
+ if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+ if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType())
+ return true;
+ return false;
+ }
- CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
- std::pair<CXXRecordDecl::conversion_iterator,
- CXXRecordDecl::conversion_iterator>
- Conversions = RD->getVisibleConversionFunctions();
- for (CXXRecordDecl::conversion_iterator
- I = Conversions.first, E = Conversions.second; I != E; ++I) {
- NamedDecl *D = I.getDecl();
- if (isa<UsingShadowDecl>(D))
- D = cast<UsingShadowDecl>(D)->getTargetDecl();
+ SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc,
+ QualType T) {
+ return S.Diag(Loc, diag::err_delete_operand) << T;
+ }
- // Skip over templated conversion functions; they aren't considered.
- if (isa<FunctionTemplateDecl>(D))
- continue;
+ SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
+ QualType T) {
+ return S.Diag(Loc, diag::err_delete_incomplete_class_type) << T;
+ }
- CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
+ SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
+ QualType T, QualType ConvTy) {
+ return S.Diag(Loc, diag::err_delete_explicit_conversion) << T << ConvTy;
+ }
- QualType ConvType = Conv->getConversionType().getNonReferenceType();
- if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
- if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType())
- ObjectPtrConversions.push_back(Conv);
+ SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
+ QualType ConvTy) {
+ return S.Diag(Conv->getLocation(), diag::note_delete_conversion)
+ << ConvTy;
}
- if (ObjectPtrConversions.size() == 1) {
- // We have a single conversion to a pointer-to-object type. Perform
- // that conversion.
- // TODO: don't redo the conversion calculation.
- ExprResult Res =
- PerformImplicitConversion(Ex.get(),
- ObjectPtrConversions.front()->getConversionType(),
- AA_Converting);
- if (Res.isUsable()) {
- Ex = Res;
- Type = Ex.get()->getType();
- }
+
+ SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
+ QualType T) {
+ return S.Diag(Loc, diag::err_ambiguous_delete_operand) << T;
}
- else if (ObjectPtrConversions.size() > 1) {
- Diag(StartLoc, diag::err_ambiguous_delete_operand)
- << Type << Ex.get()->getSourceRange();
- for (unsigned i= 0; i < ObjectPtrConversions.size(); i++)
- NoteOverloadCandidate(ObjectPtrConversions[i]);
- return ExprError();
+
+ SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
+ QualType ConvTy) {
+ return S.Diag(Conv->getLocation(), diag::note_delete_conversion)
+ << ConvTy;
}
- }
- if (!Type->isPointerType())
- return ExprError(Diag(StartLoc, diag::err_delete_operand)
- << Type << Ex.get()->getSourceRange());
+ SemaDiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,
+ QualType T, QualType ConvTy) {
+ llvm_unreachable("conversion functions are permitted");
+ }
+ } Converter;
+
+ Ex = PerformContextualImplicitConversion(StartLoc, Ex.take(), Converter);
+ if (Ex.isInvalid())
+ return ExprError();
+ Type = Ex.get()->getType();
+ if (!Converter.match(Type))
+ // FIXME: PerformContextualImplicitConversion should return ExprError
+ // itself in this case.
+ return ExprError();
QualType Pointee = Type->getAs<PointerType>()->getPointeeType();
QualType PointeeElem = Context.getBaseElementType(Pointee);
@@ -2200,7 +2356,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
// Otherwise, the usual operator delete[] should be the
// function we just found.
- else if (isa<CXXMethodDecl>(OperatorDelete))
+ else if (OperatorDelete && isa<CXXMethodDecl>(OperatorDelete))
UsualArrayDeleteWantsSize = (OperatorDelete->getNumParams() == 2);
}
@@ -2238,19 +2394,13 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
}
- if (!OperatorDelete) {
+ if (!OperatorDelete)
// Look for a global declaration.
- DeclareGlobalNewDelete();
- DeclContext *TUDecl = Context.getTranslationUnitDecl();
- Expr *Arg = Ex.get();
- if (!Context.hasSameType(Arg->getType(), Context.VoidPtrTy))
- Arg = ImplicitCastExpr::Create(Context, Context.VoidPtrTy,
- CK_BitCast, Arg, 0, VK_RValue);
- if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName,
- &Arg, 1, TUDecl, /*AllowMissing=*/false,
- OperatorDelete))
- return ExprError();
- }
+ OperatorDelete = FindUsualDeallocationFunction(
+ StartLoc, !RequireCompleteType(StartLoc, Pointee, 0) &&
+ (!ArrayForm || UsualArrayDeleteWantsSize ||
+ Pointee.isDestructedType()),
+ DeleteName);
MarkFunctionReferenced(StartLoc, OperatorDelete);
@@ -2261,7 +2411,6 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
PDiag(diag::err_access_dtor) << PointeeElem);
}
}
-
}
return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm,
@@ -2377,6 +2526,10 @@ static ExprResult BuildCXXCastArgument(Sema &S,
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Method);
SmallVector<Expr*, 8> ConstructorArgs;
+ if (S.RequireNonAbstractType(CastLoc, Ty,
+ diag::err_allocation_of_abstract_type))
+ return ExprError();
+
if (S.CompleteConstructorCall(Constructor, From, CastLoc, ConstructorArgs))
return ExprError();
@@ -2462,7 +2615,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
BeforeToType = Ctor->getParamDecl(0)->getType().getNonReferenceType();
}
}
- // Watch out for elipsis conversion.
+ // Watch out for ellipsis conversion.
if (!ICS.UserDefined.EllipsisConversion) {
ExprResult Res =
PerformImplicitConversion(From, BeforeToType,
@@ -2566,6 +2719,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
FromType = From->getType();
}
+ // If we're converting to an atomic type, first convert to the corresponding
+ // non-atomic type.
+ QualType ToAtomicType;
+ if (const AtomicType *ToAtomic = ToType->getAs<AtomicType>()) {
+ ToAtomicType = ToType;
+ ToType = ToAtomic->getValueType();
+ }
+
// Perform the first implicit conversion.
switch (SCS.First) {
case ICK_Identity:
@@ -2715,7 +2876,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
(void) PrepareCastToObjCObjectPointer(E);
From = E.take();
}
-
+ if (getLangOpts().ObjCAutoRefCount)
+ CheckObjCARCConversion(SourceRange(), ToType, From, CCK);
From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
.take();
break;
@@ -2875,7 +3037,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
<< ToType.getNonReferenceType();
break;
- }
+ }
default:
llvm_unreachable("Improper third standard conversion");
@@ -2883,11 +3045,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// If this conversion sequence involved a scalar -> atomic conversion, perform
// that conversion now.
- if (const AtomicType *ToAtomic = ToType->getAs<AtomicType>())
- if (Context.hasSameType(ToAtomic->getValueType(), From->getType()))
- From = ImpCastExprToType(From, ToType, CK_NonAtomicToAtomic, VK_RValue, 0,
- CCK).take();
-
+ if (!ToAtomicType.isNull()) {
+ assert(Context.hasSameType(
+ ToAtomicType->castAs<AtomicType>()->getValueType(), From->getType()));
+ From = ImpCastExprToType(From, ToAtomicType, CK_NonAtomicToAtomic,
+ VK_RValue, 0, CCK).take();
+ }
+
return Owned(From);
}
@@ -2979,6 +3143,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
// These traits require a complete type.
case UTT_IsFinal:
+ case UTT_IsSealed:
// These trait expressions are designed to help implement predicates in
// [meta.unary.prop] despite not being named the same. They are specified
@@ -3152,6 +3317,11 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
return RD->hasAttr<FinalAttr>();
return false;
+ case UTT_IsSealed:
+ if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+ if (FinalAttr *FA = RD->getAttr<FinalAttr>())
+ return FA->isSpelledAsSealed();
+ return false;
case UTT_IsSigned:
return T->isSignedIntegerType();
case UTT_IsUnsigned:
@@ -3444,8 +3614,8 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
// is_trivially_constructible is defined as:
//
// is_constructible<T, Args...>::value is true and the variable
- // definition for is_constructible, as defined below, is known to call no
- // operation that is not trivial.
+ // definition for is_constructible, as defined below, is known to call
+ // no operation that is not trivial.
//
// The predicate condition for a template specialization
// is_constructible<T, Args...> shall be satisfied if and only if the
@@ -3458,24 +3628,24 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
<< 1 << 1 << 1 << (int)Args.size();
return false;
}
-
- bool SawVoid = false;
+
+ // Precondition: T and all types in the parameter pack Args shall be
+ // complete types, (possibly cv-qualified) void, or arrays of
+ // unknown bound.
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
- if (Args[I]->getType()->isVoidType()) {
- SawVoid = true;
+ QualType ArgTy = Args[I]->getType();
+ if (ArgTy->isVoidType() || ArgTy->isIncompleteArrayType())
continue;
- }
-
- if (!Args[I]->getType()->isIncompleteType() &&
- S.RequireCompleteType(KWLoc, Args[I]->getType(),
+
+ if (S.RequireCompleteType(KWLoc, ArgTy,
diag::err_incomplete_type_used_in_type_trait_expr))
return false;
}
-
- // If any argument was 'void', of course it won't type-check.
- if (SawVoid)
+
+ // Make sure the first argument is a complete type.
+ if (Args[0]->getType()->isIncompleteType())
return false;
-
+
SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs;
SmallVector<Expr *, 2> ArgExprs;
ArgExprs.reserve(Args.size() - 1);
@@ -4259,8 +4429,8 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// ... 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 a prvalue.
- bool LThrow = isa<CXXThrowExpr>(LHS.get());
- bool RThrow = isa<CXXThrowExpr>(RHS.get());
+ bool LThrow = isa<CXXThrowExpr>(LHS.get()->IgnoreParenCasts());
+ bool RThrow = isa<CXXThrowExpr>(RHS.get()->IgnoreParenCasts());
if (LThrow && !RThrow)
return RTy;
if (RThrow && !LThrow)
@@ -4991,6 +5161,32 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
return Owned(E);
}
+/// Note a set of 'operator->' functions that were used for a member access.
+static void noteOperatorArrows(Sema &S,
+ llvm::ArrayRef<FunctionDecl *> OperatorArrows) {
+ unsigned SkipStart = OperatorArrows.size(), SkipCount = 0;
+ // FIXME: Make this configurable?
+ unsigned Limit = 9;
+ if (OperatorArrows.size() > Limit) {
+ // Produce Limit-1 normal notes and one 'skipping' note.
+ SkipStart = (Limit - 1) / 2 + (Limit - 1) % 2;
+ SkipCount = OperatorArrows.size() - (Limit - 1);
+ }
+
+ for (unsigned I = 0; I < OperatorArrows.size(); /**/) {
+ if (I == SkipStart) {
+ S.Diag(OperatorArrows[I]->getLocation(),
+ diag::note_operator_arrows_suppressed)
+ << SkipCount;
+ I += SkipCount;
+ } else {
+ S.Diag(OperatorArrows[I]->getLocation(), diag::note_operator_arrow_here)
+ << OperatorArrows[I]->getCallResultType();
+ ++I;
+ }
+ }
+}
+
ExprResult
Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
tok::TokenKind OpKind, ParsedType &ObjectType,
@@ -5023,29 +5219,68 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
// [...] When operator->returns, the operator-> is applied to the value
// returned, with the original second operand.
if (OpKind == tok::arrow) {
+ QualType StartingType = BaseType;
+ bool NoArrowOperatorFound = false;
+ bool FirstIteration = true;
+ FunctionDecl *CurFD = dyn_cast<FunctionDecl>(CurContext);
// The set of types we've considered so far.
llvm::SmallPtrSet<CanQualType,8> CTypes;
- SmallVector<SourceLocation, 8> Locations;
+ SmallVector<FunctionDecl*, 8> OperatorArrows;
CTypes.insert(Context.getCanonicalType(BaseType));
while (BaseType->isRecordType()) {
- Result = BuildOverloadedArrowExpr(S, Base, OpLoc);
- if (Result.isInvalid())
+ if (OperatorArrows.size() >= getLangOpts().ArrowDepth) {
+ Diag(OpLoc, diag::err_operator_arrow_depth_exceeded)
+ << StartingType << getLangOpts().ArrowDepth << Base->getSourceRange();
+ noteOperatorArrows(*this, OperatorArrows);
+ Diag(OpLoc, diag::note_operator_arrow_depth)
+ << getLangOpts().ArrowDepth;
+ return ExprError();
+ }
+
+ Result = BuildOverloadedArrowExpr(
+ S, Base, OpLoc,
+ // When in a template specialization and on the first loop iteration,
+ // potentially give the default diagnostic (with the fixit in a
+ // separate note) instead of having the error reported back to here
+ // and giving a diagnostic with a fixit attached to the error itself.
+ (FirstIteration && CurFD && CurFD->isFunctionTemplateSpecialization())
+ ? 0
+ : &NoArrowOperatorFound);
+ if (Result.isInvalid()) {
+ if (NoArrowOperatorFound) {
+ if (FirstIteration) {
+ Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+ << BaseType << 1 << Base->getSourceRange()
+ << FixItHint::CreateReplacement(OpLoc, ".");
+ OpKind = tok::period;
+ break;
+ }
+ Diag(OpLoc, diag::err_typecheck_member_reference_arrow)
+ << BaseType << Base->getSourceRange();
+ CallExpr *CE = dyn_cast<CallExpr>(Base);
+ if (Decl *CD = (CE ? CE->getCalleeDecl() : 0)) {
+ Diag(CD->getLocStart(),
+ diag::note_member_reference_arrow_from_operator_arrow);
+ }
+ }
return ExprError();
+ }
Base = Result.get();
if (CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(Base))
- Locations.push_back(OpCall->getDirectCallee()->getLocation());
+ OperatorArrows.push_back(OpCall->getDirectCallee());
BaseType = Base->getType();
CanQualType CBaseType = Context.getCanonicalType(BaseType);
if (!CTypes.insert(CBaseType)) {
- Diag(OpLoc, diag::err_operator_arrow_circular);
- for (unsigned i = 0; i < Locations.size(); i++)
- Diag(Locations[i], diag::note_declared_at);
+ Diag(OpLoc, diag::err_operator_arrow_circular) << StartingType;
+ noteOperatorArrows(*this, OperatorArrows);
return ExprError();
}
+ FirstIteration = false;
}
- if (BaseType->isPointerType() || BaseType->isObjCObjectPointerType())
+ if (OpKind == tok::arrow &&
+ (BaseType->isPointerType() || BaseType->isObjCObjectPointerType()))
BaseType = BaseType->getPointeeType();
}
@@ -5555,7 +5790,7 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) {
if (Res.isInvalid())
return Owned(E);
E = Res.take();
- }
+ }
return Owned(E);
}
@@ -5579,15 +5814,144 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) {
return Owned(E);
}
+// If we can unambiguously determine whether Var can never be used
+// in a constant expression, return true.
+// - if the variable and its initializer are non-dependent, then
+// we can unambiguously check if the variable is a constant expression.
+// - if the initializer is not value dependent - we can determine whether
+// it can be used to initialize a constant expression. If Init can not
+// be used to initialize a constant expression we conclude that Var can
+// never be a constant expression.
+// - FXIME: if the initializer is dependent, we can still do some analysis and
+// identify certain cases unambiguously as non-const by using a Visitor:
+// - such as those that involve odr-use of a ParmVarDecl, involve a new
+// delete, lambda-expr, dynamic-cast, reinterpret-cast etc...
+static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var,
+ ASTContext &Context) {
+ if (isa<ParmVarDecl>(Var)) return true;
+ const VarDecl *DefVD = 0;
+
+ // If there is no initializer - this can not be a constant expression.
+ if (!Var->getAnyInitializer(DefVD)) return true;
+ assert(DefVD);
+ if (DefVD->isWeak()) return false;
+ EvaluatedStmt *Eval = DefVD->ensureEvaluatedStmt();
+
+ Expr *Init = cast<Expr>(Eval->Value);
+
+ if (Var->getType()->isDependentType() || Init->isValueDependent()) {
+ if (!Init->isValueDependent())
+ return !DefVD->checkInitIsICE();
+ // FIXME: We might still be able to do some analysis of Init here
+ // to conclude that even in a dependent setting, Init can never
+ // be a constexpr - but for now admit agnosticity.
+ return false;
+ }
+ return !IsVariableAConstantExpression(Var, Context);
+}
+
+/// \brief Check if the current lambda scope has any potential captures, and
+/// whether they can be captured by any of the enclosing lambdas that are
+/// ready to capture. If there is a lambda that can capture a nested
+/// potential-capture, go ahead and do so. Also, check to see if any
+/// variables are uncaptureable or do not involve an odr-use so do not
+/// need to be captured.
+
+static void CheckLambdaCaptures(Expr *const FE,
+ LambdaScopeInfo *const CurrentLSI, Sema &S) {
+
+ assert(!S.isUnevaluatedContext());
+ assert(S.CurContext->isDependentContext());
+ const bool IsFullExprInstantiationDependent =
+ FE->isInstantiationDependent();
+ // All the potentially captureable variables in the current nested
+ // lambda (within a generic outer lambda), must be captured by an
+ // outer lambda that is enclosed within a non-dependent context.
+
+ for (size_t I = 0, N = CurrentLSI->getNumPotentialVariableCaptures();
+ I != N; ++I) {
+ Expr *VarExpr = 0;
+ VarDecl *Var = 0;
+ CurrentLSI->getPotentialVariableCapture(I, Var, VarExpr);
+ //
+ if (CurrentLSI->isVariableExprMarkedAsNonODRUsed(VarExpr) &&
+ !IsFullExprInstantiationDependent)
+ continue;
+ // Climb up until we find a lambda that can capture:
+ // - a generic-or-non-generic lambda call operator that is enclosed
+ // within a non-dependent context.
+ unsigned FunctionScopeIndexOfCapturableLambda = 0;
+ if (GetInnermostEnclosingCapturableLambda(
+ S.FunctionScopes, FunctionScopeIndexOfCapturableLambda,
+ S.CurContext, Var, S)) {
+ MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(),
+ S, &FunctionScopeIndexOfCapturableLambda);
+ }
+ const bool IsVarNeverAConstantExpression =
+ VariableCanNeverBeAConstantExpression(Var, S.Context);
+ if (!IsFullExprInstantiationDependent || IsVarNeverAConstantExpression) {
+ // This full expression is not instantiation dependent or the variable
+ // can not be used in a constant expression - which means
+ // this variable must be odr-used here, so diagnose a
+ // capture violation early, if the variable is un-captureable.
+ // This is purely for diagnosing errors early. Otherwise, this
+ // error would get diagnosed when the lambda becomes capture ready.
+ QualType CaptureType, DeclRefType;
+ SourceLocation ExprLoc = VarExpr->getExprLoc();
+ if (S.tryCaptureVariable(Var, ExprLoc, S.TryCapture_Implicit,
+ /*EllipsisLoc*/ SourceLocation(),
+ /*BuildAndDiagnose*/false, CaptureType,
+ DeclRefType, 0)) {
+ // We will never be able to capture this variable, and we need
+ // to be able to in any and all instantiations, so diagnose it.
+ S.tryCaptureVariable(Var, ExprLoc, S.TryCapture_Implicit,
+ /*EllipsisLoc*/ SourceLocation(),
+ /*BuildAndDiagnose*/true, CaptureType,
+ DeclRefType, 0);
+ }
+ }
+ }
+
+ if (CurrentLSI->hasPotentialThisCapture()) {
+ unsigned FunctionScopeIndexOfCapturableLambda = 0;
+ if (GetInnermostEnclosingCapturableLambda(
+ S.FunctionScopes, FunctionScopeIndexOfCapturableLambda,
+ S.CurContext, /*0 is 'this'*/ 0, S)) {
+ S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation,
+ /*Explicit*/false, /*BuildAndDiagnose*/true,
+ &FunctionScopeIndexOfCapturableLambda);
+ }
+ }
+ CurrentLSI->clearPotentialCaptures();
+}
+
+
ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
bool DiscardedValue,
- bool IsConstexpr) {
+ bool IsConstexpr,
+ bool IsLambdaInitCaptureInitializer) {
ExprResult FullExpr = Owned(FE);
if (!FullExpr.get())
return ExprError();
-
- if (DiagnoseUnexpandedParameterPack(FullExpr.get()))
+
+ // If we are an init-expression in a lambdas init-capture, we should not
+ // diagnose an unexpanded pack now (will be diagnosed once lambda-expr
+ // containing full-expression is done).
+ // template<class ... Ts> void test(Ts ... t) {
+ // test([&a(t)]() { <-- (t) is an init-expr that shouldn't be diagnosed now.
+ // return a;
+ // }() ...);
+ // }
+ // FIXME: This is a hack. It would be better if we pushed the lambda scope
+ // when we parse the lambda introducer, and teach capturing (but not
+ // unexpanded pack detection) to walk over LambdaScopeInfos which don't have a
+ // corresponding class yet (that is, have LambdaScopeInfo either represent a
+ // lambda where we've entered the introducer but not the body, or represent a
+ // lambda where we've entered the body, depending on where the
+ // parser/instantiation has got to).
+ if (!IsLambdaInitCaptureInitializer &&
+ DiagnoseUnexpandedParameterPack(FullExpr.get()))
return ExprError();
// Top-level expressions default to 'id' when we're in a debugger.
@@ -5609,6 +5973,56 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
}
CheckCompletedExpr(FullExpr.get(), CC, IsConstexpr);
+
+ // At the end of this full expression (which could be a deeply nested
+ // lambda), if there is a potential capture within the nested lambda,
+ // have the outer capture-able lambda try and capture it.
+ // Consider the following code:
+ // void f(int, int);
+ // void f(const int&, double);
+ // void foo() {
+ // const int x = 10, y = 20;
+ // auto L = [=](auto a) {
+ // auto M = [=](auto b) {
+ // f(x, b); <-- requires x to be captured by L and M
+ // f(y, a); <-- requires y to be captured by L, but not all Ms
+ // };
+ // };
+ // }
+
+ // FIXME: Also consider what happens for something like this that involves
+ // the gnu-extension statement-expressions or even lambda-init-captures:
+ // void f() {
+ // const int n = 0;
+ // auto L = [&](auto a) {
+ // +n + ({ 0; a; });
+ // };
+ // }
+ //
+ // Here, we see +n, and then the full-expression 0; ends, so we don't
+ // capture n (and instead remove it from our list of potential captures),
+ // and then the full-expression +n + ({ 0; }); ends, but it's too late
+ // for us to see that we need to capture n after all.
+
+ LambdaScopeInfo *const CurrentLSI = getCurLambda();
+ // FIXME: PR 17877 showed that getCurLambda() can return a valid pointer
+ // even if CurContext is not a lambda call operator. Refer to that Bug Report
+ // for an example of the code that might cause this asynchrony.
+ // By ensuring we are in the context of a lambda's call operator
+ // we can fix the bug (we only need to check whether we need to capture
+ // if we are within a lambda's body); but per the comments in that
+ // PR, a proper fix would entail :
+ // "Alternative suggestion:
+ // - Add to Sema an integer holding the smallest (outermost) scope
+ // index that we are *lexically* within, and save/restore/set to
+ // FunctionScopes.size() in InstantiatingTemplate's
+ // constructor/destructor.
+ // - Teach the handful of places that iterate over FunctionScopes to
+ // stop at the outermost enclosing lexical scope."
+ const bool IsInLambdaDeclContext = isLambdaCallOperator(CurContext);
+ if (IsInLambdaDeclContext && CurrentLSI &&
+ CurrentLSI->hasPotentialCaptures() && !FullExpr.isInvalid())
+ CheckLambdaCaptures(FE, CurrentLSI, *this);
return MaybeCreateExprWithCleanups(FullExpr);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
index 545ac2746d6d..f6accb15bf98 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
@@ -538,13 +539,42 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
namespace {
// Callback to only accept typo corrections that are either a ValueDecl or a
-// FunctionTemplateDecl.
+// FunctionTemplateDecl and are declared in the current record or, for a C++
+// classes, one of its base classes.
class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
public:
+ explicit RecordMemberExprValidatorCCC(const RecordType *RTy)
+ : Record(RTy->getDecl()) {}
+
virtual bool ValidateCandidate(const TypoCorrection &candidate) {
NamedDecl *ND = candidate.getCorrectionDecl();
- return ND && (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND));
+ // Don't accept candidates that cannot be member functions, constants,
+ // variables, or templates.
+ if (!ND || !(isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)))
+ return false;
+
+ // Accept candidates that occur in the current record.
+ if (Record->containsDecl(ND))
+ return true;
+
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record)) {
+ // Accept candidates that occur in any of the current class' base classes.
+ for (CXXRecordDecl::base_class_const_iterator BS = RD->bases_begin(),
+ BSEnd = RD->bases_end();
+ BS != BSEnd; ++BS) {
+ if (const RecordType *BSTy = dyn_cast_or_null<RecordType>(
+ BS->getType().getTypePtrOrNull())) {
+ if (BSTy->getDecl()->containsDecl(ND))
+ return true;
+ }
+ }
+ }
+
+ return false;
}
+
+ private:
+ const RecordDecl *const Record;
};
}
@@ -600,24 +630,31 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
// We didn't find anything with the given name, so try to correct
// for typos.
DeclarationName Name = R.getLookupName();
- RecordMemberExprValidatorCCC Validator;
+ RecordMemberExprValidatorCCC Validator(RTy);
TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(),
R.getLookupKind(), NULL,
&SS, Validator, DC);
R.clear();
- if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
- std::string CorrectedStr(
- Corrected.getAsString(SemaRef.getLangOpts()));
- std::string CorrectedQuotedStr(
- Corrected.getQuoted(SemaRef.getLangOpts()));
+ if (Corrected.isResolved() && !Corrected.isKeyword()) {
R.setLookupName(Corrected.getCorrection());
- R.addDecl(ND);
- SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest)
- << Name << DC << CorrectedQuotedStr << SS.getRange()
- << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
- CorrectedStr);
- SemaRef.Diag(ND->getLocation(), diag::note_previous_decl)
- << ND->getDeclName();
+ for (TypoCorrection::decl_iterator DI = Corrected.begin(),
+ DIEnd = Corrected.end();
+ DI != DIEnd; ++DI) {
+ R.addDecl(*DI);
+ }
+ R.resolveKind();
+
+ // If we're typo-correcting to an overloaded name, we don't yet have enough
+ // information to do overload resolution, so we don't know which previous
+ // declaration to point to.
+ if (Corrected.isOverloaded())
+ Corrected.setCorrectionDecl(0);
+ bool DroppedSpecifier =
+ Corrected.WillReplaceSpecifier() &&
+ Name.getAsString() == Corrected.getAsString(SemaRef.getLangOpts());
+ SemaRef.diagnoseTypo(Corrected,
+ SemaRef.PDiag(diag::err_no_member_suggest)
+ << Name << DC << DroppedSpecifier << SS.getRange());
}
return false;
@@ -687,6 +724,7 @@ ExprResult
Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
SourceLocation loc,
IndirectFieldDecl *indirectField,
+ DeclAccessPair foundDecl,
Expr *baseObjectExpr,
SourceLocation opLoc) {
// First, build the expression that refers to the base object.
@@ -764,15 +802,15 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
if (!baseVariable) {
FieldDecl *field = cast<FieldDecl>(*FI);
- // FIXME: use the real found-decl info!
- DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess());
-
// Make a nameInfo that properly uses the anonymous name.
DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer,
EmptySS, field, foundDecl,
memberNameInfo).take();
+ if (!result)
+ return ExprError();
+
baseObjectIsPointer = false;
// FIXME: check qualified member access
@@ -783,14 +821,15 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
while (FI != FEnd) {
FieldDecl *field = cast<FieldDecl>(*FI++);
-
+
// FIXME: these are somewhat meaningless
DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
- DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess());
-
+ DeclAccessPair fakeFoundDecl =
+ DeclAccessPair::make(field, field->getAccess());
+
result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false,
- (FI == FEnd? SS : EmptySS), field,
- foundDecl, memberNameInfo).take();
+ (FI == FEnd? SS : EmptySS), field,
+ fakeFoundDecl, memberNameInfo).take();
}
return Owned(result);
@@ -845,7 +884,54 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
BaseType = BaseType->castAs<PointerType>()->getPointeeType();
}
R.setBaseObjectType(BaseType);
-
+
+ LambdaScopeInfo *const CurLSI = getCurLambda();
+ // If this is an implicit member reference and the overloaded
+ // name refers to both static and non-static member functions
+ // (i.e. BaseExpr is null) and if we are currently processing a lambda,
+ // check if we should/can capture 'this'...
+ // Keep this example in mind:
+ // struct X {
+ // void f(int) { }
+ // static void f(double) { }
+ //
+ // int g() {
+ // auto L = [=](auto a) {
+ // return [](int i) {
+ // return [=](auto b) {
+ // f(b);
+ // //f(decltype(a){});
+ // };
+ // };
+ // };
+ // auto M = L(0.0);
+ // auto N = M(3);
+ // N(5.32); // OK, must not error.
+ // return 0;
+ // }
+ // };
+ //
+ if (!BaseExpr && CurLSI) {
+ SourceLocation Loc = R.getNameLoc();
+ if (SS.getRange().isValid())
+ Loc = SS.getRange().getBegin();
+ DeclContext *EnclosingFunctionCtx = CurContext->getParent()->getParent();
+ // If the enclosing function is not dependent, then this lambda is
+ // capture ready, so if we can capture this, do so.
+ if (!EnclosingFunctionCtx->isDependentContext()) {
+ // If the current lambda and all enclosing lambdas can capture 'this' -
+ // then go ahead and capture 'this' (since our unresolved overload set
+ // contains both static and non-static member functions).
+ if (!CheckCXXThisCapture(Loc, /*Explcit*/false, /*Diagnose*/false))
+ CheckCXXThisCapture(Loc);
+ } else if (CurContext->isDependentContext()) {
+ // ... since this is an implicit member reference, that might potentially
+ // involve a 'this' capture, mark 'this' for potential capture in
+ // enclosing lambdas.
+ if (CurLSI->ImpCaptureStyle != CurLSI->ImpCap_None)
+ CurLSI->addPotentialThisCapture(Loc);
+ }
+ }
const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();
DeclarationName MemberName = MemberNameInfo.getName();
SourceLocation MemberLoc = MemberNameInfo.getLoc();
@@ -974,7 +1060,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
// We may have found a field within an anonymous union or struct
// (C++ [class.union]).
return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD,
- BaseExpr, OpLoc);
+ FoundDecl, BaseExpr,
+ OpLoc);
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS,
@@ -1117,10 +1204,13 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
// foo->bar
// This is actually well-formed in C++ if MyRecord has an
// overloaded operator->, but that should have been dealt with
- // by now.
- Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
- << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
- << FixItHint::CreateReplacement(OpLoc, ".");
+ // by now--or a diagnostic message already issued if a problem
+ // was encountered while looking for the overloaded operator->.
+ if (!getLangOpts().CPlusPlus) {
+ Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+ << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
+ << FixItHint::CreateReplacement(OpLoc, ".");
+ }
IsArrow = false;
} else if (BaseType->isFunctionType()) {
goto fail;
@@ -1190,14 +1280,10 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
LookupMemberName, NULL, NULL,
Validator, IDecl)) {
IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();
- Diag(R.getNameLoc(),
- diag::err_typecheck_member_reference_ivar_suggest)
- << IDecl->getDeclName() << MemberName << IV->getDeclName()
- << FixItHint::CreateReplacement(R.getNameLoc(),
- IV->getNameAsString());
- Diag(IV->getLocation(), diag::note_previous_decl)
- << IV->getDeclName();
-
+ diagnoseTypo(Corrected,
+ PDiag(diag::err_typecheck_member_reference_ivar_suggest)
+ << IDecl->getDeclName() << MemberName);
+
// Figure out the class that declares the ivar.
assert(!ClassDeclared);
Decl *D = cast<Decl>(IV->getDeclContext());
@@ -1297,7 +1383,7 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
MemberLoc);
if (Level != DiagnosticsEngine::Ignored)
- getCurFunction()->recordUseOfWeak(Result);
+ recordUseOfEvaluatedWeak(Result);
}
}
@@ -1348,8 +1434,9 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
if (DiagnoseUseOfDecl(OMD, MemberLoc))
return ExprError();
Selector SetterSel =
- SelectorTable::constructSetterName(PP.getIdentifierTable(),
- PP.getSelectorTable(), Member);
+ SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
+ PP.getSelectorTable(),
+ Member);
ObjCMethodDecl *SMD = 0;
if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0,
SetterSel, Context))
@@ -1396,8 +1483,9 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
// If we found a getter then this may be a valid dot-reference, we
// will look for the matching setter, in case it is needed.
Selector SetterSel =
- SelectorTable::constructSetterName(PP.getIdentifierTable(),
- PP.getSelectorTable(), Member);
+ SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
+ PP.getSelectorTable(),
+ Member);
ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
if (!Setter) {
// If this reference is in an @implementation, also check for 'private'
@@ -1670,7 +1758,8 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
// (C++ [class.union]).
// FIXME: template-ids inside anonymous structs?
if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>())
- return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD);
+ return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD,
+ R.begin().getPair());
// If this is known to be an instance access, go ahead and build an
// implicit 'this' expression now.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
index cf77896cb8c3..cc8eacee6103 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
@@ -266,7 +266,7 @@ ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) {
break;
case CharacterLiteral::Wide:
- NumberType = Context.getWCharType();
+ NumberType = Context.getWideCharType();
break;
case CharacterLiteral::UTF16:
@@ -324,7 +324,8 @@ ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc,
/// \brief Check that the given expression is a valid element of an Objective-C
/// collection literal.
static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
- QualType T) {
+ QualType T,
+ bool ArrayLiteral = false) {
// If the expression is type-dependent, there's nothing for us to do.
if (Element->isTypeDependent())
return Element;
@@ -401,14 +402,34 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
Recovered = true;
}
}
-
+
if (!Recovered) {
S.Diag(Element->getLocStart(), diag::err_invalid_collection_element)
<< Element->getType();
return ExprError();
}
}
-
+ if (ArrayLiteral)
+ if (ObjCStringLiteral *getString =
+ dyn_cast<ObjCStringLiteral>(OrigElement)) {
+ if (StringLiteral *SL = getString->getString()) {
+ unsigned numConcat = SL->getNumConcatenated();
+ if (numConcat > 1) {
+ // Only warn if the concatenated string doesn't come from a macro.
+ bool hasMacro = false;
+ for (unsigned i = 0; i < numConcat ; ++i)
+ if (SL->getStrTokenLoc(i).isMacroID()) {
+ hasMacro = true;
+ break;
+ }
+ if (!hasMacro)
+ S.Diag(Element->getLocStart(),
+ diag::warn_concatenated_nsarray_literal)
+ << Element->getType();
+ }
+ }
+ }
+
// Make sure that the element has the type that the container factory
// function expects.
return S.PerformCopyInitialization(
@@ -521,7 +542,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
break;
case CharacterLiteral::Wide:
- ValueType = Context.getWCharType();
+ ValueType = Context.getWideCharType();
break;
case CharacterLiteral::UTF16:
@@ -581,7 +602,7 @@ ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
Expr *IndexExpr,
ObjCMethodDecl *getterMethod,
ObjCMethodDecl *setterMethod) {
- assert(!LangOpts.ObjCRuntime.isSubscriptPointerArithmetic());
+ assert(!LangOpts.isSubscriptPointerArithmetic());
// We can't get dependent types here; our callers should have
// filtered them out.
@@ -710,7 +731,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
ExprResult Converted = CheckObjCCollectionLiteralElement(*this,
ElementsBuffer[I],
- RequiredType);
+ RequiredType, true);
if (Converted.isInvalid())
return ExprError();
@@ -902,14 +923,10 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
QualType Ty
= Context.getObjCObjectPointerType(
- Context.getObjCInterfaceType(NSDictionaryDecl));
- return MaybeBindToTemporary(
- ObjCDictionaryLiteral::Create(Context,
- llvm::makeArrayRef(Elements,
- NumElements),
- HasPackExpansions,
- Ty,
- DictionaryWithObjectsMethod, SR));
+ Context.getObjCInterfaceType(NSDictionaryDecl));
+ return MaybeBindToTemporary(ObjCDictionaryLiteral::Create(
+ Context, makeArrayRef(Elements, NumElements), HasPackExpansions, Ty,
+ DictionaryWithObjectsMethod, SR));
}
ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
@@ -968,8 +985,18 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
if (!Method)
Method = LookupFactoryMethodInGlobalPool(Sel,
SourceRange(LParenLoc, RParenLoc));
- if (!Method)
- Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
+ if (!Method) {
+ if (const ObjCMethodDecl *OM = SelectorsForTypoCorrection(Sel)) {
+ Selector MatchedSel = OM->getSelector();
+ SourceRange SelectorRange(LParenLoc.getLocWithOffset(1),
+ RParenLoc.getLocWithOffset(-1));
+ Diag(SelLoc, diag::warn_undeclared_selector_with_typo)
+ << Sel << MatchedSel
+ << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());
+
+ } else
+ Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
+ }
if (!Method ||
Method->getImplementationControl() != ObjCMethodDecl::Optional) {
@@ -1184,8 +1211,8 @@ void Sema::EmitRelatedResultTypeNote(const Expr *E) {
}
bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
- Expr **Args, unsigned NumArgs,
- Selector Sel,
+ MultiExprArg Args,
+ Selector Sel,
ArrayRef<SourceLocation> SelectorLocs,
ObjCMethodDecl *Method,
bool isClassMessage, bool isSuperMessage,
@@ -1199,7 +1226,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
if (!Method) {
// Apply default argument promotion as for (C99 6.5.2.2p6).
- for (unsigned i = 0; i != NumArgs; i++) {
+ for (unsigned i = 0, e = Args.size(); i != e; i++) {
if (Args[i]->isTypeDependent())
continue;
@@ -1221,10 +1248,31 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
else
DiagID = isClassMessage ? diag::warn_class_method_not_found
: diag::warn_inst_method_not_found;
- if (!getLangOpts().DebuggerSupport)
- Diag(SelLoc, DiagID)
- << Sel << isClassMessage << SourceRange(SelectorLocs.front(),
+ if (!getLangOpts().DebuggerSupport) {
+ const ObjCMethodDecl *OMD = SelectorsForTypoCorrection(Sel, ReceiverType);
+ if (OMD && !OMD->isInvalidDecl()) {
+ if (getLangOpts().ObjCAutoRefCount)
+ DiagID = diag::error_method_not_found_with_typo;
+ else
+ DiagID = isClassMessage ? diag::warn_class_method_not_found_with_typo
+ : diag::warn_instance_method_not_found_with_typo;
+ Selector MatchedSel = OMD->getSelector();
+ SourceRange SelectorRange(SelectorLocs.front(), SelectorLocs.back());
+ Diag(SelLoc, DiagID)
+ << Sel<< isClassMessage << MatchedSel
+ << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());
+ }
+ else
+ Diag(SelLoc, DiagID)
+ << Sel << isClassMessage << SourceRange(SelectorLocs.front(),
SelectorLocs.back());
+ // Find the class to which we are sending this message.
+ if (ReceiverType->isObjCObjectPointerType()) {
+ if (ObjCInterfaceDecl *Class =
+ ReceiverType->getAs<ObjCObjectPointerType>()->getInterfaceDecl())
+ Diag(Class->getLocation(), diag::note_receiver_class_declared);
+ }
+ }
// In debuggers, we want to use __unknown_anytype for these
// results so that clients can cast them.
@@ -1247,9 +1295,9 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
if (Method->param_size() > Sel.getNumArgs())
NumNamedArgs = Method->param_size();
// FIXME. This need be cleaned up.
- if (NumArgs < NumNamedArgs) {
+ if (Args.size() < NumNamedArgs) {
Diag(SelLoc, diag::err_typecheck_call_too_few_args)
- << 2 << NumNamedArgs << NumArgs;
+ << 2 << NumNamedArgs << static_cast<unsigned>(Args.size());
return false;
}
@@ -1302,7 +1350,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
// Promote additional arguments to variadic methods.
if (Method->isVariadic()) {
- for (unsigned i = NumNamedArgs; i < NumArgs; ++i) {
+ for (unsigned i = NumNamedArgs, e = Args.size(); i < e; ++i) {
if (Args[i]->isTypeDependent())
continue;
@@ -1313,21 +1361,21 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
}
} else {
// Check for extra arguments to non-variadic methods.
- if (NumArgs != NumNamedArgs) {
+ if (Args.size() != NumNamedArgs) {
Diag(Args[NumNamedArgs]->getLocStart(),
diag::err_typecheck_call_too_many_args)
- << 2 /*method*/ << NumNamedArgs << NumArgs
+ << 2 /*method*/ << NumNamedArgs << static_cast<unsigned>(Args.size())
<< Method->getSourceRange()
<< SourceRange(Args[NumNamedArgs]->getLocStart(),
- Args[NumArgs-1]->getLocEnd());
+ Args.back()->getLocEnd());
}
}
- DiagnoseSentinelCalls(Method, SelLoc, Args, NumArgs);
+ DiagnoseSentinelCalls(Method, SelLoc, Args);
// Do additional checkings on method.
- IsError |= CheckObjCMethodCall(Method, SelLoc,
- llvm::makeArrayRef<const Expr *>(Args, NumArgs));
+ IsError |= CheckObjCMethodCall(
+ Method, SelLoc, makeArrayRef<const Expr *>(Args.data(), Args.size()));
return IsError;
}
@@ -1534,8 +1582,8 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
// If we found a getter then this may be a valid dot-reference, we
// will look for the matching setter, in case it is needed.
Selector SetterSel =
- SelectorTable::constructSetterName(PP.getIdentifierTable(),
- PP.getSelectorTable(), Member);
+ SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
+ PP.getSelectorTable(), Member);
ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
// May be founf in property's qualified list.
@@ -1569,16 +1617,11 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
// Attempt to correct for typos in property names.
DeclFilterCCC<ObjCPropertyDecl> Validator;
if (TypoCorrection Corrected = CorrectTypo(
- DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL,
- NULL, Validator, IFace, false, OPT)) {
- ObjCPropertyDecl *Property =
- Corrected.getCorrectionDeclAs<ObjCPropertyDecl>();
+ DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL,
+ NULL, Validator, IFace, false, OPT)) {
+ diagnoseTypo(Corrected, PDiag(diag::err_property_not_found_suggest)
+ << MemberName << QualType(OPT, 0));
DeclarationName TypoResult = Corrected.getCorrection();
- Diag(MemberLoc, diag::err_property_not_found_suggest)
- << MemberName << QualType(OPT, 0) << TypoResult
- << FixItHint::CreateReplacement(MemberLoc, TypoResult.getAsString());
- Diag(Property->getLocation(), diag::note_previous_decl)
- << Property->getDeclName();
return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc,
TypoResult, MemberLoc,
SuperLoc, SuperType, Super);
@@ -1681,8 +1724,9 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
// Look for the matching setter, in case it is needed.
Selector SetterSel =
- SelectorTable::constructSetterName(PP.getIdentifierTable(),
- PP.getSelectorTable(), &propertyName);
+ SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
+ PP.getSelectorTable(),
+ &propertyName);
ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
if (!Setter) {
@@ -1809,34 +1853,28 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
}
ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl());
- if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
- Result.getLookupKind(), S, NULL,
- Validator)) {
+ if (TypoCorrection Corrected =
+ CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S,
+ NULL, Validator, NULL, false, NULL, false)) {
if (Corrected.isKeyword()) {
// If we've found the keyword "super" (the only keyword that would be
// returned by CorrectTypo), this is a send to super.
- Diag(NameLoc, diag::err_unknown_receiver_suggest)
- << Name << Corrected.getCorrection()
- << FixItHint::CreateReplacement(SourceRange(NameLoc), "super");
+ diagnoseTypo(Corrected,
+ PDiag(diag::err_unknown_receiver_suggest) << Name);
return ObjCSuperMessage;
} else if (ObjCInterfaceDecl *Class =
- Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
+ Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
// If we found a declaration, correct when it refers to an Objective-C
// class.
- Diag(NameLoc, diag::err_unknown_receiver_suggest)
- << Name << Corrected.getCorrection()
- << FixItHint::CreateReplacement(SourceRange(NameLoc),
- Class->getNameAsString());
- Diag(Class->getLocation(), diag::note_previous_decl)
- << Corrected.getCorrection();
-
+ diagnoseTypo(Corrected,
+ PDiag(diag::err_unknown_receiver_suggest) << Name);
QualType T = Context.getObjCInterfaceType(Class);
TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
ReceiverType = CreateParsedType(T, TSInfo);
return ObjCClassMessage;
}
}
-
+
// Fall back: let the parser try to parse it as an instance message.
return ObjCInstanceMessage;
}
@@ -2065,7 +2103,8 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
unsigned NumArgs = ArgsIn.size();
Expr **Args = ArgsIn.data();
- if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, SelectorLocs,
+ if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs),
+ Sel, SelectorLocs,
Method, true,
SuperLoc.isValid(), LBracLoc, RBracLoc,
ReturnType, VK))
@@ -2246,6 +2285,11 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
}
ReceiverType = Receiver->getType();
} else if (getLangOpts().CPlusPlus) {
+ // The receiver must be a complete type.
+ if (RequireCompleteType(Loc, Receiver->getType(),
+ diag::err_incomplete_receiver_type))
+ return ExprError();
+
ExprResult result = PerformContextuallyConvertToObjCPointer(Receiver);
if (result.isUsable()) {
Receiver = result.take();
@@ -2410,8 +2454,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
ExprValueKind VK = VK_RValue;
bool ClassMessage = (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType());
- if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel,
- SelectorLocs, Method,
+ if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs),
+ Sel, SelectorLocs, Method,
ClassMessage, SuperLoc.isValid(),
LBracLoc, RBracLoc, ReturnType, VK))
return ExprError();
@@ -3121,9 +3165,112 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
<< castRange << castExpr->getSourceRange();
}
+static inline ObjCBridgeAttr *getObjCBridgeAttr(const TypedefType *TD) {
+ TypedefNameDecl *TDNDecl = TD->getDecl();
+ QualType QT = TDNDecl->getUnderlyingType();
+ if (QT->isPointerType()) {
+ QT = QT->getPointeeType();
+ if (const RecordType *RT = QT->getAs<RecordType>())
+ if (RecordDecl *RD = RT->getDecl())
+ if (RD->hasAttr<ObjCBridgeAttr>())
+ return RD->getAttr<ObjCBridgeAttr>();
+ }
+ return 0;
+}
+
+static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) {
+ QualType T = castExpr->getType();
+ while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
+ TypedefNameDecl *TDNDecl = TD->getDecl();
+ if (ObjCBridgeAttr *ObjCBAttr = getObjCBridgeAttr(TD)) {
+ if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
+ NamedDecl *Target = 0;
+ // Check for an existing type with this name.
+ LookupResult R(S, DeclarationName(Parm), SourceLocation(),
+ Sema::LookupOrdinaryName);
+ if (S.LookupName(R, S.TUScope)) {
+ Target = R.getFoundDecl();
+ if (Target && isa<ObjCInterfaceDecl>(Target)) {
+ ObjCInterfaceDecl *ExprClass = cast<ObjCInterfaceDecl>(Target);
+ if (const ObjCObjectPointerType *InterfacePointerType =
+ castType->getAsObjCInterfacePointerType()) {
+ ObjCInterfaceDecl *CastClass
+ = InterfacePointerType->getObjectType()->getInterface();
+ if ((CastClass == ExprClass) || (CastClass && ExprClass->isSuperClassOf(CastClass)))
+ return true;
+ S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
+ << T << Target->getName() << castType->getPointeeType();
+ return true;
+ } else {
+ S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
+ << T << Target->getName() << castType;
+ return true;
+ }
+ }
+ }
+ S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface)
+ << castExpr->getType() << Parm->getName();
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ if (Target)
+ S.Diag(Target->getLocStart(), diag::note_declared_at);
+ }
+ return true;
+ }
+ T = TDNDecl->getUnderlyingType();
+ }
+ return false;
+}
+
+// (CFErrorRef)ns
+static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) {
+ QualType T = castType;
+ while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
+ TypedefNameDecl *TDNDecl = TD->getDecl();
+ if (ObjCBridgeAttr *ObjCBAttr = getObjCBridgeAttr(TD)) {
+ if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
+ NamedDecl *Target = 0;
+ // Check for an existing type with this name.
+ LookupResult R(S, DeclarationName(Parm), SourceLocation(),
+ Sema::LookupOrdinaryName);
+ if (S.LookupName(R, S.TUScope)) {
+ Target = R.getFoundDecl();
+ if (Target && isa<ObjCInterfaceDecl>(Target)) {
+ ObjCInterfaceDecl *CastClass = cast<ObjCInterfaceDecl>(Target);
+ if (const ObjCObjectPointerType *InterfacePointerType =
+ castExpr->getType()->getAsObjCInterfacePointerType()) {
+ ObjCInterfaceDecl *ExprClass
+ = InterfacePointerType->getObjectType()->getInterface();
+ if ((CastClass == ExprClass) || (ExprClass && CastClass->isSuperClassOf(ExprClass)))
+ return true;
+ S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
+ << castExpr->getType()->getPointeeType() << T;
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ return true;
+ } else {
+ S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
+ << castExpr->getType() << castType;
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ return true;
+ }
+ }
+ }
+ S.Diag(castExpr->getLocStart(), diag::err_objc_ns_bridged_invalid_cfobject)
+ << castExpr->getType() << castType;
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ if (Target)
+ S.Diag(Target->getLocStart(), diag::note_declared_at);
+ }
+ return true;
+ }
+ T = TDNDecl->getUnderlyingType();
+ }
+ return false;
+}
+
Sema::ARCConversionResult
Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
- Expr *&castExpr, CheckedConversionKind CCK) {
+ Expr *&castExpr, CheckedConversionKind CCK,
+ bool DiagnoseCFAudited) {
QualType castExprType = castExpr->getType();
// For the purposes of the classification, we assume reference types
@@ -3177,6 +3324,17 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr &&
CCK != CCK_ImplicitConversion)
return ACR_okay;
+
+ if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation &&
+ (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
+ if (CheckObjCBridgeNSCast(*this, castType, castExpr))
+ return ACR_okay;
+
+ if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&
+ (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
+ if (CheckObjCBridgeCFCast(*this, castType, castExpr))
+ return ACR_okay;
+
switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) {
// For invalid casts, fall through.
@@ -3204,8 +3362,14 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
CCK != CCK_ImplicitConversion)
return ACR_unbridged;
- diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
- castExpr, castExpr, exprACTC, CCK);
+ // Do not issue "bridge cast" diagnostic when implicit casting
+ // a retainable object to a CF type parameter belonging to an audited
+ // CF API function. Let caller issue a normal type mismatched diagnostic
+ // instead.
+ if (!DiagnoseCFAudited || exprACTC != ACTC_retainable ||
+ castACTC != ACTC_coreFoundation)
+ diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
+ castExpr, castExpr, exprACTC, CCK);
return ACR_okay;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp
index 2a845ba9898b..32b56bcddc63 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp
@@ -160,27 +160,33 @@ bool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr,
return false;
}
-static bool isMacroDefined(const Sema &S, StringRef Name) {
- return S.PP.getMacroInfo(&S.getASTContext().Idents.get(Name));
+static bool isMacroDefined(const Sema &S, SourceLocation Loc, StringRef Name) {
+ const IdentifierInfo *II = &S.getASTContext().Idents.get(Name);
+ if (!II->hadMacroDefinition()) return false;
+
+ MacroDirective *Macro = S.PP.getMacroDirectiveHistory(II);
+ return Macro && Macro->findDirectiveAtLoc(Loc, S.getSourceManager());
}
-static std::string getScalarZeroExpressionForType(const Type& T, const Sema& S) {
+static std::string getScalarZeroExpressionForType(
+ const Type &T, SourceLocation Loc, const Sema &S) {
assert(T.isScalarType() && "use scalar types only");
// Suggest "0" for non-enumeration scalar types, unless we can find a
// better initializer.
if (T.isEnumeralType())
return std::string();
if ((T.isObjCObjectPointerType() || T.isBlockPointerType()) &&
- isMacroDefined(S, "nil"))
+ isMacroDefined(S, Loc, "nil"))
return "nil";
if (T.isRealFloatingType())
return "0.0";
- if (T.isBooleanType() && S.LangOpts.CPlusPlus)
+ if (T.isBooleanType() &&
+ (S.LangOpts.CPlusPlus || isMacroDefined(S, Loc, "false")))
return "false";
if (T.isPointerType() || T.isMemberPointerType()) {
if (S.LangOpts.CPlusPlus11)
return "nullptr";
- if (isMacroDefined(S, "NULL"))
+ if (isMacroDefined(S, Loc, "NULL"))
return "NULL";
}
if (T.isCharType())
@@ -194,9 +200,10 @@ static std::string getScalarZeroExpressionForType(const Type& T, const Sema& S)
return "0";
}
-std::string Sema::getFixItZeroInitializerForType(QualType T) const {
+std::string
+Sema::getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const {
if (T->isScalarType()) {
- std::string s = getScalarZeroExpressionForType(*T, *this);
+ std::string s = getScalarZeroExpressionForType(*T, Loc, *this);
if (!s.empty())
s = " = " + s;
return s;
@@ -212,6 +219,7 @@ std::string Sema::getFixItZeroInitializerForType(QualType T) const {
return std::string();
}
-std::string Sema::getFixItZeroLiteralForType(QualType T) const {
- return getScalarZeroExpressionForType(*T, *this);
+std::string
+Sema::getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const {
+ return getScalarZeroExpressionForType(*T, Loc, *this);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
index a632f022f5dd..034c1b6c7184 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -32,53 +32,99 @@ using namespace clang;
// Sema Initialization Checking
//===----------------------------------------------------------------------===//
-static Expr *IsStringInit(Expr *Init, const ArrayType *AT,
- ASTContext &Context) {
+/// \brief Check whether T is compatible with a wide character type (wchar_t,
+/// char16_t or char32_t).
+static bool IsWideCharCompatible(QualType T, ASTContext &Context) {
+ if (Context.typesAreCompatible(Context.getWideCharType(), T))
+ return true;
+ if (Context.getLangOpts().CPlusPlus || Context.getLangOpts().C11) {
+ return Context.typesAreCompatible(Context.Char16Ty, T) ||
+ Context.typesAreCompatible(Context.Char32Ty, T);
+ }
+ return false;
+}
+
+enum StringInitFailureKind {
+ SIF_None,
+ SIF_NarrowStringIntoWideChar,
+ SIF_WideStringIntoChar,
+ SIF_IncompatWideStringIntoWideChar,
+ SIF_Other
+};
+
+/// \brief Check whether the array of type AT can be initialized by the Init
+/// expression by means of string initialization. Returns SIF_None if so,
+/// otherwise returns a StringInitFailureKind that describes why the
+/// initialization would not work.
+static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT,
+ ASTContext &Context) {
if (!isa<ConstantArrayType>(AT) && !isa<IncompleteArrayType>(AT))
- return 0;
+ return SIF_Other;
// See if this is a string literal or @encode.
Init = Init->IgnoreParens();
// Handle @encode, which is a narrow string.
if (isa<ObjCEncodeExpr>(Init) && AT->getElementType()->isCharType())
- return Init;
+ return SIF_None;
// Otherwise we can only handle string literals.
StringLiteral *SL = dyn_cast<StringLiteral>(Init);
- if (SL == 0) return 0;
+ if (SL == 0)
+ return SIF_Other;
- QualType ElemTy = Context.getCanonicalType(AT->getElementType());
+ const QualType ElemTy =
+ Context.getCanonicalType(AT->getElementType()).getUnqualifiedType();
switch (SL->getKind()) {
case StringLiteral::Ascii:
case StringLiteral::UTF8:
// char array can be initialized with a narrow string.
// Only allow char x[] = "foo"; not char x[] = L"foo";
- return ElemTy->isCharType() ? Init : 0;
+ if (ElemTy->isCharType())
+ return SIF_None;
+ if (IsWideCharCompatible(ElemTy, Context))
+ return SIF_NarrowStringIntoWideChar;
+ return SIF_Other;
+ // C99 6.7.8p15 (with correction from DR343), or C11 6.7.9p15:
+ // "An array with element type compatible with a qualified or unqualified
+ // version of wchar_t, char16_t, or char32_t may be initialized by a wide
+ // string literal with the corresponding encoding prefix (L, u, or U,
+ // respectively), optionally enclosed in braces.
case StringLiteral::UTF16:
- return ElemTy->isChar16Type() ? Init : 0;
+ if (Context.typesAreCompatible(Context.Char16Ty, ElemTy))
+ return SIF_None;
+ if (ElemTy->isCharType())
+ return SIF_WideStringIntoChar;
+ if (IsWideCharCompatible(ElemTy, Context))
+ return SIF_IncompatWideStringIntoWideChar;
+ return SIF_Other;
case StringLiteral::UTF32:
- return ElemTy->isChar32Type() ? Init : 0;
+ if (Context.typesAreCompatible(Context.Char32Ty, ElemTy))
+ return SIF_None;
+ if (ElemTy->isCharType())
+ return SIF_WideStringIntoChar;
+ if (IsWideCharCompatible(ElemTy, Context))
+ return SIF_IncompatWideStringIntoWideChar;
+ return SIF_Other;
case StringLiteral::Wide:
- // wchar_t array can be initialized with a wide string: C99 6.7.8p15 (with
- // correction from DR343): "An array with element type compatible with a
- // qualified or unqualified version of wchar_t may be initialized by a wide
- // string literal, optionally enclosed in braces."
- if (Context.typesAreCompatible(Context.getWCharType(),
- ElemTy.getUnqualifiedType()))
- return Init;
-
- return 0;
+ if (Context.typesAreCompatible(Context.getWideCharType(), ElemTy))
+ return SIF_None;
+ if (ElemTy->isCharType())
+ return SIF_WideStringIntoChar;
+ if (IsWideCharCompatible(ElemTy, Context))
+ return SIF_IncompatWideStringIntoWideChar;
+ return SIF_Other;
}
llvm_unreachable("missed a StringLiteral kind?");
}
-static Expr *IsStringInit(Expr *init, QualType declType, ASTContext &Context) {
+static StringInitFailureKind IsStringInit(Expr *init, QualType declType,
+ ASTContext &Context) {
const ArrayType *arrayType = Context.getAsArrayType(declType);
- if (!arrayType) return 0;
-
+ if (!arrayType)
+ return SIF_Other;
return IsStringInit(init, arrayType, Context);
}
@@ -190,7 +236,6 @@ class InitListChecker {
Sema &SemaRef;
bool hadError;
bool VerifyOnly; // no diagnostics, no structure building
- bool AllowBraceElision;
llvm::DenseMap<InitListExpr *, InitListExpr *> SyntacticToSemantic;
InitListExpr *FullyStructuredList;
@@ -200,8 +245,7 @@ class InitListChecker {
unsigned &StructuredIndex);
void CheckExplicitInitList(const InitializedEntity &Entity,
InitListExpr *IList, QualType &T,
- unsigned &Index, InitListExpr *StructuredList,
- unsigned &StructuredIndex,
+ InitListExpr *StructuredList,
bool TopLevelObject = false);
void CheckListElementTypes(const InitializedEntity &Entity,
InitListExpr *IList, QualType &DeclType,
@@ -281,8 +325,7 @@ class InitListChecker {
public:
InitListChecker(Sema &S, const InitializedEntity &Entity,
- InitListExpr *IL, QualType &T, bool VerifyOnly,
- bool AllowBraceElision);
+ InitListExpr *IL, QualType &T, bool VerifyOnly);
bool HadError() { return hadError; }
// @brief Retrieves the fully-structured initializer list used for
@@ -513,16 +556,13 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
InitListExpr *IL, QualType &T,
- bool VerifyOnly, bool AllowBraceElision)
- : SemaRef(S), VerifyOnly(VerifyOnly), AllowBraceElision(AllowBraceElision) {
+ bool VerifyOnly)
+ : SemaRef(S), VerifyOnly(VerifyOnly) {
hadError = false;
- unsigned newIndex = 0;
- unsigned newStructuredIndex = 0;
- FullyStructuredList
- = getStructuredSubobjectInit(IL, newIndex, T, 0, 0, IL->getSourceRange());
- CheckExplicitInitList(Entity, IL, T, newIndex,
- FullyStructuredList, newStructuredIndex,
+ FullyStructuredList =
+ getStructuredSubobjectInit(IL, 0, T, 0, 0, IL->getSourceRange());
+ CheckExplicitInitList(Entity, IL, T, FullyStructuredList,
/*TopLevelObject=*/true);
if (!hadError && !VerifyOnly) {
@@ -559,6 +599,12 @@ int InitListChecker::numStructUnionElements(QualType DeclType) {
return InitializableMembers - structDecl->hasFlexibleArrayMember();
}
+/// Check whether the range of the initializer \p ParentIList from element
+/// \p Index onwards can be used to initialize an object of type \p T. Update
+/// \p Index to indicate how many elements of the list were consumed.
+///
+/// This also fills in \p StructuredList, from element \p StructuredIndex
+/// onwards, with the fully-braced, desugared form of the initialization.
void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
InitListExpr *ParentIList,
QualType T, unsigned &Index,
@@ -599,10 +645,7 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
StructuredSubobjectInitList,
StructuredSubobjectInitIndex);
- if (VerifyOnly) {
- if (!AllowBraceElision && (T->isArrayType() || T->isRecordType()))
- hadError = true;
- } else {
+ if (!VerifyOnly) {
StructuredSubobjectInitList->setType(T);
unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
@@ -617,8 +660,7 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
// Complain about missing braces.
if (T->isArrayType() || T->isRecordType()) {
SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
- AllowBraceElision ? diag::warn_missing_braces :
- diag::err_missing_braces)
+ diag::warn_missing_braces)
<< StructuredSubobjectInitList->getSourceRange()
<< FixItHint::CreateInsertion(
StructuredSubobjectInitList->getLocStart(), "{")
@@ -626,23 +668,26 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
SemaRef.PP.getLocForEndOfToken(
StructuredSubobjectInitList->getLocEnd()),
"}");
- if (!AllowBraceElision)
- hadError = true;
}
}
}
+/// Check whether the initializer \p IList (that was written with explicit
+/// braces) can be used to initialize an object of type \p T.
+///
+/// This also fills in \p StructuredList with the fully-braced, desugared
+/// form of the initialization.
void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
InitListExpr *IList, QualType &T,
- unsigned &Index,
InitListExpr *StructuredList,
- unsigned &StructuredIndex,
bool TopLevelObject) {
assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
if (!VerifyOnly) {
SyntacticToSemantic[IList] = StructuredList;
StructuredList->setSyntacticForm(IList);
}
+
+ unsigned Index = 0, StructuredIndex = 0;
CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true,
Index, StructuredList, StructuredIndex, TopLevelObject);
if (!VerifyOnly) {
@@ -667,7 +712,8 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
}
if (StructuredIndex == 1 &&
- IsStringInit(StructuredList->getInit(0), T, SemaRef.Context)) {
+ IsStringInit(StructuredList->getInit(0), T, SemaRef.Context) ==
+ SIF_None) {
unsigned DK = diag::warn_excess_initializers_in_char_array_initializer;
if (SemaRef.getLangOpts().CPlusPlus) {
DK = diag::err_excess_initializers_in_char_array_initializer;
@@ -781,14 +827,12 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
if (!ElemType->isRecordType() || ElemType->isAggregateType()) {
- unsigned newIndex = 0;
- unsigned newStructuredIndex = 0;
- InitListExpr *newStructuredList
+ InitListExpr *InnerStructuredList
= getStructuredSubobjectInit(IList, Index, ElemType,
StructuredList, StructuredIndex,
SubInitList->getSourceRange());
- CheckExplicitInitList(Entity, SubInitList, ElemType, newIndex,
- newStructuredList, newStructuredIndex);
+ CheckExplicitInitList(Entity, SubInitList, ElemType,
+ InnerStructuredList);
++StructuredIndex;
++Index;
return;
@@ -811,10 +855,10 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// array member. There's nothing we can do with the completed
// type here, though.
- if (Expr *Str = IsStringInit(expr, arrayType, SemaRef.Context)) {
+ if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) {
if (!VerifyOnly) {
- CheckStringInit(Str, ElemType, arrayType, SemaRef);
- UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+ CheckStringInit(expr, ElemType, arrayType, SemaRef);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
}
++Index;
return;
@@ -862,7 +906,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes,
!VerifyOnly)
- == Sema::Compatible) {
+ != Sema::Incompatible) {
if (ExprRes.isInvalid())
hadError = true;
else {
@@ -1194,16 +1238,17 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
// Check for the special-case of initializing an array with a string.
if (Index < IList->getNumInits()) {
- if (Expr *Str = IsStringInit(IList->getInit(Index), arrayType,
- SemaRef.Context)) {
+ if (IsStringInit(IList->getInit(Index), arrayType, SemaRef.Context) ==
+ SIF_None) {
// We place the string literal directly into the resulting
// initializer list. This is the only place where the structure
// of the structured initializer list doesn't match exactly,
// because doing so would involve allocating one character
// constant for each string.
if (!VerifyOnly) {
- CheckStringInit(Str, DeclType, arrayType, SemaRef);
- UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+ CheckStringInit(IList->getInit(Index), DeclType, arrayType, SemaRef);
+ UpdateStructuredListElement(StructuredList, StructuredIndex,
+ IList->getInit(Index));
StructuredList->resizeInits(SemaRef.Context, StructuredIndex);
}
++Index;
@@ -1773,22 +1818,15 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Name lookup didn't find anything. Determine whether this
// was a typo for another field name.
FieldInitializerValidatorCCC Validator(RT->getDecl());
- TypoCorrection Corrected = SemaRef.CorrectTypo(
- DeclarationNameInfo(FieldName, D->getFieldLoc()),
- Sema::LookupMemberName, /*Scope=*/0, /*SS=*/0, Validator,
- RT->getDecl());
- if (Corrected) {
- std::string CorrectedStr(
- Corrected.getAsString(SemaRef.getLangOpts()));
- std::string CorrectedQuotedStr(
- Corrected.getQuoted(SemaRef.getLangOpts()));
+ if (TypoCorrection Corrected = SemaRef.CorrectTypo(
+ DeclarationNameInfo(FieldName, D->getFieldLoc()),
+ Sema::LookupMemberName, /*Scope=*/ 0, /*SS=*/ 0, Validator,
+ RT->getDecl())) {
+ SemaRef.diagnoseTypo(
+ Corrected,
+ SemaRef.PDiag(diag::err_field_designator_unknown_suggest)
+ << FieldName << CurrentObjectType);
ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>();
- SemaRef.Diag(D->getFieldLoc(),
- diag::err_field_designator_unknown_suggest)
- << FieldName << CurrentObjectType << CorrectedQuotedStr
- << FixItHint::CreateReplacement(D->getFieldLoc(), CorrectedStr);
- SemaRef.Diag(ReplacementField->getLocation(),
- diag::note_previous_decl) << CorrectedQuotedStr;
hadError = true;
} else {
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
@@ -1830,8 +1868,29 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// the initializer list.
if (RT->getDecl()->isUnion()) {
FieldIndex = 0;
- if (!VerifyOnly)
+ if (!VerifyOnly) {
+ FieldDecl *CurrentField = StructuredList->getInitializedFieldInUnion();
+ if (CurrentField && CurrentField != *Field) {
+ assert(StructuredList->getNumInits() == 1
+ && "A union should never have more than one initializer!");
+
+ // we're about to throw away an initializer, emit warning
+ SemaRef.Diag(D->getFieldLoc(),
+ diag::warn_initializer_overrides)
+ << D->getSourceRange();
+ Expr *ExistingInit = StructuredList->getInit(0);
+ SemaRef.Diag(ExistingInit->getLocStart(),
+ diag::note_previous_initializer)
+ << /*FIXME:has side effects=*/0
+ << ExistingInit->getSourceRange();
+
+ // remove existing initializer
+ StructuredList->resizeInits(SemaRef.Context, 0);
+ StructuredList->setInitializedFieldInUnion(0);
+ }
+
StructuredList->setInitializedFieldInUnion(*Field);
+ }
}
// Make sure we can use this declaration.
@@ -2039,6 +2098,64 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
DesignatedEndIndex.setIsUnsigned(true);
}
+ if (!VerifyOnly && StructuredList->isStringLiteralInit()) {
+ // We're modifying a string literal init; we have to decompose the string
+ // so we can modify the individual characters.
+ ASTContext &Context = SemaRef.Context;
+ Expr *SubExpr = StructuredList->getInit(0)->IgnoreParens();
+
+ // Compute the character type
+ QualType CharTy = AT->getElementType();
+
+ // Compute the type of the integer literals.
+ QualType PromotedCharTy = CharTy;
+ if (CharTy->isPromotableIntegerType())
+ PromotedCharTy = Context.getPromotedIntegerType(CharTy);
+ unsigned PromotedCharTyWidth = Context.getTypeSize(PromotedCharTy);
+
+ if (StringLiteral *SL = dyn_cast<StringLiteral>(SubExpr)) {
+ // Get the length of the string.
+ uint64_t StrLen = SL->getLength();
+ if (cast<ConstantArrayType>(AT)->getSize().ult(StrLen))
+ StrLen = cast<ConstantArrayType>(AT)->getSize().getZExtValue();
+ StructuredList->resizeInits(Context, StrLen);
+
+ // Build a literal for each character in the string, and put them into
+ // the init list.
+ for (unsigned i = 0, e = StrLen; i != e; ++i) {
+ llvm::APInt CodeUnit(PromotedCharTyWidth, SL->getCodeUnit(i));
+ Expr *Init = new (Context) IntegerLiteral(
+ Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc());
+ if (CharTy != PromotedCharTy)
+ Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
+ Init, 0, VK_RValue);
+ StructuredList->updateInit(Context, i, Init);
+ }
+ } else {
+ ObjCEncodeExpr *E = cast<ObjCEncodeExpr>(SubExpr);
+ std::string Str;
+ Context.getObjCEncodingForType(E->getEncodedType(), Str);
+
+ // Get the length of the string.
+ uint64_t StrLen = Str.size();
+ if (cast<ConstantArrayType>(AT)->getSize().ult(StrLen))
+ StrLen = cast<ConstantArrayType>(AT)->getSize().getZExtValue();
+ StructuredList->resizeInits(Context, StrLen);
+
+ // Build a literal for each character in the string, and put them into
+ // the init list.
+ for (unsigned i = 0, e = StrLen; i != e; ++i) {
+ llvm::APInt CodeUnit(PromotedCharTyWidth, Str[i]);
+ Expr *Init = new (Context) IntegerLiteral(
+ Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc());
+ if (CharTy != PromotedCharTy)
+ Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
+ Init, 0, VK_RValue);
+ StructuredList->updateInit(Context, i, Init);
+ }
+ }
+ }
+
// Make sure that our non-designated initializer list has space
// for a subobject corresponding to this array element.
if (!VerifyOnly &&
@@ -2361,12 +2478,13 @@ InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
}
}
-InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
- CXXBaseSpecifier *Base,
- bool IsInheritedVirtualBase)
-{
+InitializedEntity
+InitializedEntity::InitializeBase(ASTContext &Context,
+ const CXXBaseSpecifier *Base,
+ bool IsInheritedVirtualBase) {
InitializedEntity Result;
Result.Kind = EK_Base;
+ Result.Parent = 0;
Result.Base = reinterpret_cast<uintptr_t>(Base);
if (IsInheritedVirtualBase)
Result.Base |= 0x01;
@@ -2377,7 +2495,8 @@ InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
DeclarationName InitializedEntity::getName() const {
switch (getKind()) {
- case EK_Parameter: {
+ case EK_Parameter:
+ case EK_Parameter_CF_Audited: {
ParmVarDecl *D = reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);
return (D ? D->getDeclName() : DeclarationName());
}
@@ -2387,7 +2506,7 @@ DeclarationName InitializedEntity::getName() const {
return VariableOrMember->getDeclName();
case EK_LambdaCapture:
- return Capture.Var->getDeclName();
+ return DeclarationName(Capture.VarID);
case EK_Result:
case EK_Exception:
@@ -2400,6 +2519,7 @@ DeclarationName InitializedEntity::getName() const {
case EK_ComplexElement:
case EK_BlockElement:
case EK_CompoundLiteralInit:
+ case EK_RelatedResult:
return DeclarationName();
}
@@ -2413,6 +2533,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const {
return VariableOrMember;
case EK_Parameter:
+ case EK_Parameter_CF_Audited:
return reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);
case EK_Result:
@@ -2427,6 +2548,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const {
case EK_BlockElement:
case EK_LambdaCapture:
case EK_CompoundLiteralInit:
+ case EK_RelatedResult:
return 0;
}
@@ -2441,6 +2563,7 @@ bool InitializedEntity::allowsNRVO() const {
case EK_Variable:
case EK_Parameter:
+ case EK_Parameter_CF_Audited:
case EK_Member:
case EK_New:
case EK_Temporary:
@@ -2452,12 +2575,57 @@ bool InitializedEntity::allowsNRVO() const {
case EK_ComplexElement:
case EK_BlockElement:
case EK_LambdaCapture:
+ case EK_RelatedResult:
break;
}
return false;
}
+unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
+ assert(getParent() != this);
+ unsigned Depth = getParent() ? getParent()->dumpImpl(OS) : 0;
+ for (unsigned I = 0; I != Depth; ++I)
+ OS << "`-";
+
+ switch (getKind()) {
+ case EK_Variable: OS << "Variable"; break;
+ case EK_Parameter: OS << "Parameter"; break;
+ case EK_Parameter_CF_Audited: OS << "CF audited function Parameter";
+ break;
+ case EK_Result: OS << "Result"; break;
+ case EK_Exception: OS << "Exception"; break;
+ case EK_Member: OS << "Member"; break;
+ case EK_New: OS << "New"; break;
+ case EK_Temporary: OS << "Temporary"; break;
+ case EK_CompoundLiteralInit: OS << "CompoundLiteral";break;
+ case EK_RelatedResult: OS << "RelatedResult"; break;
+ case EK_Base: OS << "Base"; break;
+ case EK_Delegating: OS << "Delegating"; break;
+ case EK_ArrayElement: OS << "ArrayElement " << Index; break;
+ case EK_VectorElement: OS << "VectorElement " << Index; break;
+ case EK_ComplexElement: OS << "ComplexElement " << Index; break;
+ case EK_BlockElement: OS << "Block"; break;
+ case EK_LambdaCapture:
+ OS << "LambdaCapture ";
+ OS << DeclarationName(Capture.VarID);
+ break;
+ }
+
+ if (Decl *D = getDecl()) {
+ OS << " ";
+ cast<NamedDecl>(D)->printQualifiedName(OS);
+ }
+
+ OS << " '" << getType().getAsString() << "'\n";
+
+ return Depth + 1;
+}
+
+void InitializedEntity::dump() const {
+ dumpImpl(llvm::errs());
+}
+
//===----------------------------------------------------------------------===//
// Initialization sequence
//===----------------------------------------------------------------------===//
@@ -2496,6 +2664,7 @@ void InitializationSequence::Step::Destroy() {
break;
case SK_ConversionSequence:
+ case SK_ConversionSequenceNoNarrowing:
delete ICS;
}
}
@@ -2512,6 +2681,10 @@ bool InitializationSequence::isAmbiguous() const {
case FK_TooManyInitsForReference:
case FK_ArrayNeedsInitList:
case FK_ArrayNeedsInitListOrStringLiteral:
+ case FK_ArrayNeedsInitListOrWideStringLiteral:
+ case FK_NarrowStringIntoWideCharArray:
+ case FK_WideStringIntoCharArray:
+ case FK_IncompatWideStringIntoWideChar:
case FK_AddressOfOverloadFailed: // FIXME: Could do better
case FK_NonConstLValueReferenceBindingToTemporary:
case FK_NonConstLValueReferenceBindingToUnrelated:
@@ -2530,7 +2703,6 @@ bool InitializationSequence::isAmbiguous() const {
case FK_ListInitializationFailed:
case FK_VariableLengthArrayHasInitializer:
case FK_PlaceholderType:
- case FK_InitListElementCopyFailure:
case FK_ExplicitConstructor:
return false;
@@ -2632,10 +2804,11 @@ void InitializationSequence::AddLValueToRValueStep(QualType Ty) {
}
void InitializationSequence::AddConversionSequenceStep(
- const ImplicitConversionSequence &ICS,
- QualType T) {
+ const ImplicitConversionSequence &ICS, QualType T,
+ bool TopLevelOfInitList) {
Step S;
- S.Kind = SK_ConversionSequence;
+ S.Kind = TopLevelOfInitList ? SK_ConversionSequenceNoNarrowing
+ : SK_ConversionSequence;
S.Type = T;
S.ICS = new ImplicitConversionSequence(ICS);
Steps.push_back(S);
@@ -2777,7 +2950,7 @@ static void MaybeProduceObjCObject(Sema &S,
/// When initializing a parameter, produce the value if it's marked
/// __attribute__((ns_consumed)).
- if (Entity.getKind() == InitializedEntity::EK_Parameter) {
+ if (Entity.isParameterKind()) {
if (!Entity.isParameterConsumed())
return;
@@ -2797,6 +2970,12 @@ static void MaybeProduceObjCObject(Sema &S,
}
}
+static void TryListInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ InitListExpr *InitList,
+ InitializationSequence &Sequence);
+
/// \brief When initializing from init list via constructor, handle
/// initialization of an object of type std::initializer_list<T>.
///
@@ -2810,25 +2989,23 @@ static bool TryInitializerListConstruction(Sema &S,
if (!S.isStdInitializerList(DestType, &E))
return false;
- // Check that each individual element can be copy-constructed. But since we
- // have no place to store further information, we'll recalculate everything
- // later.
- InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
- S.Context.getConstantArrayType(E,
- llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
- List->getNumInits()),
- ArrayType::Normal, 0));
- InitializedEntity Element = InitializedEntity::InitializeElement(S.Context,
- 0, HiddenArray);
- for (unsigned i = 0, n = List->getNumInits(); i < n; ++i) {
- Element.setElementIndex(i);
- if (!S.CanPerformCopyInitialization(Element, List->getInit(i))) {
- Sequence.SetFailed(
- InitializationSequence::FK_InitListElementCopyFailure);
- return true;
- }
+ if (S.RequireCompleteType(List->getExprLoc(), E, 0)) {
+ Sequence.setIncompleteTypeFailure(E);
+ return true;
}
- Sequence.AddStdInitializerListConstructionStep(DestType);
+
+ // Try initializing a temporary array from the init list.
+ QualType ArrayType = S.Context.getConstantArrayType(
+ E.withConst(), llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
+ List->getNumInits()),
+ clang::ArrayType::Normal, 0);
+ InitializedEntity HiddenArray =
+ InitializedEntity::InitializeTemporary(ArrayType);
+ InitializationKind Kind =
+ InitializationKind::CreateDirectList(List->getExprLoc());
+ TryListInitialization(S, HiddenArray, Kind, List, Sequence);
+ if (Sequence)
+ Sequence.AddStdInitializerListConstructionStep(DestType);
return true;
}
@@ -2857,9 +3034,19 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
else {
Constructor = cast<CXXConstructorDecl>(D);
- // If we're performing copy initialization using a copy constructor, we
- // suppress user-defined conversions on the arguments. We do the same for
- // move constructors.
+ // C++11 [over.best.ics]p4:
+ // However, when considering the argument of a constructor or
+ // user-defined conversion function that is a candidate:
+ // -- by 13.3.1.3 when invoked for the copying/moving of a temporary
+ // in the second step of a class copy-initialization,
+ // -- by 13.3.1.7 when passing the initializer list as a single
+ // argument or when the initializer list has exactly one elementand
+ // a conversion to some class X or reference to (possibly
+ // cv-qualified) X is considered for the first parameter of a
+ // constructor of X, or
+ // -- by 13.3.1.4, 13.3.1.5, or 13.3.1.6 in all cases,
+ // only standard conversion sequences and ellipsis conversion sequences
+ // are considered.
if ((CopyInitializing || (InitListSyntax && Args.size() == 1)) &&
Constructor->isCopyOrMoveConstructor())
SuppressUserConversions = true;
@@ -3058,19 +3245,12 @@ static void TryValueInitialization(Sema &S,
InitializationSequence &Sequence,
InitListExpr *InitList = 0);
-static void TryListInitialization(Sema &S,
- const InitializedEntity &Entity,
- const InitializationKind &Kind,
- InitListExpr *InitList,
- InitializationSequence &Sequence);
-
/// \brief Attempt list initialization of a reference.
static void TryReferenceListInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
InitListExpr *InitList,
- InitializationSequence &Sequence)
-{
+ InitializationSequence &Sequence) {
// First, catch C++03 where this isn't possible.
if (!S.getLangOpts().CPlusPlus11) {
Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
@@ -3187,11 +3367,36 @@ static void TryListInitialization(Sema &S,
return;
}
}
+ if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() &&
+ InitList->getNumInits() == 1 &&
+ InitList->getInit(0)->getType()->isRecordType()) {
+ // - Otherwise, if the initializer list has a single element of type E
+ // [...references are handled above...], the object or reference is
+ // initialized from that element; if a narrowing conversion is required
+ // to convert the element to T, the program is ill-formed.
+ //
+ // Per core-24034, this is direct-initialization if we were performing
+ // direct-list-initialization and copy-initialization otherwise.
+ // We can't use InitListChecker for this, because it always performs
+ // copy-initialization. This only matters if we might use an 'explicit'
+ // conversion operator, so we only need to handle the cases where the source
+ // is of record type.
+ InitializationKind SubKind =
+ Kind.getKind() == InitializationKind::IK_DirectList
+ ? InitializationKind::CreateDirect(Kind.getLocation(),
+ InitList->getLBraceLoc(),
+ InitList->getRBraceLoc())
+ : Kind;
+ Expr *SubInit[1] = { InitList->getInit(0) };
+ Sequence.InitializeFrom(S, Entity, SubKind, SubInit,
+ /*TopLevelOfInitList*/true);
+ if (Sequence)
+ Sequence.RewrapReferenceInitList(Entity.getType(), InitList);
+ return;
+ }
InitListChecker CheckInitList(S, Entity, InitList,
- DestType, /*VerifyOnly=*/true,
- Kind.getKind() != InitializationKind::IK_DirectList ||
- !S.getLangOpts().CPlusPlus11);
+ DestType, /*VerifyOnly=*/true);
if (CheckInitList.HadError()) {
Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed);
return;
@@ -3235,8 +3440,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
bool AllowExplicit = Kind.AllowExplicit();
- bool AllowExplicitConvs = Kind.allowExplicitConversionFunctions();
-
+ bool AllowExplicitConvs = Kind.allowExplicitConversionFunctionsInRefBinding();
+
const RecordType *T1RecordType = 0;
if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) &&
!S.RequireCompleteType(Kind.getLocation(), T1, 0)) {
@@ -3249,7 +3454,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// be changed while iterating (e.g. because of deserialization).
// To be safe we copy the lookup results to a new container.
SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end());
- for (SmallVector<NamedDecl*, 16>::iterator
+ for (SmallVectorImpl<NamedDecl *>::iterator
CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) {
NamedDecl *D = *CI;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
@@ -3503,7 +3708,7 @@ static void TryReferenceInitializationCore(Sema &S,
//
// - If the reference is an lvalue reference and the initializer
// expression
- // Note the analogous bullet points for rvlaue refs to functions. Because
+ // Note the analogous bullet points for rvalue refs to functions. Because
// there are no function rvalues in C++, rvalue refs to functions are treated
// like lvalue refs.
OverloadingResult ConvOvlResult = OR_Success;
@@ -3544,20 +3749,17 @@ static void TryReferenceInitializationCore(Sema &S,
// applicable conversion functions (13.3.1.6) and choosing the best
// one through overload resolution (13.3)),
// If we have an rvalue ref to function type here, the rhs must be
- // an rvalue.
+ // an rvalue. DR1287 removed the "implicitly" here.
if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() &&
(isLValueRef || InitCategory.isRValue())) {
- ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind,
- Initializer,
- /*AllowRValues=*/isRValueRef,
- Sequence);
+ ConvOvlResult = TryRefInitWithConversionFunction(
+ S, Entity, Kind, Initializer, /*AllowRValues*/isRValueRef, Sequence);
if (ConvOvlResult == OR_Success)
return;
- if (ConvOvlResult != OR_No_Viable_Function) {
+ if (ConvOvlResult != OR_No_Viable_Function)
Sequence.SetOverloadFailure(
- InitializationSequence::FK_ReferenceInitOverloadFailed,
- ConvOvlResult);
- }
+ InitializationSequence::FK_ReferenceInitOverloadFailed,
+ ConvOvlResult);
}
}
@@ -3629,16 +3831,16 @@ static void TryReferenceInitializationCore(Sema &S,
// reference-related to T2, and can be implicitly converted to an
// xvalue, class prvalue, or function lvalue of type "cv3 T3",
// where "cv1 T1" is reference-compatible with "cv3 T3",
+ //
+ // DR1287 removes the "implicitly" here.
if (T2->isRecordType()) {
if (RefRelationship == Sema::Ref_Incompatible) {
- ConvOvlResult = TryRefInitWithConversionFunction(S, Entity,
- Kind, Initializer,
- /*AllowRValues=*/true,
- Sequence);
+ ConvOvlResult = TryRefInitWithConversionFunction(
+ S, Entity, Kind, Initializer, /*AllowRValues*/true, Sequence);
if (ConvOvlResult)
Sequence.SetOverloadFailure(
- InitializationSequence::FK_ReferenceInitOverloadFailed,
- ConvOvlResult);
+ InitializationSequence::FK_ReferenceInitOverloadFailed,
+ ConvOvlResult);
return;
}
@@ -3657,19 +3859,17 @@ static void TryReferenceInitializationCore(Sema &S,
// - Otherwise, a temporary of type "cv1 T1" is created and initialized
// from the initializer expression using the rules for a non-reference
- // copy initialization (8.5). The reference is then bound to the
+ // copy-initialization (8.5). The reference is then bound to the
// temporary. [...]
- // Determine whether we are allowed to call explicit constructors or
- // explicit conversion operators.
- bool AllowExplicit = Kind.AllowExplicit();
-
InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1);
+ // FIXME: Why do we use an implicit conversion here rather than trying
+ // copy-initialization?
ImplicitConversionSequence ICS
= S.TryImplicitConversion(Initializer, TempEntity.getType(),
- /*SuppressUserConversions*/ false,
- AllowExplicit,
+ /*SuppressUserConversions=*/false,
+ /*AllowExplicit=*/false,
/*FIXME:InOverloadResolution=*/false,
/*CStyle=*/Kind.isCStyleOrFunctionalCast(),
/*AllowObjCWritebackConversion=*/false);
@@ -3848,7 +4048,8 @@ static void TryUserDefinedConversion(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
Expr *Initializer,
- InitializationSequence &Sequence) {
+ InitializationSequence &Sequence,
+ bool TopLevelOfInitList) {
QualType DestType = Entity.getType();
assert(!DestType->isReferenceType() && "References are handled elsewhere");
QualType SourceType = Initializer->getType();
@@ -3877,7 +4078,7 @@ static void TryUserDefinedConversion(Sema &S,
// be changed while iterating. To be safe we copy the lookup results
// to a new container.
SmallVector<NamedDecl*, 8> CopyOfCon(R.begin(), R.end());
- for (SmallVector<NamedDecl*, 8>::iterator
+ for (SmallVectorImpl<NamedDecl *>::iterator
Con = CopyOfCon.begin(), ConEnd = CopyOfCon.end();
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
@@ -3999,10 +4200,28 @@ static void TryUserDefinedConversion(Sema &S,
ImplicitConversionSequence ICS;
ICS.setStandard();
ICS.Standard = Best->FinalConversion;
- Sequence.AddConversionSequenceStep(ICS, DestType);
+ Sequence.AddConversionSequenceStep(ICS, DestType, TopLevelOfInitList);
}
}
+/// An egregious hack for compatibility with libstdc++-4.2: in <tr1/hashtable>,
+/// a function with a pointer return type contains a 'return false;' statement.
+/// In C++11, 'false' is not a null pointer, so this breaks the build of any
+/// code using that header.
+///
+/// Work around this by treating 'return false;' as zero-initializing the result
+/// if it's used in a pointer-returning function in a system header.
+static bool isLibstdcxxPointerReturnFalseHack(Sema &S,
+ const InitializedEntity &Entity,
+ const Expr *Init) {
+ return S.getLangOpts().CPlusPlus11 &&
+ Entity.getKind() == InitializedEntity::EK_Result &&
+ Entity.getType()->isPointerType() &&
+ isa<CXXBoolLiteralExpr>(Init) &&
+ !cast<CXXBoolLiteralExpr>(Init)->getValue() &&
+ S.getSourceManager().isInSystemHeader(Init->getExprLoc());
+}
+
/// The non-zero enum values here are indexes into diagnostic alternatives.
enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar };
@@ -4192,8 +4411,17 @@ static bool TryOCLZeroEventInitialization(Sema &S,
InitializationSequence::InitializationSequence(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
- MultiExprArg Args)
+ MultiExprArg Args,
+ bool TopLevelOfInitList)
: FailedCandidateSet(Kind.getLocation()) {
+ InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList);
+}
+
+void InitializationSequence::InitializeFrom(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ MultiExprArg Args,
+ bool TopLevelOfInitList) {
ASTContext &Context = S.Context;
// Eliminate non-overload placeholder types in the arguments. We
@@ -4283,9 +4511,23 @@ InitializationSequence::InitializationSequence(Sema &S,
return;
}
- if (Initializer && IsStringInit(Initializer, DestAT, Context)) {
- TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
- return;
+ if (Initializer) {
+ switch (IsStringInit(Initializer, DestAT, Context)) {
+ case SIF_None:
+ TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
+ return;
+ case SIF_NarrowStringIntoWideChar:
+ SetFailed(FK_NarrowStringIntoWideCharArray);
+ return;
+ case SIF_WideStringIntoChar:
+ SetFailed(FK_WideStringIntoCharArray);
+ return;
+ case SIF_IncompatWideStringIntoWideChar:
+ SetFailed(FK_IncompatWideStringIntoWideChar);
+ return;
+ case SIF_Other:
+ break;
+ }
}
// Note: as an GNU C extension, we allow initialization of an
@@ -4312,8 +4554,10 @@ InitializationSequence::InitializationSequence(Sema &S,
TryListInitialization(S, Entity, Kind, cast<InitListExpr>(Initializer),
*this);
AddParenthesizedArrayInitStep(DestType);
- } else if (DestAT->getElementType()->isAnyCharacterType())
+ } else if (DestAT->getElementType()->isCharType())
SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
+ else if (IsWideCharCompatible(DestAT->getElementType(), Context))
+ SetFailed(FK_ArrayNeedsInitListOrWideStringLiteral);
else
SetFailed(FK_ArrayNeedsInitList);
@@ -4323,7 +4567,7 @@ InitializationSequence::InitializationSequence(Sema &S,
// Determine whether we should consider writeback conversions for
// Objective-C ARC.
bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount &&
- Entity.getKind() == InitializedEntity::EK_Parameter;
+ Entity.isParameterKind();
// We're at the end of the line for C: it's either a write-back conversion
// or it's a C assignment. There's no need to check anything else.
@@ -4367,7 +4611,8 @@ InitializationSequence::InitializationSequence(Sema &S,
// 13.3.1.4, and the best one is chosen through overload resolution
// (13.3).
else
- TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
+ TryUserDefinedConversion(S, Entity, Kind, Initializer, *this,
+ TopLevelOfInitList);
return;
}
@@ -4380,7 +4625,8 @@ InitializationSequence::InitializationSequence(Sema &S,
// - Otherwise, if the source type is a (possibly cv-qualified) class
// type, conversion functions are considered.
if (!SourceType.isNull() && SourceType->isRecordType()) {
- TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
+ TryUserDefinedConversion(S, Entity, Kind, Initializer, *this,
+ TopLevelOfInitList);
MaybeProduceObjCObject(S, *this, Entity);
return;
}
@@ -4423,14 +4669,16 @@ InitializationSequence::InitializationSequence(Sema &S,
AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
} else if (ICS.isBad()) {
DeclAccessPair dap;
- if (Initializer->getType() == Context.OverloadTy &&
- !S.ResolveAddressOfOverloadedFunction(Initializer
- , DestType, false, dap))
+ if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) {
+ AddZeroInitializationStep(Entity.getType());
+ } else if (Initializer->getType() == Context.OverloadTy &&
+ !S.ResolveAddressOfOverloadedFunction(Initializer, DestType,
+ false, dap))
SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
else
SetFailed(InitializationSequence::FK_ConversionFailed);
} else {
- AddConversionSequenceStep(ICS, Entity.getType());
+ AddConversionSequenceStep(ICS, Entity.getType(), TopLevelOfInitList);
MaybeProduceObjCObject(S, *this, Entity);
}
@@ -4447,7 +4695,7 @@ InitializationSequence::~InitializationSequence() {
// Perform initialization
//===----------------------------------------------------------------------===//
static Sema::AssignmentAction
-getAssignmentAction(const InitializedEntity &Entity) {
+getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) {
switch(Entity.getKind()) {
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_New:
@@ -4463,10 +4711,18 @@ getAssignmentAction(const InitializedEntity &Entity) {
return Sema::AA_Passing;
+ case InitializedEntity::EK_Parameter_CF_Audited:
+ if (Entity.getDecl() &&
+ isa<ObjCMethodDecl>(Entity.getDecl()->getDeclContext()))
+ return Sema::AA_Sending;
+
+ return !Diagnose ? Sema::AA_Passing : Sema::AA_Passing_CFAudited;
+
case InitializedEntity::EK_Result:
return Sema::AA_Returning;
case InitializedEntity::EK_Temporary:
+ case InitializedEntity::EK_RelatedResult:
// FIXME: Can we tell apart casting vs. converting?
return Sema::AA_Casting;
@@ -4503,7 +4759,9 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
return false;
case InitializedEntity::EK_Parameter:
+ case InitializedEntity::EK_Parameter_CF_Audited:
case InitializedEntity::EK_Temporary:
+ case InitializedEntity::EK_RelatedResult:
return true;
}
@@ -4527,10 +4785,12 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_Member:
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Parameter:
+ case InitializedEntity::EK_Parameter_CF_Audited:
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Exception:
case InitializedEntity::EK_CompoundLiteralInit:
+ case InitializedEntity::EK_RelatedResult:
return true;
}
@@ -4548,7 +4808,7 @@ static void LookupCopyAndMoveConstructors(Sema &S,
// be changed while iterating (e.g. because of deserialization).
// To be safe we copy the lookup results to a new container.
SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end());
- for (SmallVector<NamedDecl*, 16>::iterator
+ for (SmallVectorImpl<NamedDecl *>::iterator
CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) {
NamedDecl *D = *CI;
CXXConstructorDecl *Constructor = 0;
@@ -4605,6 +4865,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Member:
case InitializedEntity::EK_Parameter:
+ case InitializedEntity::EK_Parameter_CF_Audited:
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_New:
case InitializedEntity::EK_Base:
@@ -4613,6 +4874,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
case InitializedEntity::EK_ComplexElement:
case InitializedEntity::EK_BlockElement:
case InitializedEntity::EK_CompoundLiteralInit:
+ case InitializedEntity::EK_RelatedResult:
return Initializer->getLocStart();
}
llvm_unreachable("missed an InitializedEntity kind?");
@@ -4823,7 +5085,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S,
void InitializationSequence::PrintInitLocationNote(Sema &S,
const InitializedEntity &Entity) {
- if (Entity.getKind() == InitializedEntity::EK_Parameter && Entity.getDecl()) {
+ if (Entity.isParameterKind() && Entity.getDecl()) {
if (Entity.getDecl()->getLocation().isInvalid())
return;
@@ -4833,6 +5095,11 @@ void InitializationSequence::PrintInitLocationNote(Sema &S,
else
S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_here);
}
+ else if (Entity.getKind() == InitializedEntity::EK_RelatedResult &&
+ Entity.getMethodDecl())
+ S.Diag(Entity.getMethodDecl()->getLocation(),
+ diag::note_method_return_type_change)
+ << Entity.getMethodDecl()->getDeclName();
}
static bool isReferenceBinding(const InitializationSequence::Step &s) {
@@ -4848,6 +5115,7 @@ static bool isExplicitTemporary(const InitializedEntity &Entity,
switch (Entity.getKind()) {
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_CompoundLiteralInit:
+ case InitializedEntity::EK_RelatedResult:
break;
default:
return false;
@@ -4872,7 +5140,9 @@ PerformConstructorInitialization(Sema &S,
MultiExprArg Args,
const InitializationSequence::Step& Step,
bool &ConstructorInitRequiresZeroInit,
- bool IsListInitialization) {
+ bool IsListInitialization,
+ SourceLocation LBraceLoc,
+ SourceLocation RBraceLoc) {
unsigned NumArgs = Args.size();
CXXConstructorDecl *Constructor
= cast<CXXConstructorDecl>(Step.Function.Function);
@@ -4924,15 +5194,17 @@ PerformConstructorInitialization(Sema &S,
TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
if (!TSInfo)
TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
- SourceRange ParenRange;
- if (Kind.getKind() != InitializationKind::IK_DirectList)
- ParenRange = Kind.getParenRange();
+ SourceRange ParenOrBraceRange =
+ (Kind.getKind() == InitializationKind::IK_DirectList)
+ ? SourceRange(LBraceLoc, RBraceLoc)
+ : Kind.getParenRange();
CurInit = S.Owned(
new (S.Context) CXXTemporaryObjectExpr(S.Context, Constructor,
TSInfo, ConstructorArgs,
- ParenRange, IsListInitialization,
+ ParenOrBraceRange,
HadMultipleCandidates,
+ IsListInitialization,
ConstructorInitRequiresZeroInit));
} else {
CXXConstructExpr::ConstructionKind ConstructKind =
@@ -4982,7 +5254,7 @@ PerformConstructorInitialization(Sema &S,
return ExprError();
if (shouldBindAsTemporary(Entity))
- CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+ CurInit = S.MaybeBindToTemporary(CurInit.take());
return CurInit;
}
@@ -5015,9 +5287,11 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) {
return false;
case InitializedEntity::EK_Parameter:
+ case InitializedEntity::EK_Parameter_CF_Audited:
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_LambdaCapture:
case InitializedEntity::EK_CompoundLiteralInit:
+ case InitializedEntity::EK_RelatedResult:
// The entity being initialized might not outlive the full-expression.
return false;
}
@@ -5025,6 +5299,220 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) {
llvm_unreachable("unknown entity kind");
}
+/// Determine the declaration which an initialized entity ultimately refers to,
+/// for the purpose of lifetime-extending a temporary bound to a reference in
+/// the initialization of \p Entity.
+static const ValueDecl *
+getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity,
+ const ValueDecl *FallbackDecl = 0) {
+ // C++11 [class.temporary]p5:
+ switch (Entity.getKind()) {
+ case InitializedEntity::EK_Variable:
+ // The temporary [...] persists for the lifetime of the reference
+ return Entity.getDecl();
+
+ case InitializedEntity::EK_Member:
+ // For subobjects, we look at the complete object.
+ if (Entity.getParent())
+ return getDeclForTemporaryLifetimeExtension(*Entity.getParent(),
+ Entity.getDecl());
+
+ // except:
+ // -- A temporary bound to a reference member in a constructor's
+ // ctor-initializer persists until the constructor exits.
+ return Entity.getDecl();
+
+ case InitializedEntity::EK_Parameter:
+ case InitializedEntity::EK_Parameter_CF_Audited:
+ // -- A temporary bound to a reference parameter in a function call
+ // persists until the completion of the full-expression containing
+ // the call.
+ case InitializedEntity::EK_Result:
+ // -- The lifetime of a temporary bound to the returned value in a
+ // function return statement is not extended; the temporary is
+ // destroyed at the end of the full-expression in the return statement.
+ case InitializedEntity::EK_New:
+ // -- A temporary bound to a reference in a new-initializer persists
+ // until the completion of the full-expression containing the
+ // new-initializer.
+ return 0;
+
+ case InitializedEntity::EK_Temporary:
+ case InitializedEntity::EK_CompoundLiteralInit:
+ case InitializedEntity::EK_RelatedResult:
+ // We don't yet know the storage duration of the surrounding temporary.
+ // Assume it's got full-expression duration for now, it will patch up our
+ // storage duration if that's not correct.
+ return 0;
+
+ case InitializedEntity::EK_ArrayElement:
+ // For subobjects, we look at the complete object.
+ return getDeclForTemporaryLifetimeExtension(*Entity.getParent(),
+ FallbackDecl);
+
+ case InitializedEntity::EK_Base:
+ case InitializedEntity::EK_Delegating:
+ // We can reach this case for aggregate initialization in a constructor:
+ // struct A { int &&r; };
+ // struct B : A { B() : A{0} {} };
+ // In this case, use the innermost field decl as the context.
+ return FallbackDecl;
+
+ case InitializedEntity::EK_BlockElement:
+ case InitializedEntity::EK_LambdaCapture:
+ case InitializedEntity::EK_Exception:
+ case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_ComplexElement:
+ return 0;
+ }
+ llvm_unreachable("unknown entity kind");
+}
+
+static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD);
+
+/// Update a glvalue expression that is used as the initializer of a reference
+/// to note that its lifetime is extended.
+/// \return \c true if any temporary had its lifetime extended.
+static bool performReferenceExtension(Expr *Init, const ValueDecl *ExtendingD) {
+ if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
+ if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
+ // This is just redundant braces around an initializer. Step over it.
+ Init = ILE->getInit(0);
+ }
+ }
+
+ // Walk past any constructs which we can lifetime-extend across.
+ Expr *Old;
+ do {
+ Old = Init;
+
+ // Step over any subobject adjustments; we may have a materialized
+ // temporary inside them.
+ SmallVector<const Expr *, 2> CommaLHSs;
+ SmallVector<SubobjectAdjustment, 2> Adjustments;
+ Init = const_cast<Expr *>(
+ Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
+
+ // Per current approach for DR1376, look through casts to reference type
+ // when performing lifetime extension.
+ if (CastExpr *CE = dyn_cast<CastExpr>(Init))
+ if (CE->getSubExpr()->isGLValue())
+ Init = CE->getSubExpr();
+
+ // FIXME: Per DR1213, subscripting on an array temporary produces an xvalue.
+ // It's unclear if binding a reference to that xvalue extends the array
+ // temporary.
+ } while (Init != Old);
+
+ if (MaterializeTemporaryExpr *ME = dyn_cast<MaterializeTemporaryExpr>(Init)) {
+ // Update the storage duration of the materialized temporary.
+ // FIXME: Rebuild the expression instead of mutating it.
+ ME->setExtendingDecl(ExtendingD);
+ performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingD);
+ return true;
+ }
+
+ return false;
+}
+
+/// Update a prvalue expression that is going to be materialized as a
+/// lifetime-extended temporary.
+static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) {
+ // Dig out the expression which constructs the extended temporary.
+ SmallVector<const Expr *, 2> CommaLHSs;
+ SmallVector<SubobjectAdjustment, 2> Adjustments;
+ Init = const_cast<Expr *>(
+ Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
+
+ if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
+ Init = BTE->getSubExpr();
+
+ if (CXXStdInitializerListExpr *ILE =
+ dyn_cast<CXXStdInitializerListExpr>(Init)) {
+ performReferenceExtension(ILE->getSubExpr(), ExtendingD);
+ return;
+ }
+
+ if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
+ if (ILE->getType()->isArrayType()) {
+ for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
+ performLifetimeExtension(ILE->getInit(I), ExtendingD);
+ return;
+ }
+
+ if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
+ assert(RD->isAggregate() && "aggregate init on non-aggregate");
+
+ // If we lifetime-extend a braced initializer which is initializing an
+ // aggregate, and that aggregate contains reference members which are
+ // bound to temporaries, those temporaries are also lifetime-extended.
+ if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
+ ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
+ performReferenceExtension(ILE->getInit(0), ExtendingD);
+ else {
+ unsigned Index = 0;
+ for (RecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end();
+ I != E; ++I) {
+ if (Index >= ILE->getNumInits())
+ break;
+ if (I->isUnnamedBitfield())
+ continue;
+ Expr *SubInit = ILE->getInit(Index);
+ if (I->getType()->isReferenceType())
+ performReferenceExtension(SubInit, ExtendingD);
+ else if (isa<InitListExpr>(SubInit) ||
+ isa<CXXStdInitializerListExpr>(SubInit))
+ // This may be either aggregate-initialization of a member or
+ // initialization of a std::initializer_list object. Either way,
+ // we should recursively lifetime-extend that initializer.
+ performLifetimeExtension(SubInit, ExtendingD);
+ ++Index;
+ }
+ }
+ }
+ }
+}
+
+static void warnOnLifetimeExtension(Sema &S, const InitializedEntity &Entity,
+ const Expr *Init, bool IsInitializerList,
+ const ValueDecl *ExtendingDecl) {
+ // Warn if a field lifetime-extends a temporary.
+ if (isa<FieldDecl>(ExtendingDecl)) {
+ if (IsInitializerList) {
+ S.Diag(Init->getExprLoc(), diag::warn_dangling_std_initializer_list)
+ << /*at end of constructor*/true;
+ return;
+ }
+
+ bool IsSubobjectMember = false;
+ for (const InitializedEntity *Ent = Entity.getParent(); Ent;
+ Ent = Ent->getParent()) {
+ if (Ent->getKind() != InitializedEntity::EK_Base) {
+ IsSubobjectMember = true;
+ break;
+ }
+ }
+ S.Diag(Init->getExprLoc(),
+ diag::warn_bind_ref_member_to_temporary)
+ << ExtendingDecl << Init->getSourceRange()
+ << IsSubobjectMember << IsInitializerList;
+ if (IsSubobjectMember)
+ S.Diag(ExtendingDecl->getLocation(),
+ diag::note_ref_subobject_of_member_declared_here);
+ else
+ S.Diag(ExtendingDecl->getLocation(),
+ diag::note_ref_or_ptr_member_declared_here)
+ << /*is pointer*/false;
+ }
+}
+
+static void DiagnoseNarrowingInInitList(Sema &S,
+ const ImplicitConversionSequence &ICS,
+ QualType PreNarrowingType,
+ QualType EntityType,
+ const Expr *PostInit);
+
ExprResult
InitializationSequence::Perform(Sema &S,
const InitializedEntity &Entity,
@@ -5094,7 +5582,7 @@ InitializationSequence::Perform(Sema &S,
if (S.getLangOpts().CPlusPlus11 && Entity.getType()->isReferenceType() &&
Args.size() == 1 && isa<InitListExpr>(Args[0]) &&
- Entity.getKind() != InitializedEntity::EK_Parameter) {
+ !Entity.isParameterKind()) {
// Produce a C++98 compatibility warning if we are initializing a reference
// from an initializer list. For parameters, we produce a better warning
// elsewhere.
@@ -5142,6 +5630,7 @@ InitializationSequence::Perform(Sema &S,
case SK_QualificationConversionRValue:
case SK_LValueToRValue:
case SK_ConversionSequence:
+ case SK_ConversionSequenceNoNarrowing:
case SK_ListInitialization:
case SK_UnwrapInitList:
case SK_RewrapInitList:
@@ -5260,9 +5749,19 @@ InitializationSequence::Perform(Sema &S,
if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
return ExprError();
+ // Even though we didn't materialize a temporary, the binding may still
+ // extend the lifetime of a temporary. This happens if we bind a reference
+ // to the result of a cast to reference type.
+ if (const ValueDecl *ExtendingDecl =
+ getDeclForTemporaryLifetimeExtension(Entity)) {
+ if (performReferenceExtension(CurInit.get(), ExtendingDecl))
+ warnOnLifetimeExtension(S, Entity, CurInit.get(), false,
+ ExtendingDecl);
+ }
+
break;
- case SK_BindReferenceToTemporary:
+ case SK_BindReferenceToTemporary: {
// Make sure the "temporary" is actually an rvalue.
assert(CurInit.get()->isRValue() && "not a temporary");
@@ -5270,19 +5769,33 @@ InitializationSequence::Perform(Sema &S,
if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
return ExprError();
+ // Maybe lifetime-extend the temporary's subobjects to match the
+ // entity's lifetime.
+ const ValueDecl *ExtendingDecl =
+ getDeclForTemporaryLifetimeExtension(Entity);
+ if (ExtendingDecl) {
+ performLifetimeExtension(CurInit.get(), ExtendingDecl);
+ warnOnLifetimeExtension(S, Entity, CurInit.get(), false, ExtendingDecl);
+ }
+
// Materialize the temporary into memory.
- CurInit = new (S.Context) MaterializeTemporaryExpr(
- Entity.getType().getNonReferenceType(),
- CurInit.get(),
- Entity.getType()->isLValueReferenceType());
+ MaterializeTemporaryExpr *MTE = new (S.Context) MaterializeTemporaryExpr(
+ Entity.getType().getNonReferenceType(), CurInit.get(),
+ Entity.getType()->isLValueReferenceType(), ExtendingDecl);
// If we're binding to an Objective-C object that has lifetime, we
- // need cleanups.
- if (S.getLangOpts().ObjCAutoRefCount &&
- CurInit.get()->getType()->isObjCLifetimeType())
+ // need cleanups. Likewise if we're extending this temporary to automatic
+ // storage duration -- we need to register its cleanup during the
+ // full-expression's cleanups.
+ if ((S.getLangOpts().ObjCAutoRefCount &&
+ MTE->getType()->isObjCLifetimeType()) ||
+ (MTE->getStorageDuration() == SD_Automatic &&
+ MTE->getType().isDestructedType()))
S.ExprNeedsCleanups = true;
-
+
+ CurInit = S.Owned(MTE);
break;
+ }
case SK_ExtraneousCopyToTemporary:
CurInit = CopyObject(S, Step->Type, Entity, CurInit,
@@ -5416,8 +5929,9 @@ InitializationSequence::Perform(Sema &S,
break;
}
- case SK_ConversionSequence: {
- Sema::CheckedConversionKind CCK
+ case SK_ConversionSequence:
+ case SK_ConversionSequenceNoNarrowing: {
+ Sema::CheckedConversionKind CCK
= Kind.isCStyleCast()? Sema::CCK_CStyleCast
: Kind.isFunctionalCast()? Sema::CCK_FunctionalCast
: Kind.isExplicitCast()? Sema::CCK_OtherCast
@@ -5428,31 +5942,32 @@ InitializationSequence::Perform(Sema &S,
if (CurInitExprRes.isInvalid())
return ExprError();
CurInit = CurInitExprRes;
+
+ if (Step->Kind == SK_ConversionSequenceNoNarrowing &&
+ S.getLangOpts().CPlusPlus && !CurInit.get()->isValueDependent())
+ DiagnoseNarrowingInInitList(S, *Step->ICS, SourceType, Entity.getType(),
+ CurInit.get());
break;
}
case SK_ListInitialization: {
InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
- // Hack: We must pass *ResultType if available in order to set the type
- // of arrays, e.g. in 'int ar[] = {1, 2, 3};'.
- // But in 'const X &x = {1, 2, 3};' we're supposed to initialize a
- // temporary, not a reference, so we should pass Ty.
- // Worst case: 'const int (&arref)[] = {1, 2, 3};'.
- // Since this step is never used for a reference directly, we explicitly
- // unwrap references here and rewrap them afterwards.
- // We also need to create a InitializeTemporary entity for this.
- QualType Ty = ResultType ? ResultType->getNonReferenceType() : Step->Type;
- bool IsTemporary = Entity.getType()->isReferenceType();
+ // If we're not initializing the top-level entity, we need to create an
+ // InitializeTemporary entity for our target type.
+ QualType Ty = Step->Type;
+ bool IsTemporary = !S.Context.hasSameType(Entity.getType(), Ty);
InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty);
InitializedEntity InitEntity = IsTemporary ? TempEntity : Entity;
InitListChecker PerformInitList(S, InitEntity,
- InitList, Ty, /*VerifyOnly=*/false,
- Kind.getKind() != InitializationKind::IK_DirectList ||
- !S.getLangOpts().CPlusPlus11);
+ InitList, Ty, /*VerifyOnly=*/false);
if (PerformInitList.HadError())
return ExprError();
- if (ResultType) {
+ // Hack: We must update *ResultType if available in order to set the
+ // bounds of arrays, e.g. in 'int ar[] = {1, 2, 3};'.
+ // Worst case: 'const int (&arref)[] = {1, 2, 3};'.
+ if (ResultType &&
+ ResultType->getNonReferenceType()->isIncompleteArrayType()) {
if ((*ResultType)->isRValueReferenceType())
Ty = S.Context.getRValueReferenceType(Ty);
else if ((*ResultType)->isLValueReferenceType())
@@ -5489,7 +6004,9 @@ InitializationSequence::Perform(Sema &S,
Entity,
Kind, Arg, *Step,
ConstructorInitRequiresZeroInit,
- /*IsListInitialization*/ true);
+ /*IsListInitialization*/ true,
+ InitList->getLBraceLoc(),
+ InitList->getRBraceLoc());
break;
}
@@ -5523,7 +6040,9 @@ InitializationSequence::Perform(Sema &S,
: Entity,
Kind, Args, *Step,
ConstructorInitRequiresZeroInit,
- /*IsListInitialization*/ false);
+ /*IsListInitialization*/ false,
+ /*LBraceLoc*/ SourceLocation(),
+ /*RBraceLoc*/ SourceLocation());
break;
}
@@ -5558,7 +6077,8 @@ InitializationSequence::Perform(Sema &S,
QualType SourceType = CurInit.get()->getType();
ExprResult Result = CurInit;
Sema::AssignConvertType ConvTy =
- S.CheckSingleAssignmentConstraints(Step->Type, Result);
+ S.CheckSingleAssignmentConstraints(Step->Type, Result, true,
+ Entity.getKind() == InitializedEntity::EK_Parameter_CF_Audited);
if (Result.isInvalid())
return ExprError();
CurInit = Result;
@@ -5566,7 +6086,7 @@ InitializationSequence::Perform(Sema &S,
// If this is a call, allow conversion to a transparent union.
ExprResult CurInitExprRes = CurInit;
if (ConvTy != Sema::Compatible &&
- Entity.getKind() == InitializedEntity::EK_Parameter &&
+ Entity.isParameterKind() &&
S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExprRes)
== Sema::Compatible)
ConvTy = Sema::Compatible;
@@ -5578,7 +6098,7 @@ InitializationSequence::Perform(Sema &S,
if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(),
Step->Type, SourceType,
CurInit.get(),
- getAssignmentAction(Entity),
+ getAssignmentAction(Entity, true),
&Complained)) {
PrintInitLocationNote(S, Entity);
return ExprError();
@@ -5645,67 +6165,46 @@ InitializationSequence::Perform(Sema &S,
break;
case SK_StdInitializerList: {
- QualType Dest = Step->Type;
- QualType E;
- bool Success = S.isStdInitializerList(Dest.getNonReferenceType(), &E);
- (void)Success;
- assert(Success && "Destination type changed?");
-
- // If the element type has a destructor, check it.
- if (CXXRecordDecl *RD = E->getAsCXXRecordDecl()) {
- if (!RD->hasIrrelevantDestructor()) {
- if (CXXDestructorDecl *Destructor = S.LookupDestructor(RD)) {
- S.MarkFunctionReferenced(Kind.getLocation(), Destructor);
- S.CheckDestructorAccess(Kind.getLocation(), Destructor,
- S.PDiag(diag::err_access_dtor_temp) << E);
- if (S.DiagnoseUseOfDecl(Destructor, Kind.getLocation()))
- return ExprError();
- }
- }
- }
+ S.Diag(CurInit.get()->getExprLoc(),
+ diag::warn_cxx98_compat_initializer_list_init)
+ << CurInit.get()->getSourceRange();
- InitListExpr *ILE = cast<InitListExpr>(CurInit.take());
- S.Diag(ILE->getExprLoc(), diag::warn_cxx98_compat_initializer_list_init)
- << ILE->getSourceRange();
- unsigned NumInits = ILE->getNumInits();
- SmallVector<Expr*, 16> Converted(NumInits);
- InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
- S.Context.getConstantArrayType(E,
- llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
- NumInits),
- ArrayType::Normal, 0));
- InitializedEntity Element =InitializedEntity::InitializeElement(S.Context,
- 0, HiddenArray);
- for (unsigned i = 0; i < NumInits; ++i) {
- Element.setElementIndex(i);
- ExprResult Init = S.Owned(ILE->getInit(i));
- ExprResult Res = S.PerformCopyInitialization(
- Element, Init.get()->getExprLoc(), Init,
- /*TopLevelOfInitList=*/ true);
- assert(!Res.isInvalid() && "Result changed since try phase.");
- Converted[i] = Res.take();
+ // Maybe lifetime-extend the array temporary's subobjects to match the
+ // entity's lifetime.
+ const ValueDecl *ExtendingDecl =
+ getDeclForTemporaryLifetimeExtension(Entity);
+ if (ExtendingDecl) {
+ performLifetimeExtension(CurInit.get(), ExtendingDecl);
+ warnOnLifetimeExtension(S, Entity, CurInit.get(), true, ExtendingDecl);
}
- InitListExpr *Semantic = new (S.Context)
- InitListExpr(S.Context, ILE->getLBraceLoc(),
- Converted, ILE->getRBraceLoc());
- Semantic->setSyntacticForm(ILE);
- Semantic->setType(Dest);
- Semantic->setInitializesStdInitializerList();
- CurInit = S.Owned(Semantic);
+
+ // Materialize the temporary into memory.
+ MaterializeTemporaryExpr *MTE = new (S.Context)
+ MaterializeTemporaryExpr(CurInit.get()->getType(), CurInit.get(),
+ /*lvalue reference*/ false, ExtendingDecl);
+
+ // Wrap it in a construction of a std::initializer_list<T>.
+ CurInit = S.Owned(
+ new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE));
+
+ // Bind the result, in case the library has given initializer_list a
+ // non-trivial destructor.
+ if (shouldBindAsTemporary(Entity))
+ CurInit = S.MaybeBindToTemporary(CurInit.take());
break;
}
+
case SK_OCLSamplerInit: {
assert(Step->Type->isSamplerT() &&
"Sampler initialization on non sampler type.");
QualType SourceType = CurInit.get()->getType();
- InitializedEntity::EntityKind EntityKind = Entity.getKind();
- if (EntityKind == InitializedEntity::EK_Parameter) {
+ if (Entity.isParameterKind()) {
if (!SourceType->isSamplerT())
S.Diag(Kind.getLocation(), diag::err_sampler_argument_required)
<< SourceType;
- } else if (EntityKind != InitializedEntity::EK_Variable) {
+ } else if (Entity.getKind() != InitializedEntity::EK_Variable) {
llvm_unreachable("Invalid EntityKind!");
}
@@ -5794,6 +6293,28 @@ static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity,
}
}
+static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
+ InitListExpr *InitList) {
+ QualType DestType = Entity.getType();
+
+ QualType E;
+ if (S.getLangOpts().CPlusPlus11 && S.isStdInitializerList(DestType, &E)) {
+ QualType ArrayType = S.Context.getConstantArrayType(
+ E.withConst(),
+ llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
+ InitList->getNumInits()),
+ clang::ArrayType::Normal, 0);
+ InitializedEntity HiddenArray =
+ InitializedEntity::InitializeTemporary(ArrayType);
+ return diagnoseListInit(S, HiddenArray, InitList);
+ }
+
+ InitListChecker DiagnoseInitList(S, Entity, InitList, DestType,
+ /*VerifyOnly=*/false);
+ assert(DiagnoseInitList.HadError() &&
+ "Inconsistent init list check result.");
+}
+
bool InitializationSequence::Diagnose(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -5821,14 +6342,27 @@ bool InitializationSequence::Diagnose(Sema &S,
break;
case FK_ArrayNeedsInitList:
+ S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 0;
+ break;
case FK_ArrayNeedsInitListOrStringLiteral:
- S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list)
- << (Failure == FK_ArrayNeedsInitListOrStringLiteral);
+ S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 1;
+ break;
+ case FK_ArrayNeedsInitListOrWideStringLiteral:
+ S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 2;
+ break;
+ case FK_NarrowStringIntoWideCharArray:
+ S.Diag(Kind.getLocation(), diag::err_array_init_narrow_string_into_wchar);
+ break;
+ case FK_WideStringIntoCharArray:
+ S.Diag(Kind.getLocation(), diag::err_array_init_wide_string_into_char);
+ break;
+ case FK_IncompatWideStringIntoWideChar:
+ S.Diag(Kind.getLocation(),
+ diag::err_array_init_incompat_wide_string_into_wchar);
break;
-
case FK_ArrayTypeMismatch:
case FK_NonConstantArrayInit:
- S.Diag(Kind.getLocation(),
+ S.Diag(Kind.getLocation(),
(Failure == FK_ArrayTypeMismatch
? diag::err_array_init_different_type
: diag::err_array_init_non_constant_array))
@@ -5868,9 +6402,14 @@ bool InitializationSequence::Diagnose(Sema &S,
break;
case OR_No_Viable_Function:
- S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
- << Args[0]->getType() << DestType.getNonReferenceType()
- << Args[0]->getSourceRange();
+ if (!S.RequireCompleteType(Kind.getLocation(),
+ DestType.getNonReferenceType(),
+ diag::err_typecheck_nonviable_condition_incomplete,
+ Args[0]->getType(), Args[0]->getSourceRange()))
+ S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
+ << Args[0]->getType() << Args[0]->getSourceRange()
+ << DestType.getNonReferenceType();
+
FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args);
break;
@@ -6115,14 +6654,8 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_ListInitializationFailed: {
// Run the init list checker again to emit diagnostics.
- InitListExpr* InitList = cast<InitListExpr>(Args[0]);
- QualType DestType = Entity.getType();
- InitListChecker DiagnoseInitList(S, Entity, InitList,
- DestType, /*VerifyOnly=*/false,
- Kind.getKind() != InitializationKind::IK_DirectList ||
- !S.getLangOpts().CPlusPlus11);
- assert(DiagnoseInitList.HadError() &&
- "Inconsistent init list check result.");
+ InitListExpr *InitList = cast<InitListExpr>(Args[0]);
+ diagnoseListInit(S, Entity, InitList);
break;
}
@@ -6131,37 +6664,6 @@ bool InitializationSequence::Diagnose(Sema &S,
break;
}
- case FK_InitListElementCopyFailure: {
- // Try to perform all copies again.
- InitListExpr* InitList = cast<InitListExpr>(Args[0]);
- unsigned NumInits = InitList->getNumInits();
- QualType DestType = Entity.getType();
- QualType E;
- bool Success = S.isStdInitializerList(DestType.getNonReferenceType(), &E);
- (void)Success;
- assert(Success && "Where did the std::initializer_list go?");
- InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
- S.Context.getConstantArrayType(E,
- llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
- NumInits),
- ArrayType::Normal, 0));
- InitializedEntity Element = InitializedEntity::InitializeElement(S.Context,
- 0, HiddenArray);
- // Show at most 3 errors. Otherwise, you'd get a lot of errors for errors
- // where the init list type is wrong, e.g.
- // std::initializer_list<void*> list = { 1, 2, 3, 4, 5, 6, 7, 8 };
- // FIXME: Emit a note if we hit the limit?
- int ErrorCount = 0;
- for (unsigned i = 0; i < NumInits && ErrorCount < 3; ++i) {
- Element.setElementIndex(i);
- ExprResult Init = S.Owned(InitList->getInit(i));
- if (S.PerformCopyInitialization(Element, Init.get()->getExprLoc(), Init)
- .isInvalid())
- ++ErrorCount;
- }
- break;
- }
-
case FK_ExplicitConstructor: {
S.Diag(Kind.getLocation(), diag::err_selected_explicit_constructor)
<< Args[0]->getSourceRange();
@@ -6197,6 +6699,22 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "array requires initializer list or string literal";
break;
+ case FK_ArrayNeedsInitListOrWideStringLiteral:
+ OS << "array requires initializer list or wide string literal";
+ break;
+
+ case FK_NarrowStringIntoWideCharArray:
+ OS << "narrow string into wide char array";
+ break;
+
+ case FK_WideStringIntoCharArray:
+ OS << "wide string into char array";
+ break;
+
+ case FK_IncompatWideStringIntoWideChar:
+ OS << "incompatible wide string into wide char array";
+ break;
+
case FK_ArrayTypeMismatch:
OS << "array type mismatch";
break;
@@ -6285,10 +6803,6 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "list constructor overloading failed";
break;
- case FK_InitListElementCopyFailure:
- OS << "copy construction of initializer list element failed";
- break;
-
case FK_ExplicitConstructor:
OS << "list copy initialization chose explicit constructor";
break;
@@ -6362,7 +6876,13 @@ void InitializationSequence::dump(raw_ostream &OS) const {
case SK_ConversionSequence:
OS << "implicit conversion sequence (";
- S->ICS->DebugPrint(); // FIXME: use OS
+ S->ICS->dump(); // FIXME: use OS
+ OS << ")";
+ break;
+
+ case SK_ConversionSequenceNoNarrowing:
+ OS << "implicit conversion sequence with narrowing prohibited (";
+ S->ICS->dump(); // FIXME: use OS
OS << ")";
break;
@@ -6445,20 +6965,11 @@ void InitializationSequence::dump() const {
dump(llvm::errs());
}
-static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq,
+static void DiagnoseNarrowingInInitList(Sema &S,
+ const ImplicitConversionSequence &ICS,
+ QualType PreNarrowingType,
QualType EntityType,
- const Expr *PreInit,
const Expr *PostInit) {
- if (Seq.step_begin() == Seq.step_end() || PreInit->isValueDependent())
- return;
-
- // A narrowing conversion can only appear as the final implicit conversion in
- // an initialization sequence.
- const InitializationSequence::Step &LastStep = Seq.step_end()[-1];
- if (LastStep.Kind != InitializationSequence::SK_ConversionSequence)
- return;
-
- const ImplicitConversionSequence &ICS = *LastStep.ICS;
const StandardConversionSequence *SCS = 0;
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
@@ -6473,13 +6984,6 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq,
return;
}
- // Determine the type prior to the narrowing conversion. If a conversion
- // operator was used, this may be different from both the type of the entity
- // and of the pre-initialization expression.
- QualType PreNarrowingType = PreInit->getType();
- if (Seq.step_begin() + 1 != Seq.step_end())
- PreNarrowingType = Seq.step_end()[-2].Type;
-
// C++11 [dcl.init.list]p7: Check whether this is a narrowing conversion.
APValue ConstantValue;
QualType ConstantType;
@@ -6494,11 +6998,9 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq,
// narrowing conversion even if the value is a constant and can be
// represented exactly as an integer.
S.Diag(PostInit->getLocStart(),
- S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11?
- diag::warn_init_list_type_narrowing
- : S.isSFINAEContext()?
- diag::err_init_list_type_narrowing_sfinae
- : diag::err_init_list_type_narrowing)
+ (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11)
+ ? diag::warn_init_list_type_narrowing
+ : diag::ext_init_list_type_narrowing)
<< PostInit->getSourceRange()
<< PreNarrowingType.getLocalUnqualifiedType()
<< EntityType.getLocalUnqualifiedType();
@@ -6507,11 +7009,9 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq,
case NK_Constant_Narrowing:
// A constant value was narrowed.
S.Diag(PostInit->getLocStart(),
- S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11?
- diag::warn_init_list_constant_narrowing
- : S.isSFINAEContext()?
- diag::err_init_list_constant_narrowing_sfinae
- : diag::err_init_list_constant_narrowing)
+ (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11)
+ ? diag::warn_init_list_constant_narrowing
+ : diag::ext_init_list_constant_narrowing)
<< PostInit->getSourceRange()
<< ConstantValue.getAsString(S.getASTContext(), ConstantType)
<< EntityType.getLocalUnqualifiedType();
@@ -6520,11 +7020,9 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq,
case NK_Variable_Narrowing:
// A variable's value may have been narrowed.
S.Diag(PostInit->getLocStart(),
- S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11?
- diag::warn_init_list_variable_narrowing
- : S.isSFINAEContext()?
- diag::err_init_list_variable_narrowing_sfinae
- : diag::err_init_list_variable_narrowing)
+ (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11)
+ ? diag::warn_init_list_variable_narrowing
+ : diag::ext_init_list_variable_narrowing)
<< PostInit->getSourceRange()
<< PreNarrowingType.getLocalUnqualifiedType()
<< EntityType.getLocalUnqualifiedType();
@@ -6592,14 +7090,10 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity,
InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(),
EqualLoc,
AllowExplicit);
- InitializationSequence Seq(*this, Entity, Kind, InitE);
+ InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList);
Init.release();
ExprResult Result = Seq.Perform(*this, Entity, Kind, InitE);
- if (!Result.isInvalid() && TopLevelOfInitList)
- DiagnoseNarrowingInInitList(*this, Seq, Entity.getType(),
- InitE, Result.get());
-
return Result;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
index c7ba3cc822f3..a7d5b6526464 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
@@ -11,27 +11,163 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/DeclSpec.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/SemaLambda.h"
+#include "TypeLocBuilder.h"
using namespace clang;
using namespace sema;
+// returns -1 if none of the lambdas on the scope stack can capture.
+// A lambda 'L' is capture-ready for a certain variable 'V' if,
+// - its enclosing context is non-dependent
+// - and if the chain of lambdas between L and the lambda in which
+// V is potentially used, call all capture or have captured V.
+static inline int GetScopeIndexOfNearestCaptureReadyLambda(
+ ArrayRef<clang::sema::FunctionScopeInfo*> FunctionScopes,
+ DeclContext *const CurContext, VarDecl *VD) {
+
+ DeclContext *EnclosingDC = CurContext;
+ // If VD is null, we are attempting to capture 'this'
+ const bool IsCapturingThis = !VD;
+ const bool IsCapturingVariable = !IsCapturingThis;
+ int RetIndex = -1;
+ unsigned CurScopeIndex = FunctionScopes.size() - 1;
+ while (!EnclosingDC->isTranslationUnit() &&
+ EnclosingDC->isDependentContext() && isLambdaCallOperator(EnclosingDC)) {
+ RetIndex = CurScopeIndex;
+ clang::sema::LambdaScopeInfo *LSI =
+ cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]);
+ // We have crawled up to an intervening lambda that contains the
+ // variable declaration - so not only does it not need to capture;
+ // none of the enclosing lambdas need to capture it, and since all
+ // other nested lambdas are dependent (otherwise we wouldn't have
+ // arrived here) - we don't yet have a lambda that can capture the
+ // variable.
+ if (IsCapturingVariable && VD->getDeclContext()->Equals(EnclosingDC))
+ return -1;
+ // All intervening lambda call operators have to be able to capture.
+ // If they do not have a default implicit capture, check to see
+ // if the entity has already been explicitly captured.
+ // If even a single dependent enclosing lambda lacks the capability
+ // to ever capture this variable, there is no further enclosing
+ // non-dependent lambda that can capture this variable.
+ if (LSI->ImpCaptureStyle == sema::LambdaScopeInfo::ImpCap_None) {
+ if (IsCapturingVariable && !LSI->isCaptured(VD))
+ return -1;
+ if (IsCapturingThis && !LSI->isCXXThisCaptured())
+ return -1;
+ }
+ EnclosingDC = getLambdaAwareParentOfDeclContext(EnclosingDC);
+ --CurScopeIndex;
+ }
+ // If the enclosingDC is not dependent, then the immediately nested lambda
+ // is capture-ready.
+ if (!EnclosingDC->isDependentContext())
+ return RetIndex;
+ return -1;
+}
+// Given a lambda's call operator and a variable (or null for 'this'),
+// compute the nearest enclosing lambda that is capture-ready (i.e
+// the enclosing context is not dependent, and all intervening lambdas can
+// either implicitly or explicitly capture Var)
+//
+// The approach is as follows, for the entity VD ('this' if null):
+// - start with the current lambda
+// - if it is non-dependent and can capture VD, return it.
+// - if it is dependent and has an implicit or explicit capture, check its parent
+// whether the parent is non-depdendent and all its intervening lambdas
+// can capture, if so return the child.
+// [Note: When we hit a generic lambda specialization, do not climb up
+// the scope stack any further since not only do we not need to,
+// the scope stack will often not be synchronized with any lambdas
+// enclosing the specialized generic lambda]
+//
+// Return the CallOperator of the capturable lambda and set function scope
+// index to the correct index within the function scope stack to correspond
+// to the capturable lambda.
+// If VarDecl *VD is null, we check for 'this' capture.
+CXXMethodDecl* clang::GetInnermostEnclosingCapturableLambda(
+ ArrayRef<sema::FunctionScopeInfo*> FunctionScopes,
+ unsigned &FunctionScopeIndex,
+ DeclContext *const CurContext, VarDecl *VD,
+ Sema &S) {
+
+ const int IndexOfCaptureReadyLambda =
+ GetScopeIndexOfNearestCaptureReadyLambda(FunctionScopes,CurContext, VD);
+ if (IndexOfCaptureReadyLambda == -1) return 0;
+ assert(IndexOfCaptureReadyLambda >= 0);
+ const unsigned IndexOfCaptureReadyLambdaU =
+ static_cast<unsigned>(IndexOfCaptureReadyLambda);
+ sema::LambdaScopeInfo *const CaptureReadyLambdaLSI =
+ cast<sema::LambdaScopeInfo>(FunctionScopes[IndexOfCaptureReadyLambdaU]);
+ // If VD is null, we are attempting to capture 'this'
+ const bool IsCapturingThis = !VD;
+ const bool IsCapturingVariable = !IsCapturingThis;
+
+ if (IsCapturingVariable) {
+ // Now check to see if this lambda can truly capture, and also
+ // if all enclosing lambdas of this lambda allow this capture.
+ QualType CaptureType, DeclRefType;
+ const bool CanCaptureVariable = !S.tryCaptureVariable(VD,
+ /*ExprVarIsUsedInLoc*/SourceLocation(), clang::Sema::TryCapture_Implicit,
+ /*EllipsisLoc*/ SourceLocation(),
+ /*BuildAndDiagnose*/false, CaptureType, DeclRefType,
+ &IndexOfCaptureReadyLambdaU);
+ if (!CanCaptureVariable) return 0;
+ } else {
+ const bool CanCaptureThis = !S.CheckCXXThisCapture(
+ CaptureReadyLambdaLSI->PotentialThisCaptureLocation, false, false,
+ &IndexOfCaptureReadyLambdaU);
+ if (!CanCaptureThis) return 0;
+ } // end 'this' capture test
+ FunctionScopeIndex = IndexOfCaptureReadyLambdaU;
+ return CaptureReadyLambdaLSI->CallOperator;
+}
+
+static inline TemplateParameterList *
+getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
+ if (LSI->GLTemplateParameterList)
+ return LSI->GLTemplateParameterList;
+
+ if (LSI->AutoTemplateParams.size()) {
+ SourceRange IntroRange = LSI->IntroducerRange;
+ SourceLocation LAngleLoc = IntroRange.getBegin();
+ SourceLocation RAngleLoc = IntroRange.getEnd();
+ LSI->GLTemplateParameterList = TemplateParameterList::Create(
+ SemaRef.Context,
+ /*Template kw loc*/SourceLocation(),
+ LAngleLoc,
+ (NamedDecl**)LSI->AutoTemplateParams.data(),
+ LSI->AutoTemplateParams.size(), RAngleLoc);
+ }
+ return LSI->GLTemplateParameterList;
+}
+
+
+
CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
- bool KnownDependent) {
+ bool KnownDependent,
+ LambdaCaptureDefault CaptureDefault) {
DeclContext *DC = CurContext;
while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
DC = DC->getParent();
-
+ bool IsGenericLambda = getGenericLambdaTemplateParameterList(getCurLambda(),
+ *this);
// Start constructing the lambda class.
CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, Info,
IntroducerRange.getBegin(),
- KnownDependent);
+ KnownDependent,
+ IsGenericLambda,
+ CaptureDefault);
DC->addDecl(Class);
return Class;
@@ -51,55 +187,12 @@ static bool isInInlineFunction(const DeclContext *DC) {
return false;
}
-CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
- SourceRange IntroducerRange,
- TypeSourceInfo *MethodType,
- SourceLocation EndLoc,
- ArrayRef<ParmVarDecl *> Params) {
- // C++11 [expr.prim.lambda]p5:
- // The closure type for a lambda-expression has a public inline function
- // call operator (13.5.4) whose parameters and return type are described by
- // the lambda-expression's parameter-declaration-clause and
- // trailing-return-type respectively.
- DeclarationName MethodName
- = Context.DeclarationNames.getCXXOperatorName(OO_Call);
- DeclarationNameLoc MethodNameLoc;
- MethodNameLoc.CXXOperatorName.BeginOpNameLoc
- = IntroducerRange.getBegin().getRawEncoding();
- MethodNameLoc.CXXOperatorName.EndOpNameLoc
- = IntroducerRange.getEnd().getRawEncoding();
- CXXMethodDecl *Method
- = CXXMethodDecl::Create(Context, Class, EndLoc,
- DeclarationNameInfo(MethodName,
- IntroducerRange.getBegin(),
- MethodNameLoc),
- MethodType->getType(), MethodType,
- SC_None,
- /*isInline=*/true,
- /*isConstExpr=*/false,
- EndLoc);
- Method->setAccess(AS_public);
-
- // Temporarily set the lexical declaration context to the current
- // context, so that the Scope stack matches the lexical nesting.
- Method->setLexicalDeclContext(CurContext);
-
- // Add parameters.
- if (!Params.empty()) {
- Method->setParams(Params);
- CheckParmsForFunctionDef(const_cast<ParmVarDecl **>(Params.begin()),
- const_cast<ParmVarDecl **>(Params.end()),
- /*CheckParameterNames=*/false);
-
- for (CXXMethodDecl::param_iterator P = Method->param_begin(),
- PEnd = Method->param_end();
- P != PEnd; ++P)
- (*P)->setOwningFunction(Method);
- }
-
- // Allocate a mangling number for this lambda expression, if the ABI
- // requires one.
- Decl *ContextDecl = ExprEvalContexts.back().LambdaContextDecl;
+MangleNumberingContext *
+Sema::getCurrentMangleNumberContext(const DeclContext *DC,
+ Decl *&ManglingContextDecl) {
+ // Compute the context for allocating mangling numbers in the current
+ // expression, if the ABI requires them.
+ ManglingContextDecl = ExprEvalContexts.back().ManglingContextDecl;
enum ContextKind {
Normal,
@@ -111,16 +204,16 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
// Default arguments of member function parameters that appear in a class
// definition, as well as the initializers of data members, receive special
// treatment. Identify them.
- if (ContextDecl) {
- if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) {
+ if (ManglingContextDecl) {
+ if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ManglingContextDecl)) {
if (const DeclContext *LexicalDC
= Param->getDeclContext()->getLexicalParent())
if (LexicalDC->isRecord())
Kind = DefaultArgument;
- } else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) {
+ } else if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl)) {
if (Var->getDeclContext()->isRecord())
Kind = StaticDataMember;
- } else if (isa<FieldDecl>(ContextDecl)) {
+ } else if (isa<FieldDecl>(ManglingContextDecl)) {
Kind = DataMember;
}
}
@@ -130,57 +223,147 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
// types in different translation units to "correspond":
bool IsInNonspecializedTemplate =
!ActiveTemplateInstantiations.empty() || CurContext->isDependentContext();
- unsigned ManglingNumber;
switch (Kind) {
case Normal:
// -- the bodies of non-exported nonspecialized template functions
// -- the bodies of inline functions
if ((IsInNonspecializedTemplate &&
- !(ContextDecl && isa<ParmVarDecl>(ContextDecl))) ||
- isInInlineFunction(CurContext))
- ManglingNumber = Context.getLambdaManglingNumber(Method);
- else
- ManglingNumber = 0;
+ !(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl))) ||
+ isInInlineFunction(CurContext)) {
+ ManglingContextDecl = 0;
+ return &Context.getManglingNumberContext(DC);
+ }
- // There is no special context for this lambda.
- ContextDecl = 0;
- break;
+ ManglingContextDecl = 0;
+ return 0;
case StaticDataMember:
// -- the initializers of nonspecialized static members of template classes
if (!IsInNonspecializedTemplate) {
- ManglingNumber = 0;
- ContextDecl = 0;
- break;
+ ManglingContextDecl = 0;
+ return 0;
}
- // Fall through to assign a mangling number.
+ // Fall through to get the current context.
case DataMember:
// -- the in-class initializers of class members
case DefaultArgument:
// -- default arguments appearing in class definitions
- ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
- .getManglingNumber(Method);
- break;
+ return &ExprEvalContexts.back().getMangleNumberingContext(Context);
}
- Class->setLambdaMangling(ManglingNumber, ContextDecl);
+ llvm_unreachable("unexpected context");
+}
+
+MangleNumberingContext &
+Sema::ExpressionEvaluationContextRecord::getMangleNumberingContext(
+ ASTContext &Ctx) {
+ assert(ManglingContextDecl && "Need to have a context declaration");
+ if (!MangleNumbering)
+ MangleNumbering = Ctx.createMangleNumberingContext();
+ return *MangleNumbering;
+}
+
+CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
+ SourceRange IntroducerRange,
+ TypeSourceInfo *MethodTypeInfo,
+ SourceLocation EndLoc,
+ ArrayRef<ParmVarDecl *> Params) {
+ QualType MethodType = MethodTypeInfo->getType();
+ TemplateParameterList *TemplateParams =
+ getGenericLambdaTemplateParameterList(getCurLambda(), *this);
+ // If a lambda appears in a dependent context or is a generic lambda (has
+ // template parameters) and has an 'auto' return type, deduce it to a
+ // dependent type.
+ if (Class->isDependentContext() || TemplateParams) {
+ const FunctionProtoType *FPT = MethodType->castAs<FunctionProtoType>();
+ QualType Result = FPT->getResultType();
+ if (Result->isUndeducedType()) {
+ Result = SubstAutoType(Result, Context.DependentTy);
+ MethodType = Context.getFunctionType(Result, FPT->getArgTypes(),
+ FPT->getExtProtoInfo());
+ }
+ }
+
+ // C++11 [expr.prim.lambda]p5:
+ // The closure type for a lambda-expression has a public inline function
+ // call operator (13.5.4) whose parameters and return type are described by
+ // the lambda-expression's parameter-declaration-clause and
+ // trailing-return-type respectively.
+ DeclarationName MethodName
+ = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+ DeclarationNameLoc MethodNameLoc;
+ MethodNameLoc.CXXOperatorName.BeginOpNameLoc
+ = IntroducerRange.getBegin().getRawEncoding();
+ MethodNameLoc.CXXOperatorName.EndOpNameLoc
+ = IntroducerRange.getEnd().getRawEncoding();
+ CXXMethodDecl *Method
+ = CXXMethodDecl::Create(Context, Class, EndLoc,
+ DeclarationNameInfo(MethodName,
+ IntroducerRange.getBegin(),
+ MethodNameLoc),
+ MethodType, MethodTypeInfo,
+ SC_None,
+ /*isInline=*/true,
+ /*isConstExpr=*/false,
+ EndLoc);
+ Method->setAccess(AS_public);
+
+ // Temporarily set the lexical declaration context to the current
+ // context, so that the Scope stack matches the lexical nesting.
+ Method->setLexicalDeclContext(CurContext);
+ // Create a function template if we have a template parameter list
+ FunctionTemplateDecl *const TemplateMethod = TemplateParams ?
+ FunctionTemplateDecl::Create(Context, Class,
+ Method->getLocation(), MethodName,
+ TemplateParams,
+ Method) : 0;
+ if (TemplateMethod) {
+ TemplateMethod->setLexicalDeclContext(CurContext);
+ TemplateMethod->setAccess(AS_public);
+ Method->setDescribedFunctionTemplate(TemplateMethod);
+ }
+
+ // Add parameters.
+ if (!Params.empty()) {
+ Method->setParams(Params);
+ CheckParmsForFunctionDef(const_cast<ParmVarDecl **>(Params.begin()),
+ const_cast<ParmVarDecl **>(Params.end()),
+ /*CheckParameterNames=*/false);
+
+ for (CXXMethodDecl::param_iterator P = Method->param_begin(),
+ PEnd = Method->param_end();
+ P != PEnd; ++P)
+ (*P)->setOwningFunction(Method);
+ }
+
+ Decl *ManglingContextDecl;
+ if (MangleNumberingContext *MCtx =
+ getCurrentMangleNumberContext(Class->getDeclContext(),
+ ManglingContextDecl)) {
+ unsigned ManglingNumber = MCtx->getManglingNumber(Method);
+ Class->setLambdaMangling(ManglingNumber, ManglingContextDecl);
+ }
return Method;
}
-LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator,
+void Sema::buildLambdaScope(LambdaScopeInfo *LSI,
+ CXXMethodDecl *CallOperator,
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc,
bool ExplicitParams,
bool ExplicitResultType,
bool Mutable) {
- PushLambdaScope(CallOperator->getParent(), CallOperator);
- LambdaScopeInfo *LSI = getCurLambda();
+ LSI->CallOperator = CallOperator;
+ CXXRecordDecl *LambdaClass = CallOperator->getParent();
+ LSI->Lambda = LambdaClass;
if (CaptureDefault == LCD_ByCopy)
LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
else if (CaptureDefault == LCD_ByRef)
LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
+ LSI->CaptureDefaultLoc = CaptureDefaultLoc;
LSI->IntroducerRange = IntroducerRange;
LSI->ExplicitParams = ExplicitParams;
LSI->Mutable = Mutable;
@@ -193,16 +376,11 @@ LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator,
if (RequireCompleteType(CallOperator->getLocStart(), LSI->ReturnType,
diag::err_lambda_incomplete_result)) {
// Do nothing.
- } else if (LSI->ReturnType->isObjCObjectOrInterfaceType()) {
- Diag(CallOperator->getLocStart(), diag::err_lambda_objc_object_result)
- << LSI->ReturnType;
}
}
} else {
LSI->HasImplicitReturnType = true;
}
-
- return LSI;
}
void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
@@ -275,11 +453,12 @@ static EnumDecl *findEnumForBlockReturn(Expr *E) {
// - it is an implicit integral conversion applied to an
// enumerator-like expression of type T or
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- // We can only see integral conversions in valid enumerator-like
- // expressions.
+ // We can sometimes see integral conversions in valid
+ // enumerator-like expressions.
if (ICE->getCastKind() == CK_IntegralCast)
return findEnumForBlockReturn(ICE->getSubExpr());
- return 0;
+
+ // Otherwise, just rely on the type.
}
// - it is an expression of that formal enum type.
@@ -351,6 +530,8 @@ static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns,
void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
assert(CSI.HasImplicitReturnType);
+ // If it was ever a placeholder, it had to been deduced to DependentTy.
+ assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType());
// C++ Core Issue #975, proposed resolution:
// If a lambda-expression does not include a trailing-return-type,
@@ -428,16 +609,160 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
}
}
+QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc,
+ bool ByRef,
+ IdentifierInfo *Id,
+ Expr *&Init) {
+
+ // We do not need to distinguish between direct-list-initialization
+ // and copy-list-initialization here, because we will always deduce
+ // std::initializer_list<T>, and direct- and copy-list-initialization
+ // always behave the same for such a type.
+ // FIXME: We should model whether an '=' was present.
+ const bool IsDirectInit = isa<ParenListExpr>(Init) || isa<InitListExpr>(Init);
+
+ // Create an 'auto' or 'auto&' TypeSourceInfo that we can use to
+ // deduce against.
+ QualType DeductType = Context.getAutoDeductType();
+ TypeLocBuilder TLB;
+ TLB.pushTypeSpec(DeductType).setNameLoc(Loc);
+ if (ByRef) {
+ DeductType = BuildReferenceType(DeductType, true, Loc, Id);
+ assert(!DeductType.isNull() && "can't build reference to auto");
+ TLB.push<ReferenceTypeLoc>(DeductType).setSigilLoc(Loc);
+ }
+ TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType);
+
+ // Are we a non-list direct initialization?
+ ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
+
+ Expr *DeduceInit = Init;
+ // Initializer could be a C++ direct-initializer. Deduction only works if it
+ // contains exactly one expression.
+ if (CXXDirectInit) {
+ if (CXXDirectInit->getNumExprs() == 0) {
+ Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_no_expression)
+ << DeclarationName(Id) << TSI->getType() << Loc;
+ return QualType();
+ } else if (CXXDirectInit->getNumExprs() > 1) {
+ Diag(CXXDirectInit->getExpr(1)->getLocStart(),
+ diag::err_init_capture_multiple_expressions)
+ << DeclarationName(Id) << TSI->getType() << Loc;
+ return QualType();
+ } else {
+ DeduceInit = CXXDirectInit->getExpr(0);
+ }
+ }
+
+ // Now deduce against the initialization expression and store the deduced
+ // type below.
+ QualType DeducedType;
+ if (DeduceAutoType(TSI, DeduceInit, DeducedType) == DAR_Failed) {
+ if (isa<InitListExpr>(Init))
+ Diag(Loc, diag::err_init_capture_deduction_failure_from_init_list)
+ << DeclarationName(Id)
+ << (DeduceInit->getType().isNull() ? TSI->getType()
+ : DeduceInit->getType())
+ << DeduceInit->getSourceRange();
+ else
+ Diag(Loc, diag::err_init_capture_deduction_failure)
+ << DeclarationName(Id) << TSI->getType()
+ << (DeduceInit->getType().isNull() ? TSI->getType()
+ : DeduceInit->getType())
+ << DeduceInit->getSourceRange();
+ }
+ if (DeducedType.isNull())
+ return QualType();
+
+ // Perform initialization analysis and ensure any implicit conversions
+ // (such as lvalue-to-rvalue) are enforced.
+ InitializedEntity Entity =
+ InitializedEntity::InitializeLambdaCapture(Id, DeducedType, Loc);
+ InitializationKind Kind =
+ IsDirectInit
+ ? (CXXDirectInit ? InitializationKind::CreateDirect(
+ Loc, Init->getLocStart(), Init->getLocEnd())
+ : InitializationKind::CreateDirectList(Loc))
+ : InitializationKind::CreateCopy(Loc, Init->getLocStart());
+
+ MultiExprArg Args = Init;
+ if (CXXDirectInit)
+ Args =
+ MultiExprArg(CXXDirectInit->getExprs(), CXXDirectInit->getNumExprs());
+ QualType DclT;
+ InitializationSequence InitSeq(*this, Entity, Kind, Args);
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT);
+
+ if (Result.isInvalid())
+ return QualType();
+ Init = Result.takeAs<Expr>();
+
+ // The init-capture initialization is a full-expression that must be
+ // processed as one before we enter the declcontext of the lambda's
+ // call-operator.
+ Result = ActOnFinishFullExpr(Init, Loc, /*DiscardedValue*/ false,
+ /*IsConstexpr*/ false,
+ /*IsLambdaInitCaptureInitalizer*/ true);
+ if (Result.isInvalid())
+ return QualType();
+
+ Init = Result.takeAs<Expr>();
+ return DeducedType;
+}
+
+VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc,
+ QualType InitCaptureType, IdentifierInfo *Id, Expr *Init) {
+
+ TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(InitCaptureType,
+ Loc);
+ // Create a dummy variable representing the init-capture. This is not actually
+ // used as a variable, and only exists as a way to name and refer to the
+ // init-capture.
+ // FIXME: Pass in separate source locations for '&' and identifier.
+ VarDecl *NewVD = VarDecl::Create(Context, CurContext, Loc,
+ Loc, Id, InitCaptureType, TSI, SC_Auto);
+ NewVD->setInitCapture(true);
+ NewVD->setReferenced(true);
+ NewVD->markUsed(Context);
+ NewVD->setInit(Init);
+ return NewVD;
+
+}
+
+FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) {
+ FieldDecl *Field = FieldDecl::Create(
+ Context, LSI->Lambda, Var->getLocation(), Var->getLocation(),
+ 0, Var->getType(), Var->getTypeSourceInfo(), 0, false, ICIS_NoInit);
+ Field->setImplicit(true);
+ Field->setAccess(AS_private);
+ LSI->Lambda->addDecl(Field);
+
+ LSI->addCapture(Var, /*isBlock*/false, Var->getType()->isReferenceType(),
+ /*isNested*/false, Var->getLocation(), SourceLocation(),
+ Var->getType(), Var->getInit());
+ return Field;
+}
+
void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
- Declarator &ParamInfo,
- Scope *CurScope) {
+ Declarator &ParamInfo, Scope *CurScope) {
// Determine if we're within a context where we know that the lambda will
// be dependent, because there are template parameters in scope.
bool KnownDependent = false;
- if (Scope *TmplScope = CurScope->getTemplateParamParent())
- if (!TmplScope->decl_empty())
+ LambdaScopeInfo *const LSI = getCurLambda();
+ assert(LSI && "LambdaScopeInfo should be on stack!");
+ TemplateParameterList *TemplateParams =
+ getGenericLambdaTemplateParameterList(LSI, *this);
+
+ if (Scope *TmplScope = CurScope->getTemplateParamParent()) {
+ // Since we have our own TemplateParams, so check if an outer scope
+ // has template params, only then are we in a dependent scope.
+ if (TemplateParams) {
+ TmplScope = TmplScope->getParent();
+ TmplScope = TmplScope ? TmplScope->getTemplateParamParent() : 0;
+ }
+ if (TmplScope && !TmplScope->decl_empty())
KnownDependent = true;
-
+ }
// Determine the signature of the call operator.
TypeSourceInfo *MethodTyInfo;
bool ExplicitParams = true;
@@ -449,11 +774,21 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// C++11 [expr.prim.lambda]p4:
// If a lambda-expression does not include a lambda-declarator, it is as
// if the lambda-declarator were ().
- FunctionProtoType::ExtProtoInfo EPI;
+ FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention(
+ /*IsVariadic=*/false, /*IsCXXMethod=*/true));
EPI.HasTrailingReturn = true;
EPI.TypeQuals |= DeclSpec::TQ_const;
- QualType MethodTy = Context.getFunctionType(Context.DependentTy, None,
- EPI);
+ // C++1y [expr.prim.lambda]:
+ // The lambda return type is 'auto', which is replaced by the
+ // trailing-return type if provided and/or deduced from 'return'
+ // statements
+ // We don't do this before C++1y, because we don't support deduced return
+ // types there.
+ QualType DefaultTypeForNoTrailingReturn =
+ getLangOpts().CPlusPlus1y ? Context.getAutoDeductType()
+ : Context.DependentTy;
+ QualType MethodTy =
+ Context.getFunctionType(DefaultTypeForNoTrailingReturn, None, EPI);
MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
ExplicitParams = false;
ExplicitResultType = false;
@@ -462,21 +797,19 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
assert(ParamInfo.isFunctionDeclarator() &&
"lambda-declarator is a function");
DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();
-
+
// C++11 [expr.prim.lambda]p5:
// This function call operator is declared const (9.3.1) if and only if
// the lambda-expression's parameter-declaration-clause is not followed
// by mutable. It is neither virtual nor declared volatile. [...]
if (!FTI.hasMutableQualifier())
FTI.TypeQuals |= DeclSpec::TQ_const;
-
+
MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
assert(MethodTyInfo && "no type from lambda-declarator");
EndLoc = ParamInfo.getSourceRange().getEnd();
-
- ExplicitResultType
- = MethodTyInfo->getType()->getAs<FunctionType>()->getResultType()
- != Context.DependentTy;
+
+ ExplicitResultType = FTI.hasTrailingReturnType();
if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
@@ -494,11 +827,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
}
CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo,
- KnownDependent);
+ KnownDependent, Intro.Default);
CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
MethodTyInfo, EndLoc, Params);
-
if (ExplicitParams)
CheckCXXDefaultArguments(Method);
@@ -508,19 +840,24 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// Introduce the function call operator as the current declaration context.
PushDeclContext(CurScope, Method);
- // Introduce the lambda scope.
- LambdaScopeInfo *LSI
- = enterLambdaScope(Method, Intro.Range, Intro.Default, ExplicitParams,
+ // Build the lambda scope.
+ buildLambdaScope(LSI, Method,
+ Intro.Range,
+ Intro.Default, Intro.DefaultLoc,
+ ExplicitParams,
ExplicitResultType,
!Method->isConst());
-
+
+ // Distinct capture names, for diagnostics.
+ llvm::SmallSet<IdentifierInfo*, 8> CaptureNames;
+
// Handle explicit captures.
SourceLocation PrevCaptureLoc
= Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc;
- for (SmallVector<LambdaCapture, 4>::const_iterator
- C = Intro.Captures.begin(),
- E = Intro.Captures.end();
- C != E;
+ for (SmallVectorImpl<LambdaCapture>::const_iterator
+ C = Intro.Captures.begin(),
+ E = Intro.Captures.end();
+ C != E;
PrevCaptureLoc = C->Loc, ++C) {
if (C->Kind == LCK_This) {
// C++11 [expr.prim.lambda]p8:
@@ -560,44 +897,89 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
assert(C->Id && "missing identifier for capture");
- // C++11 [expr.prim.lambda]p8:
- // If a lambda-capture includes a capture-default that is &, the
- // identifiers in the lambda-capture shall not be preceded by &.
- // If a lambda-capture includes a capture-default that is =, [...]
- // each identifier it contains shall be preceded by &.
- if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
- Diag(C->Loc, diag::err_reference_capture_with_reference_default)
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
- continue;
- } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
- Diag(C->Loc, diag::err_copy_capture_with_copy_default)
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ if (C->Init.isInvalid())
continue;
+
+ VarDecl *Var = 0;
+ if (C->Init.isUsable()) {
+ Diag(C->Loc, getLangOpts().CPlusPlus1y
+ ? diag::warn_cxx11_compat_init_capture
+ : diag::ext_init_capture);
+
+ if (C->Init.get()->containsUnexpandedParameterPack())
+ ContainsUnexpandedParameterPack = true;
+ // If the initializer expression is usable, but the InitCaptureType
+ // is not, then an error has occurred - so ignore the capture for now.
+ // for e.g., [n{0}] { }; <-- if no <initializer_list> is included.
+ // FIXME: we should create the init capture variable and mark it invalid
+ // in this case.
+ if (C->InitCaptureType.get().isNull())
+ continue;
+ Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(),
+ C->Id, C->Init.take());
+ // C++1y [expr.prim.lambda]p11:
+ // An init-capture behaves as if it declares and explicitly
+ // captures a variable [...] whose declarative region is the
+ // lambda-expression's compound-statement
+ if (Var)
+ PushOnScopeChains(Var, CurScope, false);
+ } else {
+ // C++11 [expr.prim.lambda]p8:
+ // If a lambda-capture includes a capture-default that is &, the
+ // identifiers in the lambda-capture shall not be preceded by &.
+ // If a lambda-capture includes a capture-default that is =, [...]
+ // each identifier it contains shall be preceded by &.
+ if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
+ Diag(C->Loc, diag::err_reference_capture_with_reference_default)
+ << FixItHint::CreateRemoval(
+ SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ continue;
+ } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
+ Diag(C->Loc, diag::err_copy_capture_with_copy_default)
+ << FixItHint::CreateRemoval(
+ SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ continue;
+ }
+
+ // C++11 [expr.prim.lambda]p10:
+ // The identifiers in a capture-list are looked up using the usual
+ // rules for unqualified name lookup (3.4.1)
+ DeclarationNameInfo Name(C->Id, C->Loc);
+ LookupResult R(*this, Name, LookupOrdinaryName);
+ LookupName(R, CurScope);
+ if (R.isAmbiguous())
+ continue;
+ if (R.empty()) {
+ // FIXME: Disable corrections that would add qualification?
+ CXXScopeSpec ScopeSpec;
+ DeclFilterCCC<VarDecl> Validator;
+ if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator))
+ continue;
+ }
+
+ Var = R.getAsSingle<VarDecl>();
}
- DeclarationNameInfo Name(C->Id, C->Loc);
- LookupResult R(*this, Name, LookupOrdinaryName);
- LookupName(R, CurScope);
- if (R.isAmbiguous())
+ // C++11 [expr.prim.lambda]p8:
+ // An identifier or this shall not appear more than once in a
+ // lambda-capture.
+ if (!CaptureNames.insert(C->Id)) {
+ if (Var && LSI->isCaptured(Var)) {
+ Diag(C->Loc, diag::err_capture_more_than_once)
+ << C->Id << SourceRange(LSI->getCapture(Var).getLocation())
+ << FixItHint::CreateRemoval(
+ SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+ } else
+ // Previous capture captured something different (one or both was
+ // an init-cpature): no fixit.
+ Diag(C->Loc, diag::err_capture_more_than_once) << C->Id;
continue;
- if (R.empty()) {
- // FIXME: Disable corrections that would add qualification?
- CXXScopeSpec ScopeSpec;
- DeclFilterCCC<VarDecl> Validator;
- if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator))
- continue;
}
// C++11 [expr.prim.lambda]p10:
- // The identifiers in a capture-list are looked up using the usual rules
- // for unqualified name lookup (3.4.1); each such lookup shall find a
- // variable with automatic storage duration declared in the reaching
- // scope of the local lambda expression.
- //
+ // [...] each such lookup shall find a variable with automatic storage
+ // duration declared in the reaching scope of the local lambda expression.
// Note that the 'reaching scope' check happens in tryCaptureVariable().
- VarDecl *Var = R.getAsSingle<VarDecl>();
if (!Var) {
Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id;
continue;
@@ -613,18 +995,6 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
continue;
}
- // C++11 [expr.prim.lambda]p8:
- // An identifier or this shall not appear more than once in a
- // lambda-capture.
- if (LSI->isCaptured(Var)) {
- Diag(C->Loc, diag::err_capture_more_than_once)
- << C->Id
- << SourceRange(LSI->getCapture(Var).getLocation())
- << FixItHint::CreateRemoval(
- SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
- continue;
- }
-
// C++11 [expr.prim.lambda]p23:
// A capture followed by an ellipsis is a pack expansion (14.5.3).
SourceLocation EllipsisLoc;
@@ -640,10 +1010,14 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
} else if (Var->isParameterPack()) {
ContainsUnexpandedParameterPack = true;
}
-
- TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
- TryCapture_ExplicitByVal;
- tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
+
+ if (C->Init.isUsable()) {
+ buildInitCaptureField(LSI, Var);
+ } else {
+ TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
+ TryCapture_ExplicitByVal;
+ tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
+ }
}
finishLambdaExplicitCaptures(LSI);
@@ -689,72 +1063,173 @@ static void addFunctionPointerConversion(Sema &S,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
// Add the conversion to function pointer.
- const FunctionProtoType *Proto
- = CallOperator->getType()->getAs<FunctionProtoType>();
- QualType FunctionPtrTy;
- QualType FunctionTy;
+ const FunctionProtoType *CallOpProto =
+ CallOperator->getType()->getAs<FunctionProtoType>();
+ const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
+ CallOpProto->getExtProtoInfo();
+ QualType PtrToFunctionTy;
+ QualType InvokerFunctionTy;
{
- FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
- ExtInfo.TypeQuals = 0;
- FunctionTy =
- S.Context.getFunctionType(Proto->getResultType(),
- ArrayRef<QualType>(Proto->arg_type_begin(),
- Proto->getNumArgs()),
- ExtInfo);
- FunctionPtrTy = S.Context.getPointerType(FunctionTy);
+ FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo;
+ CallingConv CC = S.Context.getDefaultCallingConvention(
+ CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
+ InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
+ InvokerExtInfo.TypeQuals = 0;
+ assert(InvokerExtInfo.RefQualifier == RQ_None &&
+ "Lambda's call operator should not have a reference qualifier");
+ InvokerFunctionTy = S.Context.getFunctionType(CallOpProto->getResultType(),
+ CallOpProto->getArgTypes(), InvokerExtInfo);
+ PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy);
}
-
- FunctionProtoType::ExtProtoInfo ExtInfo;
- ExtInfo.TypeQuals = Qualifiers::Const;
- QualType ConvTy =
- S.Context.getFunctionType(FunctionPtrTy, None, ExtInfo);
-
+
+ // Create the type of the conversion function.
+ FunctionProtoType::ExtProtoInfo ConvExtInfo(
+ S.Context.getDefaultCallingConvention(
+ /*IsVariadic=*/false, /*IsCXXMethod=*/true));
+ // The conversion function is always const.
+ ConvExtInfo.TypeQuals = Qualifiers::Const;
+ QualType ConvTy =
+ S.Context.getFunctionType(PtrToFunctionTy, None, ConvExtInfo);
+
SourceLocation Loc = IntroducerRange.getBegin();
- DeclarationName Name
+ DeclarationName ConversionName
= S.Context.DeclarationNames.getCXXConversionFunctionName(
- S.Context.getCanonicalType(FunctionPtrTy));
- DeclarationNameLoc NameLoc;
- NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(FunctionPtrTy,
- Loc);
+ S.Context.getCanonicalType(PtrToFunctionTy));
+ DeclarationNameLoc ConvNameLoc;
+ // Construct a TypeSourceInfo for the conversion function, and wire
+ // all the parameters appropriately for the FunctionProtoTypeLoc
+ // so that everything works during transformation/instantiation of
+ // generic lambdas.
+ // The main reason for wiring up the parameters of the conversion
+ // function with that of the call operator is so that constructs
+ // like the following work:
+ // auto L = [](auto b) { <-- 1
+ // return [](auto a) -> decltype(a) { <-- 2
+ // return a;
+ // };
+ // };
+ // int (*fp)(int) = L(5);
+ // Because the trailing return type can contain DeclRefExprs that refer
+ // to the original call operator's variables, we hijack the call
+ // operators ParmVarDecls below.
+ TypeSourceInfo *ConvNamePtrToFunctionTSI =
+ S.Context.getTrivialTypeSourceInfo(PtrToFunctionTy, Loc);
+ ConvNameLoc.NamedType.TInfo = ConvNamePtrToFunctionTSI;
+
+ // The conversion function is a conversion to a pointer-to-function.
+ TypeSourceInfo *ConvTSI = S.Context.getTrivialTypeSourceInfo(ConvTy, Loc);
+ FunctionProtoTypeLoc ConvTL =
+ ConvTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
+ // Get the result of the conversion function which is a pointer-to-function.
+ PointerTypeLoc PtrToFunctionTL =
+ ConvTL.getResultLoc().getAs<PointerTypeLoc>();
+ // Do the same for the TypeSourceInfo that is used to name the conversion
+ // operator.
+ PointerTypeLoc ConvNamePtrToFunctionTL =
+ ConvNamePtrToFunctionTSI->getTypeLoc().getAs<PointerTypeLoc>();
+
+ // Get the underlying function types that the conversion function will
+ // be converting to (should match the type of the call operator).
+ FunctionProtoTypeLoc CallOpConvTL =
+ PtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>();
+ FunctionProtoTypeLoc CallOpConvNameTL =
+ ConvNamePtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>();
+
+ // Wire up the FunctionProtoTypeLocs with the call operator's parameters.
+ // These parameter's are essentially used to transform the name and
+ // the type of the conversion operator. By using the same parameters
+ // as the call operator's we don't have to fix any back references that
+ // the trailing return type of the call operator's uses (such as
+ // decltype(some_type<decltype(a)>::type{} + decltype(a){}) etc.)
+ // - we can simply use the return type of the call operator, and
+ // everything should work.
+ SmallVector<ParmVarDecl *, 4> InvokerParams;
+ for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) {
+ ParmVarDecl *From = CallOperator->getParamDecl(I);
+
+ InvokerParams.push_back(ParmVarDecl::Create(S.Context,
+ // Temporarily add to the TU. This is set to the invoker below.
+ S.Context.getTranslationUnitDecl(),
+ From->getLocStart(),
+ From->getLocation(),
+ From->getIdentifier(),
+ From->getType(),
+ From->getTypeSourceInfo(),
+ From->getStorageClass(),
+ /*DefaultArg=*/0));
+ CallOpConvTL.setArg(I, From);
+ CallOpConvNameTL.setArg(I, From);
+ }
+
CXXConversionDecl *Conversion
= CXXConversionDecl::Create(S.Context, Class, Loc,
- DeclarationNameInfo(Name, Loc, NameLoc),
+ DeclarationNameInfo(ConversionName,
+ Loc, ConvNameLoc),
ConvTy,
- S.Context.getTrivialTypeSourceInfo(ConvTy,
- Loc),
- /*isInline=*/false, /*isExplicit=*/false,
+ ConvTSI,
+ /*isInline=*/true, /*isExplicit=*/false,
/*isConstexpr=*/false,
CallOperator->getBody()->getLocEnd());
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
- Class->addDecl(Conversion);
-
- // Add a non-static member function "__invoke" that will be the result of
- // the conversion.
- Name = &S.Context.Idents.get("__invoke");
+
+ if (Class->isGenericLambda()) {
+ // Create a template version of the conversion operator, using the template
+ // parameter list of the function call operator.
+ FunctionTemplateDecl *TemplateCallOperator =
+ CallOperator->getDescribedFunctionTemplate();
+ FunctionTemplateDecl *ConversionTemplate =
+ FunctionTemplateDecl::Create(S.Context, Class,
+ Loc, ConversionName,
+ TemplateCallOperator->getTemplateParameters(),
+ Conversion);
+ ConversionTemplate->setAccess(AS_public);
+ ConversionTemplate->setImplicit(true);
+ Conversion->setDescribedFunctionTemplate(ConversionTemplate);
+ Class->addDecl(ConversionTemplate);
+ } else
+ Class->addDecl(Conversion);
+ // Add a non-static member function that will be the result of
+ // the conversion with a certain unique ID.
+ DeclarationName InvokerName = &S.Context.Idents.get(
+ getLambdaStaticInvokerName());
+ // FIXME: Instead of passing in the CallOperator->getTypeSourceInfo()
+ // we should get a prebuilt TrivialTypeSourceInfo from Context
+ // using FunctionTy & Loc and get its TypeLoc as a FunctionProtoTypeLoc
+ // then rewire the parameters accordingly, by hoisting up the InvokeParams
+ // loop below and then use its Params to set Invoke->setParams(...) below.
+ // This would avoid the 'const' qualifier of the calloperator from
+ // contaminating the type of the invoker, which is currently adjusted
+ // in SemaTemplateDeduction.cpp:DeduceTemplateArguments. Fixing the
+ // trailing return type of the invoker would require a visitor to rebuild
+ // the trailing return type and adjusting all back DeclRefExpr's to refer
+ // to the new static invoker parameters - not the call operator's.
CXXMethodDecl *Invoke
= CXXMethodDecl::Create(S.Context, Class, Loc,
- DeclarationNameInfo(Name, Loc), FunctionTy,
- CallOperator->getTypeSourceInfo(),
+ DeclarationNameInfo(InvokerName, Loc),
+ InvokerFunctionTy,
+ CallOperator->getTypeSourceInfo(),
SC_Static, /*IsInline=*/true,
/*IsConstexpr=*/false,
CallOperator->getBody()->getLocEnd());
- SmallVector<ParmVarDecl *, 4> InvokeParams;
- for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) {
- ParmVarDecl *From = CallOperator->getParamDecl(I);
- InvokeParams.push_back(ParmVarDecl::Create(S.Context, Invoke,
- From->getLocStart(),
- From->getLocation(),
- From->getIdentifier(),
- From->getType(),
- From->getTypeSourceInfo(),
- From->getStorageClass(),
- /*DefaultArg=*/0));
- }
- Invoke->setParams(InvokeParams);
+ for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I)
+ InvokerParams[I]->setOwningFunction(Invoke);
+ Invoke->setParams(InvokerParams);
Invoke->setAccess(AS_private);
Invoke->setImplicit(true);
- Class->addDecl(Invoke);
+ if (Class->isGenericLambda()) {
+ FunctionTemplateDecl *TemplateCallOperator =
+ CallOperator->getDescribedFunctionTemplate();
+ FunctionTemplateDecl *StaticInvokerTemplate = FunctionTemplateDecl::Create(
+ S.Context, Class, Loc, InvokerName,
+ TemplateCallOperator->getTemplateParameters(),
+ Invoke);
+ StaticInvokerTemplate->setAccess(AS_private);
+ StaticInvokerTemplate->setImplicit(true);
+ Invoke->setDescribedFunctionTemplate(StaticInvokerTemplate);
+ Class->addDecl(StaticInvokerTemplate);
+ } else
+ Class->addDecl(Invoke);
}
/// \brief Add a lambda's conversion to block pointer.
@@ -768,15 +1243,13 @@ static void addBlockPointerConversion(Sema &S,
{
FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
ExtInfo.TypeQuals = 0;
- QualType FunctionTy
- = S.Context.getFunctionType(Proto->getResultType(),
- ArrayRef<QualType>(Proto->arg_type_begin(),
- Proto->getNumArgs()),
- ExtInfo);
+ QualType FunctionTy = S.Context.getFunctionType(
+ Proto->getResultType(), Proto->getArgTypes(), ExtInfo);
BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);
}
-
- FunctionProtoType::ExtProtoInfo ExtInfo;
+
+ FunctionProtoType::ExtProtoInfo ExtInfo(S.Context.getDefaultCallingConvention(
+ /*IsVariadic=*/false, /*IsCXXMethod=*/true));
ExtInfo.TypeQuals = Qualifiers::Const;
QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ExtInfo);
@@ -791,7 +1264,7 @@ static void addBlockPointerConversion(Sema &S,
DeclarationNameInfo(Name, Loc, NameLoc),
ConvTy,
S.Context.getTrivialTypeSourceInfo(ConvTy, Loc),
- /*isInline=*/false, /*isExplicit=*/false,
+ /*isInline=*/true, /*isExplicit=*/false,
/*isConstexpr=*/false,
CallOperator->getBody()->getLocEnd());
Conversion->setAccess(AS_public);
@@ -806,6 +1279,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
SmallVector<LambdaExpr::Capture, 4> Captures;
SmallVector<Expr *, 4> CaptureInits;
LambdaCaptureDefault CaptureDefault;
+ SourceLocation CaptureDefaultLoc;
CXXRecordDecl *Class;
CXXMethodDecl *CallOperator;
SourceRange IntroducerRange;
@@ -848,7 +1322,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef;
Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit,
Kind, Var, From.getEllipsisLoc()));
- CaptureInits.push_back(From.getCopyExpr());
+ CaptureInits.push_back(From.getInitExpr());
}
switch (LSI->ImpCaptureStyle) {
@@ -869,13 +1343,18 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
llvm_unreachable("block capture in lambda");
break;
}
+ CaptureDefaultLoc = LSI->CaptureDefaultLoc;
// C++11 [expr.prim.lambda]p4:
// If a lambda-expression does not include a
// trailing-return-type, it is as if the trailing-return-type
// denotes the following type:
+ //
+ // Skip for C++1y return type deduction semantics which uses
+ // different machinery.
+ // FIXME: Refactor and Merge the return type deduction machinery.
// FIXME: Assumes current resolution to core issue 975.
- if (LSI->HasImplicitReturnType) {
+ if (LSI->HasImplicitReturnType && !getLangOpts().CPlusPlus1y) {
deduceClosureReturnType(*LSI);
// - if there are no return statements in the
@@ -889,20 +1368,23 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
// Create a function type with the inferred return type.
const FunctionProtoType *Proto
= CallOperator->getType()->getAs<FunctionProtoType>();
- QualType FunctionTy
- = Context.getFunctionType(LSI->ReturnType,
- ArrayRef<QualType>(Proto->arg_type_begin(),
- Proto->getNumArgs()),
- Proto->getExtProtoInfo());
+ QualType FunctionTy = Context.getFunctionType(
+ LSI->ReturnType, Proto->getArgTypes(), Proto->getExtProtoInfo());
CallOperator->setType(FunctionTy);
}
-
// C++ [expr.prim.lambda]p7:
// The lambda-expression's compound-statement yields the
// function-body (8.4) of the function call operator [...].
ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation);
CallOperator->setLexicalDeclContext(Class);
- Class->addDecl(CallOperator);
+ Decl *TemplateOrNonTemplateCallOperatorDecl =
+ CallOperator->getDescribedFunctionTemplate()
+ ? CallOperator->getDescribedFunctionTemplate()
+ : cast<Decl>(CallOperator);
+
+ TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class);
+ Class->addDecl(TemplateOrNonTemplateCallOperatorDecl);
+
PopExpressionEvaluationContext();
// C++11 [expr.prim.lambda]p6:
@@ -919,7 +1401,9 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
// non-explicit const conversion function to a block pointer having the
// same parameter and return types as the closure type's function call
// operator.
- if (getLangOpts().Blocks && getLangOpts().ObjC1)
+ // FIXME: Fix generic lambda to block conversions.
+ if (getLangOpts().Blocks && getLangOpts().ObjC1 &&
+ !Class->isGenericLambda())
addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator);
// Finalize the lambda class.
@@ -936,32 +1420,42 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
ExprNeedsCleanups = true;
LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
- CaptureDefault, Captures,
+ CaptureDefault, CaptureDefaultLoc,
+ Captures,
ExplicitParams, ExplicitResultType,
CaptureInits, ArrayIndexVars,
ArrayIndexStarts, Body->getLocEnd(),
ContainsUnexpandedParameterPack);
- // C++11 [expr.prim.lambda]p2:
- // A lambda-expression shall not appear in an unevaluated operand
- // (Clause 5).
if (!CurContext->isDependentContext()) {
switch (ExprEvalContexts.back().Context) {
+ // C++11 [expr.prim.lambda]p2:
+ // A lambda-expression shall not appear in an unevaluated operand
+ // (Clause 5).
case Unevaluated:
case UnevaluatedAbstract:
+ // C++1y [expr.const]p2:
+ // A conditional-expression e is a core constant expression unless the
+ // evaluation of e, following the rules of the abstract machine, would
+ // evaluate [...] a lambda-expression.
+ //
+ // This is technically incorrect, there are some constant evaluated contexts
+ // where this should be allowed. We should probably fix this when DR1607 is
+ // ratified, it lays out the exact set of conditions where we shouldn't
+ // allow a lambda-expression.
+ case ConstantEvaluated:
// We don't actually diagnose this case immediately, because we
// could be within a context where we might find out later that
// the expression is potentially evaluated (e.g., for typeid).
ExprEvalContexts.back().Lambdas.push_back(Lambda);
break;
- case ConstantEvaluated:
case PotentiallyEvaluated:
case PotentiallyEvaluatedIfUsed:
break;
}
}
-
+
return MaybeBindToTemporary(Lambda);
}
@@ -976,7 +1470,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
Lambda->lookup(
Context.DeclarationNames.getCXXOperatorName(OO_Call)).front());
CallOperator->setReferenced();
- CallOperator->setUsed();
+ CallOperator->markUsed(Context);
ExprResult Init = PerformCopyInitialization(
InitializedEntity::InitializeBlock(ConvLocation,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
index 9ab3b2d08ec0..919c6ad61ab2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
@@ -102,15 +102,14 @@ namespace {
// During unqualified name lookup, the names appear as if they
// were declared in the nearest enclosing namespace which contains
// both the using-directive and the nominated namespace.
- DeclContext *InnermostFileDC
- = static_cast<DeclContext*>(InnermostFileScope->getEntity());
+ DeclContext *InnermostFileDC = InnermostFileScope->getEntity();
assert(InnermostFileDC && InnermostFileDC->isFileContext());
for (; S; S = S->getParent()) {
// C++ [namespace.udir]p1:
// A using-directive shall not appear in class scope, but may
// appear in namespace scope or in block scope.
- DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+ DeclContext *Ctx = S->getEntity();
if (Ctx && Ctx->isFileContext()) {
visit(Ctx, Ctx);
} else if (!Ctx || Ctx->isFunctionOrMethod()) {
@@ -167,8 +166,7 @@ namespace {
if (queue.empty())
return;
- DC = queue.back();
- queue.pop_back();
+ DC = queue.pop_back_val();
}
}
@@ -217,12 +215,15 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
case Sema::LookupObjCImplicitSelfParam:
case Sema::LookupOrdinaryName:
case Sema::LookupRedeclarationWithLinkage:
+ case Sema::LookupLocalFriendName:
IDNS = Decl::IDNS_Ordinary;
if (CPlusPlus) {
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace;
if (Redeclaration)
IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend;
}
+ if (Redeclaration)
+ IDNS |= Decl::IDNS_LocalExtern;
break;
case Sema::LookupOperatorName:
@@ -336,10 +337,19 @@ void LookupResult::deletePaths(CXXBasePaths *Paths) {
delete Paths;
}
-static NamedDecl *getVisibleDecl(NamedDecl *D);
-
-NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
- return getVisibleDecl(D);
+/// Get a representative context for a declaration such that two declarations
+/// will have the same context if they were found within the same scope.
+static DeclContext *getContextForScopeMatching(Decl *D) {
+ // For function-local declarations, use that function as the context. This
+ // doesn't account for scopes within the function; the caller must deal with
+ // those.
+ DeclContext *DC = D->getLexicalDeclContext();
+ if (DC->isFunctionOrMethod())
+ return DC;
+
+ // Otherwise, look at the semantic context of the declaration. The
+ // declaration must have been found there.
+ return D->getDeclContext()->getRedeclContext();
}
/// Resolves the result kind of this lookup.
@@ -442,8 +452,8 @@ void LookupResult::resolveKind() {
// even if they're not visible. (ref?)
if (HideTags && HasTag && !Ambiguous &&
(HasFunction || HasNonFunction || HasUnresolved)) {
- if (Decls[UniqueTagIndex]->getDeclContext()->getRedeclContext()->Equals(
- Decls[UniqueTagIndex? 0 : N-1]->getDeclContext()->getRedeclContext()))
+ if (getContextForScopeMatching(Decls[UniqueTagIndex])->Equals(
+ getContextForScopeMatching(Decls[UniqueTagIndex ? 0 : N - 1])))
Decls[UniqueTagIndex] = Decls[--N];
else
Ambiguous = true;
@@ -511,6 +521,14 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
NameKind == Sema::LookupRedeclarationWithLinkage) {
IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo();
if (II) {
+ if (S.getLangOpts().CPlusPlus11 && S.getLangOpts().GNUMode &&
+ II == S.getFloat128Identifier()) {
+ // libstdc++4.7's type_traits expects type __float128 to exist, so
+ // insert a dummy type to make that header build in gnu++11 mode.
+ R.addDecl(S.getASTContext().getFloat128StubType());
+ return true;
+ }
+
// If this is a builtin on this (or all) targets, create the decl.
if (unsigned BuiltinID = II->getBuiltinID()) {
// In C++, we don't have any predefined library functions like
@@ -726,7 +744,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
// function to have, if it were to match the name given.
// FIXME: Calling convention!
FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo();
- EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_Default);
+ EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_C);
EPI.ExceptionSpecType = EST_None;
EPI.NumExceptions = 0;
QualType ExpectedType
@@ -771,7 +789,7 @@ CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context,
}
static bool isNamespaceOrTranslationUnitScope(Scope *S) {
- if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()))
+ if (DeclContext *Ctx = S->getEntity())
return Ctx->isFileContext();
return false;
}
@@ -784,12 +802,12 @@ static bool isNamespaceOrTranslationUnitScope(Scope *S) {
// name lookup should continue searching in this semantic context when
// it leaves the current template parameter scope.
static std::pair<DeclContext *, bool> findOuterContext(Scope *S) {
- DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
+ DeclContext *DC = S->getEntity();
DeclContext *Lexical = 0;
for (Scope *OuterS = S->getParent(); OuterS;
OuterS = OuterS->getParent()) {
if (OuterS->getEntity()) {
- Lexical = static_cast<DeclContext *>(OuterS->getEntity());
+ Lexical = OuterS->getEntity();
break;
}
}
@@ -845,16 +863,37 @@ static std::pair<DeclContext *, bool> findOuterContext(Scope *S) {
return std::make_pair(Lexical, false);
}
+namespace {
+/// An RAII object to specify that we want to find block scope extern
+/// declarations.
+struct FindLocalExternScope {
+ FindLocalExternScope(LookupResult &R)
+ : R(R), OldFindLocalExtern(R.getIdentifierNamespace() &
+ Decl::IDNS_LocalExtern) {
+ R.setFindLocalExtern(R.getIdentifierNamespace() & Decl::IDNS_Ordinary);
+ }
+ void restore() {
+ R.setFindLocalExtern(OldFindLocalExtern);
+ }
+ ~FindLocalExternScope() {
+ restore();
+ }
+ LookupResult &R;
+ bool OldFindLocalExtern;
+};
+}
+
bool Sema::CppLookupName(LookupResult &R, Scope *S) {
assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup");
DeclarationName Name = R.getLookupName();
+ Sema::LookupNameKind NameKind = R.getLookupKind();
// If this is the name of an implicitly-declared special member function,
// go through the scope stack to implicitly declare
if (isImplicitlyDeclaredMemberFunctionName(Name)) {
for (Scope *PreS = S; PreS; PreS = PreS->getParent())
- if (DeclContext *DC = static_cast<DeclContext *>(PreS->getEntity()))
+ if (DeclContext *DC = PreS->getEntity())
DeclareImplicitMemberFunctionsWithName(*this, Name, DC);
}
@@ -886,14 +925,35 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
//
UnqualUsingDirectiveSet UDirs;
bool VisitedUsingDirectives = false;
+ bool LeftStartingScope = false;
DeclContext *OutsideOfTemplateParamDC = 0;
+
+ // When performing a scope lookup, we want to find local extern decls.
+ FindLocalExternScope FindLocals(R);
+
for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
- DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+ DeclContext *Ctx = S->getEntity();
// Check whether the IdResolver has anything in this scope.
bool Found = false;
for (; I != IEnd && S->isDeclScope(*I); ++I) {
if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
+ if (NameKind == LookupRedeclarationWithLinkage) {
+ // Determine whether this (or a previous) declaration is
+ // out-of-scope.
+ if (!LeftStartingScope && !Initial->isDeclScope(*I))
+ LeftStartingScope = true;
+
+ // If we found something outside of our starting scope that
+ // does not have linkage, skip it. If it's a template parameter,
+ // we still find it, so we can diagnose the invalid redeclaration.
+ if (LeftStartingScope && !((*I)->hasLinkage()) &&
+ !(*I)->isTemplateParameter()) {
+ R.setShadowed();
+ continue;
+ }
+ }
+
Found = true;
R.addDecl(ND);
}
@@ -906,6 +966,15 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
return true;
}
+ if (NameKind == LookupLocalFriendName && !S->isClassScope()) {
+ // C++11 [class.friend]p11:
+ // If a friend declaration appears in a local class and the name
+ // specified is an unqualified name, a prior declaration is
+ // looked up without considering scopes that are outside the
+ // innermost enclosing non-class scope.
+ return false;
+ }
+
if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC &&
S->getParent() && !S->getParent()->isTemplateParamScope()) {
// We've just searched the last template parameter scope and
@@ -1007,7 +1076,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
if (!S) return false;
// If we are looking for members, no need to look into global/namespace scope.
- if (R.getLookupKind() == LookupMemberName)
+ if (NameKind == LookupMemberName)
return false;
// Collect UsingDirectiveDecls in all scopes, and recursively all
@@ -1019,7 +1088,12 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
UDirs.visitScopeChain(Initial, S);
UDirs.done();
}
-
+
+ // If we're not performing redeclaration lookup, do not look for local
+ // extern declarations outside of a function scope.
+ if (!R.isForRedeclaration())
+ FindLocals.restore();
+
// Lookup namespace scope, and global scope.
// Unqualified name lookup in C++ requires looking into scopes
// that aren't strictly lexical, and therefore we walk through the
@@ -1043,7 +1117,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
return true;
}
- DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
+ DeclContext *Ctx = S->getEntity();
if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC &&
S->getParent() && !S->getParent()->isTemplateParamScope()) {
// We've just searched the last template parameter scope and
@@ -1098,29 +1172,127 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
return !R.empty();
}
+/// \brief Find the declaration that a class temploid member specialization was
+/// instantiated from, or the member itself if it is an explicit specialization.
+static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) {
+ return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom();
+}
+
+/// \brief Find the module in which the given declaration was defined.
+static Module *getDefiningModule(Decl *Entity) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Entity)) {
+ // If this function was instantiated from a template, the defining module is
+ // the module containing the pattern.
+ if (FunctionDecl *Pattern = FD->getTemplateInstantiationPattern())
+ Entity = Pattern;
+ } else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Entity)) {
+ // If it's a class template specialization, find the template or partial
+ // specialization from which it was instantiated.
+ if (ClassTemplateSpecializationDecl *SpecRD =
+ dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
+ llvm::PointerUnion<ClassTemplateDecl*,
+ ClassTemplatePartialSpecializationDecl*> From =
+ SpecRD->getInstantiatedFrom();
+ if (ClassTemplateDecl *FromTemplate = From.dyn_cast<ClassTemplateDecl*>())
+ Entity = FromTemplate->getTemplatedDecl();
+ else if (From)
+ Entity = From.get<ClassTemplatePartialSpecializationDecl*>();
+ // Otherwise, it's an explicit specialization.
+ } else if (MemberSpecializationInfo *MSInfo =
+ RD->getMemberSpecializationInfo())
+ Entity = getInstantiatedFrom(RD, MSInfo);
+ } else if (EnumDecl *ED = dyn_cast<EnumDecl>(Entity)) {
+ if (MemberSpecializationInfo *MSInfo = ED->getMemberSpecializationInfo())
+ Entity = getInstantiatedFrom(ED, MSInfo);
+ } else if (VarDecl *VD = dyn_cast<VarDecl>(Entity)) {
+ // FIXME: Map from variable template specializations back to the template.
+ if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo())
+ Entity = getInstantiatedFrom(VD, MSInfo);
+ }
+
+ // Walk up to the containing context. That might also have been instantiated
+ // from a template.
+ DeclContext *Context = Entity->getDeclContext();
+ if (Context->isFileContext())
+ return Entity->getOwningModule();
+ return getDefiningModule(cast<Decl>(Context));
+}
+
+llvm::DenseSet<Module*> &Sema::getLookupModules() {
+ unsigned N = ActiveTemplateInstantiations.size();
+ for (unsigned I = ActiveTemplateInstantiationLookupModules.size();
+ I != N; ++I) {
+ Module *M = getDefiningModule(ActiveTemplateInstantiations[I].Entity);
+ if (M && !LookupModulesCache.insert(M).second)
+ M = 0;
+ ActiveTemplateInstantiationLookupModules.push_back(M);
+ }
+ return LookupModulesCache;
+}
+
+/// \brief Determine whether a declaration is visible to name lookup.
+///
+/// This routine determines whether the declaration D is visible in the current
+/// lookup context, taking into account the current template instantiation
+/// stack. During template instantiation, a declaration is visible if it is
+/// visible from a module containing any entity on the template instantiation
+/// path (by instantiating a template, you allow it to see the declarations that
+/// your module can see, including those later on in your module).
+bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
+ assert(D->isHidden() && !SemaRef.ActiveTemplateInstantiations.empty() &&
+ "should not call this: not in slow case");
+ Module *DeclModule = D->getOwningModule();
+ assert(DeclModule && "hidden decl not from a module");
+
+ // Find the extra places where we need to look.
+ llvm::DenseSet<Module*> &LookupModules = SemaRef.getLookupModules();
+ if (LookupModules.empty())
+ return false;
+
+ // If our lookup set contains the decl's module, it's visible.
+ if (LookupModules.count(DeclModule))
+ return true;
+
+ // If the declaration isn't exported, it's not visible in any other module.
+ if (D->isModulePrivate())
+ return false;
+
+ // Check whether DeclModule is transitively exported to an import of
+ // the lookup set.
+ for (llvm::DenseSet<Module *>::iterator I = LookupModules.begin(),
+ E = LookupModules.end();
+ I != E; ++I)
+ if ((*I)->isModuleVisible(DeclModule))
+ return true;
+ return false;
+}
+
/// \brief Retrieve the visible declaration corresponding to D, if any.
///
/// This routine determines whether the declaration D is visible in the current
/// module, with the current imports. If not, it checks whether any
/// redeclaration of D is visible, and if so, returns that declaration.
-///
+///
/// \returns D, or a visible previous declaration of D, whichever is more recent
/// and visible. If no declaration of D is visible, returns null.
-static NamedDecl *getVisibleDecl(NamedDecl *D) {
- if (LookupResult::isVisible(D))
- return D;
-
+static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
+ assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
+
for (Decl::redecl_iterator RD = D->redecls_begin(), RDEnd = D->redecls_end();
RD != RDEnd; ++RD) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(*RD)) {
- if (LookupResult::isVisible(ND))
+ if (LookupResult::isVisible(SemaRef, ND))
return ND;
}
}
-
+
return 0;
}
+NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
+ return findAcceptableDecl(SemaRef, D);
+}
+
/// @brief Perform unqualified name lookup starting from a given
/// scope.
///
@@ -1161,13 +1333,12 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
if (NameKind == Sema::LookupRedeclarationWithLinkage) {
// Find the nearest non-transparent declaration scope.
while (!(S->getFlags() & Scope::DeclScope) ||
- (S->getEntity() &&
- static_cast<DeclContext *>(S->getEntity())
- ->isTransparentContext()))
+ (S->getEntity() && S->getEntity()->isTransparentContext()))
S = S->getParent();
}
- unsigned IDNS = R.getIdentifierNamespace();
+ // When performing a scope lookup, we want to find local extern decls.
+ FindLocalExternScope FindLocals(R);
// Scan up the scope chain looking for a decl that matches this
// identifier that is in the appropriate namespace. This search
@@ -1178,7 +1349,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
for (IdentifierResolver::iterator I = IdResolver.begin(Name),
IEnd = IdResolver.end();
I != IEnd; ++I)
- if ((*I)->isInIdentifierNamespace(IDNS)) {
+ if (NamedDecl *D = R.getAcceptableDecl(*I)) {
if (NameKind == LookupRedeclarationWithLinkage) {
// Determine whether this (or a previous) declaration is
// out-of-scope.
@@ -1187,19 +1358,15 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
// If we found something outside of our starting scope that
// does not have linkage, skip it.
- if (LeftStartingScope && !((*I)->hasLinkage()))
+ if (LeftStartingScope && !((*I)->hasLinkage())) {
+ R.setShadowed();
continue;
+ }
}
else if (NameKind == LookupObjCImplicitSelfParam &&
!isa<ImplicitParamDecl>(*I))
continue;
-
- // If this declaration is module-private and it came from an AST
- // file, we can't see it.
- NamedDecl *D = R.isHiddenDeclarationVisible()? *I : getVisibleDecl(*I);
- if (!D)
- continue;
-
+
R.addDecl(D);
// Check whether there are any other declarations with the same name
@@ -1234,18 +1401,15 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
if (!LastDC->Equals(DC))
break;
}
-
- // If the declaration isn't in the right namespace, skip it.
- if (!(*LastI)->isInIdentifierNamespace(IDNS))
- continue;
-
- D = R.isHiddenDeclarationVisible()? *LastI : getVisibleDecl(*LastI);
- if (D)
- R.addDecl(D);
+
+ // If the declaration is in the right namespace and visible, add it.
+ if (NamedDecl *LastD = R.getAcceptableDecl(*LastI))
+ R.addDecl(LastD);
}
R.resolveKind();
}
+
return true;
}
} else {
@@ -1330,8 +1494,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
bool Found = false;
while (!Queue.empty()) {
- NamespaceDecl *ND = Queue.back();
- Queue.pop_back();
+ NamespaceDecl *ND = Queue.pop_back_val();
// We go through some convolutions here to avoid copying results
// between LookupResults.
@@ -1510,6 +1673,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
case LookupOrdinaryName:
case LookupMemberName:
case LookupRedeclarationWithLinkage:
+ case LookupLocalFriendName:
BaseCallback = &CXXRecordDecl::FindOrdinaryMember;
break;
@@ -1681,9 +1845,7 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
/// from name lookup.
///
/// \param Result The result of the ambiguous lookup to be diagnosed.
-///
-/// \returns true
-bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
+void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
assert(Result.isAmbiguous() && "Lookup result must be ambiguous");
DeclarationName Name = Result.getLookupName();
@@ -1704,8 +1866,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
++Found;
Diag((*Found)->getLocation(), diag::note_ambiguous_member_found);
-
- return true;
+ break;
}
case LookupResult::AmbiguousBaseSubobjectTypes: {
@@ -1721,8 +1882,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
if (DeclsPrinted.insert(D).second)
Diag(D->getLocation(), diag::note_ambiguous_member_found);
}
-
- return true;
+ break;
}
case LookupResult::AmbiguousTagHiding: {
@@ -1748,8 +1908,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
F.erase();
}
F.done();
-
- return true;
+ break;
}
case LookupResult::AmbiguousReference: {
@@ -1758,12 +1917,9 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
LookupResult::iterator DI = Result.begin(), DE = Result.end();
for (; DI != DE; ++DI)
Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI;
-
- return true;
+ break;
}
}
-
- llvm_unreachable("unknown ambiguity kind");
}
namespace {
@@ -1922,8 +2078,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
Bases.push_back(Class);
while (!Bases.empty()) {
// Pop this class off the stack.
- Class = Bases.back();
- Bases.pop_back();
+ Class = Bases.pop_back_val();
// Visit the base classes.
for (CXXRecordDecl::base_class_iterator Base = Class->bases_begin(),
@@ -2107,9 +2262,9 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
continue;
}
- if (Queue.empty()) break;
- T = Queue.back();
- Queue.pop_back();
+ if (Queue.empty())
+ break;
+ T = Queue.pop_back_val();
}
}
@@ -2120,11 +2275,10 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
/// This routine computes the sets of associated classes and associated
/// namespaces searched by argument-dependent lookup
/// (C++ [basic.lookup.argdep]) for a given set of arguments.
-void
-Sema::FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc,
- llvm::ArrayRef<Expr *> Args,
- AssociatedNamespaceSet &AssociatedNamespaces,
- AssociatedClassSet &AssociatedClasses) {
+void Sema::FindAssociatedClassesAndNamespaces(
+ SourceLocation InstantiationLoc, ArrayRef<Expr *> Args,
+ AssociatedNamespaceSet &AssociatedNamespaces,
+ AssociatedClassSet &AssociatedClasses) {
AssociatedNamespaces.clear();
AssociatedClasses.clear();
@@ -2393,11 +2547,17 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
// will always be a (possibly implicit) declaration to shadow any others.
OverloadCandidateSet OCS((SourceLocation()));
DeclContext::lookup_result R = RD->lookup(Name);
-
assert(!R.empty() &&
"lookup for a constructor or assignment operator was empty");
- for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
- Decl *Cand = *I;
+
+ // Copy the candidates as our processing of them may load new declarations
+ // from an external source and invalidate lookup_result.
+ SmallVector<NamedDecl *, 8> Candidates(R.begin(), R.end());
+
+ for (SmallVectorImpl<NamedDecl *>::iterator I = Candidates.begin(),
+ E = Candidates.end();
+ I != E; ++I) {
+ NamedDecl *Cand = *I;
if (Cand->isInvalidDecl())
continue;
@@ -2565,7 +2725,8 @@ CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) {
Sema::LiteralOperatorLookupResult
Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
ArrayRef<QualType> ArgTys,
- bool AllowRawAndTemplate) {
+ bool AllowRaw, bool AllowTemplate,
+ bool AllowStringTemplate) {
LookupName(R, S);
assert(R.getResultKind() != LookupResult::Ambiguous &&
"literal operator lookup can't be ambiguous");
@@ -2573,8 +2734,9 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
// Filter the lookup results appropriately.
LookupResult::Filter F = R.makeFilter();
- bool FoundTemplate = false;
bool FoundRaw = false;
+ bool FoundTemplate = false;
+ bool FoundStringTemplate = false;
bool FoundExactMatch = false;
while (F.hasNext()) {
@@ -2582,16 +2744,17 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
D = USD->getTargetDecl();
- bool IsTemplate = isa<FunctionTemplateDecl>(D);
- bool IsRaw = false;
- bool IsExactMatch = false;
-
// If the declaration we found is invalid, skip it.
if (D->isInvalidDecl()) {
F.erase();
continue;
}
+ bool IsRaw = false;
+ bool IsTemplate = false;
+ bool IsStringTemplate = false;
+ bool IsExactMatch = false;
+
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->getNumParams() == 1 &&
FD->getParamDecl(0)->getType()->getAs<PointerType>())
@@ -2607,19 +2770,31 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
}
}
}
+ if (FunctionTemplateDecl *FD = dyn_cast<FunctionTemplateDecl>(D)) {
+ TemplateParameterList *Params = FD->getTemplateParameters();
+ if (Params->size() == 1)
+ IsTemplate = true;
+ else
+ IsStringTemplate = true;
+ }
if (IsExactMatch) {
FoundExactMatch = true;
- AllowRawAndTemplate = false;
- if (FoundRaw || FoundTemplate) {
+ AllowRaw = false;
+ AllowTemplate = false;
+ AllowStringTemplate = false;
+ if (FoundRaw || FoundTemplate || FoundStringTemplate) {
// Go through again and remove the raw and template decls we've
// already found.
F.restart();
- FoundRaw = FoundTemplate = false;
+ FoundRaw = FoundTemplate = FoundStringTemplate = false;
}
- } else if (AllowRawAndTemplate && (IsTemplate || IsRaw)) {
- FoundTemplate |= IsTemplate;
- FoundRaw |= IsRaw;
+ } else if (AllowRaw && IsRaw) {
+ FoundRaw = true;
+ } else if (AllowTemplate && IsTemplate) {
+ FoundTemplate = true;
+ } else if (AllowStringTemplate && IsStringTemplate) {
+ FoundStringTemplate = true;
} else {
F.erase();
}
@@ -2654,10 +2829,14 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
if (FoundTemplate)
return LOLR_Template;
+ if (FoundStringTemplate)
+ return LOLR_StringTemplate;
+
// Didn't find anything we could use.
Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator)
<< R.getLookupName() << (int)ArgTys.size() << ArgTys[0]
- << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRawAndTemplate;
+ << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw
+ << (AllowTemplate || AllowStringTemplate);
return LOLR_Error;
}
@@ -2699,8 +2878,7 @@ void ADLResult::insert(NamedDecl *New) {
}
void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
- SourceLocation Loc,
- llvm::ArrayRef<Expr *> Args,
+ SourceLocation Loc, ArrayRef<Expr *> Args,
ADLResult &Result) {
// Find all of the associated namespaces and classes based on the
// arguments we have.
@@ -2748,9 +2926,21 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
NamedDecl *D = *I;
// If the only declaration here is an ordinary friend, consider
// it only if it was declared in an associated classes.
- if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) {
- DeclContext *LexDC = D->getLexicalDeclContext();
- if (!AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)))
+ if ((D->getIdentifierNamespace() & Decl::IDNS_Ordinary) == 0) {
+ // If it's neither ordinarily visible nor a friend, we can't find it.
+ if ((D->getIdentifierNamespace() & Decl::IDNS_OrdinaryFriend) == 0)
+ continue;
+
+ bool DeclaredInAssociatedClass = false;
+ for (Decl *DI = D; DI; DI = DI->getPreviousDecl()) {
+ DeclContext *LexDC = DI->getLexicalDeclContext();
+ if (isa<CXXRecordDecl>(LexDC) &&
+ AssociatedClasses.count(cast<CXXRecordDecl>(LexDC))) {
+ DeclaredInAssociatedClass = true;
+ break;
+ }
+ }
+ if (!DeclaredInAssociatedClass)
continue;
}
@@ -2775,6 +2965,8 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
//----------------------------------------------------------------------------
VisibleDeclConsumer::~VisibleDeclConsumer() { }
+bool VisibleDeclConsumer::includeHiddenDecls() const { return false; }
+
namespace {
class ShadowContextRAII;
@@ -3038,8 +3230,9 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
if (!S->getEntity() ||
(!S->getParent() &&
- !Visited.alreadyVisitedContext((DeclContext *)S->getEntity())) ||
- ((DeclContext *)S->getEntity())->isFunctionOrMethod()) {
+ !Visited.alreadyVisitedContext(S->getEntity())) ||
+ (S->getEntity())->isFunctionOrMethod()) {
+ FindLocalExternScope FindLocals(Result);
// Walk through the declarations in this Scope.
for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
D != DEnd; ++D) {
@@ -3057,7 +3250,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
// Look into this scope's declaration context, along with any of its
// parent lookup contexts (e.g., enclosing classes), up to the point
// where we hit the context stored in the next outer scope.
- Entity = (DeclContext *)S->getEntity();
+ Entity = S->getEntity();
DeclContext *OuterCtx = findOuterContext(S).first; // FIXME
for (DeclContext *Ctx = Entity; Ctx && !Ctx->Equals(OuterCtx);
@@ -3069,7 +3262,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
Result.getNameLoc(), Sema::LookupMemberName);
if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) {
LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false,
- /*InBaseClass=*/false, Consumer, Visited);
+ /*InBaseClass=*/false, Consumer, Visited);
}
}
@@ -3134,6 +3327,7 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
// Look for visible declarations.
LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
+ Result.setAllowHidden(Consumer.includeHiddenDecls());
VisibleDeclsRecord Visited;
if (!IncludeGlobalScope)
Visited.visitedContext(Context.getTranslationUnitDecl());
@@ -3145,6 +3339,7 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
VisibleDeclConsumer &Consumer,
bool IncludeGlobalScope) {
LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
+ Result.setAllowHidden(Consumer.includeHiddenDecls());
VisibleDeclsRecord Visited;
if (!IncludeGlobalScope)
Visited.visitedContext(Context.getTranslationUnitDecl());
@@ -3214,14 +3409,16 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
public:
explicit TypoCorrectionConsumer(Sema &SemaRef, IdentifierInfo *Typo)
: Typo(Typo->getName()),
- SemaRef(SemaRef) { }
+ SemaRef(SemaRef) {}
+
+ bool includeHiddenDecls() const { return true; }
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
bool InBaseClass);
void FoundName(StringRef Name);
void addKeywordResult(StringRef Keyword);
- void addName(StringRef Name, NamedDecl *ND, unsigned Distance,
- NestedNameSpecifier *NNS=NULL, bool isKeyword=false);
+ void addName(StringRef Name, NamedDecl *ND, NestedNameSpecifier *NNS = NULL,
+ bool isKeyword = false);
void addCorrection(TypoCorrection Correction);
typedef TypoResultsMap::iterator result_iterator;
@@ -3265,37 +3462,42 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
if (!Name)
return;
+ // Only consider visible declarations and declarations from modules with
+ // names that exactly match.
+ if (!LookupResult::isVisible(SemaRef, ND) && Name->getName() != Typo &&
+ !findAcceptableDecl(SemaRef, ND))
+ return;
+
FoundName(Name->getName());
}
void TypoCorrectionConsumer::FoundName(StringRef Name) {
- // 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());
- if (MinED && Typo.size() / MinED < 3)
- return;
-
- // Compute an upper bound on the allowable edit distance, so that the
- // edit-distance algorithm can short-circuit.
- unsigned UpperBound = (Typo.size() + 2) / 3;
-
// Compute the edit distance between the typo and the name of this
// entity, and add the identifier to the list of results.
- addName(Name, NULL, Typo.edit_distance(Name, true, UpperBound));
+ addName(Name, NULL);
}
void TypoCorrectionConsumer::addKeywordResult(StringRef Keyword) {
// Compute the edit distance between the typo and this keyword,
// and add the keyword to the list of results.
- addName(Keyword, NULL, Typo.edit_distance(Keyword), NULL, true);
+ addName(Keyword, NULL, NULL, true);
}
-void TypoCorrectionConsumer::addName(StringRef Name,
- NamedDecl *ND,
- unsigned Distance,
- NestedNameSpecifier *NNS,
- bool isKeyword) {
- TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, Distance);
+void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND,
+ NestedNameSpecifier *NNS, bool isKeyword) {
+ // 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());
+ if (MinED && Typo.size() / MinED < 3)
+ return;
+
+ // Compute an upper bound on the allowable edit distance, so that the
+ // edit-distance algorithm can short-circuit.
+ unsigned UpperBound = (Typo.size() + 2) / 3 + 1;
+ unsigned ED = Typo.edit_distance(Name, true, UpperBound);
+ if (ED >= UpperBound) return;
+
+ TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, ED);
if (isKeyword) TC.makeKeyword();
addCorrection(TC);
}
@@ -3388,6 +3590,7 @@ typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList;
class NamespaceSpecifierSet {
ASTContext &Context;
DeclContextList CurContextChain;
+ std::string CurNameSpecifier;
SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers;
SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers;
bool isSorted;
@@ -3406,10 +3609,14 @@ class NamespaceSpecifierSet {
NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext,
CXXScopeSpec *CurScopeSpec)
: Context(Context), CurContextChain(BuildContextChain(CurContext)),
- isSorted(true) {
- if (CurScopeSpec && CurScopeSpec->getScopeRep())
- getNestedNameSpecifierIdentifiers(CurScopeSpec->getScopeRep(),
- CurNameSpecifierIdentifiers);
+ isSorted(false) {
+ if (NestedNameSpecifier *NNS =
+ CurScopeSpec ? CurScopeSpec->getScopeRep() : 0) {
+ llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier);
+ NNS->print(SpecifierOStream, Context.getPrintingPolicy());
+
+ getNestedNameSpecifierIdentifiers(NNS, CurNameSpecifierIdentifiers);
+ }
// Build the list of identifiers that would be used for an absolute
// (from the global context) NestedNameSpecifier referring to the current
// context.
@@ -3419,11 +3626,17 @@ class NamespaceSpecifierSet {
if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C))
CurContextIdentifiers.push_back(ND->getIdentifier());
}
+
+ // Add the global context as a NestedNameSpecifier
+ Distances.insert(1);
+ DistanceMap[1].push_back(
+ SpecifierInfo(cast<DeclContext>(Context.getTranslationUnitDecl()),
+ NestedNameSpecifier::GlobalSpecifier(Context), 1));
}
- /// \brief Add the namespace to the set, computing the corresponding
- /// NestedNameSpecifier and its distance in the process.
- void AddNamespace(NamespaceDecl *ND);
+ /// \brief Add the DeclContext (a namespace or record) to the set, computing
+ /// the corresponding NestedNameSpecifier and its distance in the process.
+ void AddNameSpecifier(DeclContext *Ctx);
typedef SpecifierInfoList::iterator iterator;
iterator begin() {
@@ -3456,8 +3669,8 @@ void NamespaceSpecifierSet::SortNamespaces() {
std::sort(sortedDistances.begin(), sortedDistances.end());
Specifiers.clear();
- for (SmallVector<unsigned, 4>::iterator DI = sortedDistances.begin(),
- DIEnd = sortedDistances.end();
+ for (SmallVectorImpl<unsigned>::iterator DI = sortedDistances.begin(),
+ DIEnd = sortedDistances.end();
DI != DIEnd; ++DI) {
SpecifierInfoList &SpecList = DistanceMap[*DI];
Specifiers.append(SpecList.begin(), SpecList.end());
@@ -3466,8 +3679,26 @@ void NamespaceSpecifierSet::SortNamespaces() {
isSorted = true;
}
-void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) {
- DeclContext *Ctx = cast<DeclContext>(ND);
+static unsigned BuildNestedNameSpecifier(ASTContext &Context,
+ DeclContextList &DeclChain,
+ NestedNameSpecifier *&NNS) {
+ unsigned NumSpecifiers = 0;
+ for (DeclContextList::reverse_iterator C = DeclChain.rbegin(),
+ CEnd = DeclChain.rend();
+ C != CEnd; ++C) {
+ if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C)) {
+ NNS = NestedNameSpecifier::Create(Context, NNS, ND);
+ ++NumSpecifiers;
+ } else if (RecordDecl *RD = dyn_cast_or_null<RecordDecl>(*C)) {
+ NNS = NestedNameSpecifier::Create(Context, NNS, RD->isTemplateDecl(),
+ RD->getTypeForDecl());
+ ++NumSpecifiers;
+ }
+ }
+ return NumSpecifiers;
+}
+
+void NamespaceSpecifierSet::AddNameSpecifier(DeclContext *Ctx) {
NestedNameSpecifier *NNS = NULL;
unsigned NumSpecifiers = 0;
DeclContextList NamespaceDeclChain(BuildContextChain(Ctx));
@@ -3481,29 +3712,37 @@ void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) {
NamespaceDeclChain.pop_back();
}
+ // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain
+ NumSpecifiers = BuildNestedNameSpecifier(Context, NamespaceDeclChain, NNS);
+
// Add an explicit leading '::' specifier if needed.
- if (NamespaceDecl *ND =
- NamespaceDeclChain.empty() ? NULL :
- dyn_cast_or_null<NamespaceDecl>(NamespaceDeclChain.back())) {
+ if (NamespaceDeclChain.empty()) {
+ // Rebuild the NestedNameSpecifier as a globally-qualified specifier.
+ NNS = NestedNameSpecifier::GlobalSpecifier(Context);
+ NumSpecifiers =
+ BuildNestedNameSpecifier(Context, FullNamespaceDeclChain, NNS);
+ } else if (NamedDecl *ND =
+ dyn_cast_or_null<NamedDecl>(NamespaceDeclChain.back())) {
IdentifierInfo *Name = ND->getIdentifier();
- if (std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(),
- Name) != CurContextIdentifiers.end() ||
- std::find(CurNameSpecifierIdentifiers.begin(),
+ bool SameNameSpecifier = false;
+ if (std::find(CurNameSpecifierIdentifiers.begin(),
CurNameSpecifierIdentifiers.end(),
Name) != CurNameSpecifierIdentifiers.end()) {
- NamespaceDeclChain = FullNamespaceDeclChain;
- NNS = NestedNameSpecifier::GlobalSpecifier(Context);
+ std::string NewNameSpecifier;
+ llvm::raw_string_ostream SpecifierOStream(NewNameSpecifier);
+ SmallVector<const IdentifierInfo *, 4> NewNameSpecifierIdentifiers;
+ getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers);
+ NNS->print(SpecifierOStream, Context.getPrintingPolicy());
+ SpecifierOStream.flush();
+ SameNameSpecifier = NewNameSpecifier == CurNameSpecifier;
}
- }
-
- // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain
- for (DeclContextList::reverse_iterator C = NamespaceDeclChain.rbegin(),
- CEnd = NamespaceDeclChain.rend();
- C != CEnd; ++C) {
- NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C);
- if (ND) {
- NNS = NestedNameSpecifier::Create(Context, NNS, ND);
- ++NumSpecifiers;
+ if (SameNameSpecifier ||
+ std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(),
+ Name) != CurContextIdentifiers.end()) {
+ // Rebuild the NestedNameSpecifier as a globally-qualified specifier.
+ NNS = NestedNameSpecifier::GlobalSpecifier(Context);
+ NumSpecifiers =
+ BuildNestedNameSpecifier(Context, FullNamespaceDeclChain, NNS);
}
}
@@ -3515,8 +3754,8 @@ void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) {
SmallVector<const IdentifierInfo*, 4> NewNameSpecifierIdentifiers;
getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers);
NumSpecifiers = llvm::ComputeEditDistance(
- llvm::ArrayRef<const IdentifierInfo*>(CurNameSpecifierIdentifiers),
- llvm::ArrayRef<const IdentifierInfo*>(NewNameSpecifierIdentifiers));
+ ArrayRef<const IdentifierInfo *>(CurNameSpecifierIdentifiers),
+ ArrayRef<const IdentifierInfo *>(NewNameSpecifierIdentifiers));
}
isSorted = false;
@@ -3531,10 +3770,12 @@ static void LookupPotentialTypoResult(Sema &SemaRef,
Scope *S, CXXScopeSpec *SS,
DeclContext *MemberContext,
bool EnteringContext,
- bool isObjCIvarLookup) {
+ bool isObjCIvarLookup,
+ bool FindHidden) {
Res.suppressDiagnostics();
Res.clear();
Res.setLookupName(Name);
+ Res.setAllowHidden(FindHidden);
if (MemberContext) {
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(MemberContext)) {
if (isObjCIvarLookup) {
@@ -3593,7 +3834,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
if (CCC.WantTypeSpecifiers) {
// Add type-specifier keywords to the set of results.
- const char *CTypeSpecs[] = {
+ static const char *const CTypeSpecs[] = {
"char", "const", "double", "enum", "float", "int", "long", "short",
"signed", "struct", "union", "unsigned", "void", "volatile",
"_Complex", "_Imaginary",
@@ -3601,7 +3842,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
"extern", "inline", "static", "typedef"
};
- const unsigned NumCTypeSpecs = sizeof(CTypeSpecs) / sizeof(CTypeSpecs[0]);
+ const unsigned NumCTypeSpecs = llvm::array_lengthof(CTypeSpecs);
for (unsigned I = 0; I != NumCTypeSpecs; ++I)
Consumer.addKeywordResult(CTypeSpecs[I]);
@@ -3645,10 +3886,10 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
}
if (SemaRef.getLangOpts().CPlusPlus) {
- const char *CXXExprs[] = {
+ static const char *const CXXExprs[] = {
"delete", "new", "operator", "throw", "typeid"
};
- const unsigned NumCXXExprs = sizeof(CXXExprs) / sizeof(CXXExprs[0]);
+ const unsigned NumCXXExprs = llvm::array_lengthof(CXXExprs);
for (unsigned I = 0; I != NumCXXExprs; ++I)
Consumer.addKeywordResult(CXXExprs[I]);
@@ -3672,9 +3913,9 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
if (CCC.WantRemainingKeywords) {
if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.getCurBlock()) {
// Statements.
- const char *CStmts[] = {
+ static const char *const CStmts[] = {
"do", "else", "for", "goto", "if", "return", "switch", "while" };
- const unsigned NumCStmts = sizeof(CStmts) / sizeof(CStmts[0]);
+ const unsigned NumCStmts = llvm::array_lengthof(CStmts);
for (unsigned I = 0; I != NumCStmts; ++I)
Consumer.addKeywordResult(CStmts[I]);
@@ -3725,6 +3966,50 @@ static bool isCandidateViable(CorrectionCandidateCallback &CCC,
return Candidate.getEditDistance(false) != TypoCorrection::InvalidDistance;
}
+/// \brief Check whether the declarations found for a typo correction are
+/// visible, and if none of them are, convert the correction to an 'import
+/// a module' correction.
+static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC,
+ DeclarationName TypoName) {
+ if (TC.begin() == TC.end())
+ return;
+
+ TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end();
+
+ for (/**/; DI != DE; ++DI)
+ if (!LookupResult::isVisible(SemaRef, *DI))
+ break;
+ // Nothing to do if all decls are visible.
+ if (DI == DE)
+ return;
+
+ llvm::SmallVector<NamedDecl*, 4> NewDecls(TC.begin(), DI);
+ bool AnyVisibleDecls = !NewDecls.empty();
+
+ for (/**/; DI != DE; ++DI) {
+ NamedDecl *VisibleDecl = *DI;
+ if (!LookupResult::isVisible(SemaRef, *DI))
+ VisibleDecl = findAcceptableDecl(SemaRef, *DI);
+
+ if (VisibleDecl) {
+ if (!AnyVisibleDecls) {
+ // Found a visible decl, discard all hidden ones.
+ AnyVisibleDecls = true;
+ NewDecls.clear();
+ }
+ NewDecls.push_back(VisibleDecl);
+ } else if (!AnyVisibleDecls && !(*DI)->isModulePrivate())
+ NewDecls.push_back(*DI);
+ }
+
+ if (NewDecls.empty())
+ TC = TypoCorrection();
+ else {
+ TC.setCorrectionDecls(NewDecls);
+ TC.setRequiresImport(!AnyVisibleDecls);
+ }
+}
+
/// \brief Try to "correct" a typo in the source code by finding
/// visible declarations whose names are similar to the name that was
/// present in the source code.
@@ -3762,8 +4047,18 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
CorrectionCandidateCallback &CCC,
DeclContext *MemberContext,
bool EnteringContext,
- const ObjCObjectPointerType *OPT) {
- if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking)
+ const ObjCObjectPointerType *OPT,
+ bool RecordFailure) {
+ // Always let the ExternalSource have the first chance at correction, even
+ // if we would otherwise have given up.
+ if (ExternalSource) {
+ if (TypoCorrection Correction = ExternalSource->CorrectTypo(
+ TypoName, LookupKind, S, SS, CCC, MemberContext, EnteringContext, OPT))
+ return Correction;
+ }
+
+ if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking ||
+ DisableTypoCorrection)
return TypoCorrection();
// In Microsoft mode, don't perform typo correction in a template member
@@ -3792,6 +4087,18 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
if (S && S->isInObjcMethodScope() && Typo == getSuperIdentifier())
return TypoCorrection();
+ // Abort if typo correction already failed for this specific typo.
+ IdentifierSourceLocations::iterator locs = TypoCorrectionFailures.find(Typo);
+ if (locs != TypoCorrectionFailures.end() &&
+ locs->second.count(TypoName.getLoc()))
+ return TypoCorrection();
+
+ // Don't try to correct the identifier "vector" when in AltiVec mode.
+ // TODO: Figure out why typo correction misbehaves in this case, fix it, and
+ // remove this workaround.
+ if (getLangOpts().AltiVec && Typo->isStr("vector"))
+ return TypoCorrection();
+
NamespaceSpecifierSet Namespaces(Context, CurContext, SS);
TypoCorrectionConsumer Consumer(*this, Typo);
@@ -3836,8 +4143,15 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// keyword case, we'll end up adding the keyword below.
if (Cached->second) {
if (!Cached->second.isKeyword() &&
- isCandidateViable(CCC, Cached->second))
- Consumer.addCorrection(Cached->second);
+ isCandidateViable(CCC, Cached->second)) {
+ // Do not use correction that is unaccessible in the given scope.
+ NamedDecl *CorrectionDecl = Cached->second.getCorrectionDecl();
+ DeclarationNameInfo NameInfo(CorrectionDecl->getDeclName(),
+ CorrectionDecl->getLocation());
+ LookupResult R(*this, NameInfo, LookupOrdinaryName);
+ if (LookupName(R, S))
+ Consumer.addCorrection(Cached->second);
+ }
} else {
// Only honor no-correction cache hits when a callback that will validate
// correction candidates is not being used.
@@ -3858,11 +4172,12 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// corrections.
bool SearchNamespaces
= getLangOpts().CPlusPlus &&
- (IsUnqualifiedLookup || (QualifiedDC && QualifiedDC->isNamespace()));
- // In a few cases we *only* want to search for corrections bases on just
+ (IsUnqualifiedLookup || (SS && SS->isSet()));
+ // In a few cases we *only* want to search for corrections based on just
// adding or changing the nested name specifier.
- bool AllowOnlyNNSChanges = Typo->getName().size() < 3;
-
+ unsigned TypoLen = Typo->getName().size();
+ bool AllowOnlyNNSChanges = TypoLen < 3;
+
if (IsUnqualifiedLookup || SearchNamespaces) {
// For unqualified lookup, look through all of the names that we have
// seen in this translation unit.
@@ -3890,24 +4205,16 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
AddKeywordsToConsumer(*this, Consumer, S, CCC, SS && SS->isNotEmpty());
// If we haven't found anything, we're done.
- if (Consumer.empty()) {
- // If this was an unqualified lookup, note that no correction was found.
- if (IsUnqualifiedLookup)
- (void)UnqualifiedTyposCorrected[Typo];
-
- return TypoCorrection();
- }
+ if (Consumer.empty())
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
+ IsUnqualifiedLookup);
// Make sure the best edit distance (prior to adding any namespace qualifiers)
// is not more that about a third of the length of the typo's identifier.
unsigned ED = Consumer.getBestEditDistance(true);
- if (ED > 0 && Typo->getName().size() / ED < 3) {
- // If this was an unqualified lookup, note that no correction was found.
- if (IsUnqualifiedLookup)
- (void)UnqualifiedTyposCorrected[Typo];
-
- return TypoCorrection();
- }
+ if (ED > 0 && TypoLen / ED < 3)
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
+ IsUnqualifiedLookup);
// Build the NestedNameSpecifiers for the KnownNamespaces, if we're going
// to search those namespaces.
@@ -3920,12 +4227,24 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
for (unsigned I = 0, N = ExternalKnownNamespaces.size(); I != N; ++I)
KnownNamespaces[ExternalKnownNamespaces[I]] = true;
}
-
- for (llvm::MapVector<NamespaceDecl*, bool>::iterator
+
+ for (llvm::MapVector<NamespaceDecl*, bool>::iterator
KNI = KnownNamespaces.begin(),
KNIEnd = KnownNamespaces.end();
KNI != KNIEnd; ++KNI)
- Namespaces.AddNamespace(KNI->first);
+ Namespaces.AddNameSpecifier(KNI->first);
+
+ for (ASTContext::type_iterator TI = Context.types_begin(),
+ TIEnd = Context.types_end();
+ TI != TIEnd; ++TI) {
+ if (CXXRecordDecl *CD = (*TI)->getAsCXXRecordDecl()) {
+ CD = CD->getCanonicalDecl();
+ if (!CD->isDependentType() && !CD->isAnonymousStructOrUnion() &&
+ !CD->isUnion() &&
+ (CD->isBeingDefined() || CD->isCompleteDefinition()))
+ Namespaces.AddNameSpecifier(CD);
+ }
+ }
}
// Weed out any names that could not be found by name lookup or, if a
@@ -3935,7 +4254,6 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
TmpRes.suppressDiagnostics();
while (!Consumer.empty()) {
TypoCorrectionConsumer::distance_iterator DI = Consumer.begin();
- unsigned ED = DI->first;
for (TypoCorrectionConsumer::result_iterator I = DI->second.begin(),
IEnd = DI->second.end();
I != IEnd; /* Increment in loop. */) {
@@ -3976,13 +4294,31 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// Perform name lookup on this name.
TypoCorrection &Candidate = I->second.front();
IdentifierInfo *Name = Candidate.getCorrectionAsIdentifierInfo();
- LookupPotentialTypoResult(*this, TmpRes, Name, S, SS, MemberContext,
- EnteringContext, CCC.IsObjCIvarLookup);
+ DeclContext *TempMemberContext = MemberContext;
+ CXXScopeSpec *TempSS = SS;
+retry_lookup:
+ LookupPotentialTypoResult(*this, TmpRes, Name, S, TempSS,
+ TempMemberContext, EnteringContext,
+ CCC.IsObjCIvarLookup,
+ Name == TypoName.getName() &&
+ !Candidate.WillReplaceSpecifier());
switch (TmpRes.getResultKind()) {
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
case LookupResult::FoundUnresolvedValue:
+ if (TempSS) {
+ // Immediately retry the lookup without the given CXXScopeSpec
+ TempSS = NULL;
+ Candidate.WillReplaceSpecifier(true);
+ goto retry_lookup;
+ }
+ if (TempMemberContext) {
+ if (SS && !TempSS)
+ TempSS = SS;
+ TempMemberContext = NULL;
+ goto retry_lookup;
+ }
QualifiedResults.push_back(Candidate);
// We didn't find this name in our scope, or didn't like what we found;
// ignore it.
@@ -3996,7 +4332,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
case LookupResult::Ambiguous:
// We don't deal with ambiguities.
- return TypoCorrection();
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
case LookupResult::FoundOverloaded: {
TypoCorrectionConsumer::result_iterator Prev = I;
@@ -4006,8 +4342,10 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
TRD != TRDEnd; ++TRD)
Candidate.addCorrectionDecl(*TRD);
++I;
- if (!isCandidateViable(CCC, Candidate))
+ if (!isCandidateViable(CCC, Candidate)) {
+ QualifiedResults.push_back(Candidate);
DI->second.erase(Prev);
+ }
break;
}
@@ -4015,8 +4353,10 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
TypoCorrectionConsumer::result_iterator Prev = I;
Candidate.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
++I;
- if (!isCandidateViable(CCC, Candidate))
+ if (!isCandidateViable(CCC, Candidate)) {
+ QualifiedResults.push_back(Candidate);
DI->second.erase(Prev);
+ }
break;
}
@@ -4025,7 +4365,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
if (DI->second.empty())
Consumer.erase(DI);
- else if (!getLangOpts().CPlusPlus || QualifiedResults.empty() || !ED)
+ else if (!getLangOpts().CPlusPlus || QualifiedResults.empty() || !DI->first)
// If there are results in the closest possible bucket, stop
break;
@@ -4040,10 +4380,31 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
NIEnd = Namespaces.end();
NI != NIEnd; ++NI) {
DeclContext *Ctx = NI->DeclCtx;
+ const Type *NSType = NI->NameSpecifier->getAsType();
+
+ // If the current NestedNameSpecifier refers to a class and the
+ // current correction candidate is the name of that class, then skip
+ // it as it is unlikely a qualified version of the class' constructor
+ // is an appropriate correction.
+ if (CXXRecordDecl *NSDecl =
+ NSType ? NSType->getAsCXXRecordDecl() : 0) {
+ if (NSDecl->getIdentifier() == QRI->getCorrectionAsIdentifierInfo())
+ continue;
+ }
- // FIXME: Stop searching once the namespaces are too far away to create
- // acceptable corrections for this identifier (since the namespaces
- // are sorted in ascending order by edit distance).
+ TypoCorrection TC(*QRI);
+ TC.ClearCorrectionDecls();
+ TC.setCorrectionSpecifier(NI->NameSpecifier);
+ TC.setQualifierDistance(NI->EditDistance);
+ TC.setCallbackDistance(0); // Reset the callback distance
+
+ // If the current correction candidate and namespace combination are
+ // too far away from the original typo based on the normalized edit
+ // distance, then skip performing a qualified name lookup.
+ unsigned TmpED = TC.getEditDistance(true);
+ if (QRI->getCorrectionAsIdentifierInfo() != Typo &&
+ TmpED && TypoLen / TmpED < 3)
+ continue;
TmpRes.clear();
TmpRes.setLookupName(QRI->getCorrectionAsIdentifierInfo());
@@ -4052,23 +4413,30 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// Any corrections added below will be validated in subsequent
// iterations of the main while() loop over the Consumer's contents.
switch (TmpRes.getResultKind()) {
- case LookupResult::Found: {
- TypoCorrection TC(*QRI);
- TC.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
- TC.setCorrectionSpecifier(NI->NameSpecifier);
- TC.setQualifierDistance(NI->EditDistance);
- Consumer.addCorrection(TC);
- break;
- }
+ case LookupResult::Found:
case LookupResult::FoundOverloaded: {
- TypoCorrection TC(*QRI);
- TC.setCorrectionSpecifier(NI->NameSpecifier);
- TC.setQualifierDistance(NI->EditDistance);
+ if (SS && SS->isValid()) {
+ std::string NewQualified = TC.getAsString(getLangOpts());
+ std::string OldQualified;
+ llvm::raw_string_ostream OldOStream(OldQualified);
+ SS->getScopeRep()->print(OldOStream, getPrintingPolicy());
+ OldOStream << TypoName;
+ // If correction candidate would be an identical written qualified
+ // identifer, then the existing CXXScopeSpec probably included a
+ // typedef that didn't get accounted for properly.
+ if (OldOStream.str() == NewQualified)
+ break;
+ }
for (LookupResult::iterator TRD = TmpRes.begin(),
TRDEnd = TmpRes.end();
- TRD != TRDEnd; ++TRD)
- TC.addCorrectionDecl(*TRD);
- Consumer.addCorrection(TC);
+ TRD != TRDEnd; ++TRD) {
+ if (CheckMemberAccess(TC.getCorrectionRange().getBegin(),
+ NSType ? NSType->getAsCXXRecordDecl() : 0,
+ TRD.getPair()) == AR_accessible)
+ TC.addCorrectionDecl(*TRD);
+ }
+ if (TC.isResolved())
+ Consumer.addCorrection(TC);
break;
}
case LookupResult::NotFound:
@@ -4085,30 +4453,31 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
}
// No corrections remain...
- if (Consumer.empty()) return TypoCorrection();
+ if (Consumer.empty())
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
TypoResultsMap &BestResults = Consumer.getBestResults();
ED = Consumer.getBestEditDistance(true);
- if (!AllowOnlyNNSChanges && ED > 0 && Typo->getName().size() / ED < 3) {
+ if (!AllowOnlyNNSChanges && ED > 0 && TypoLen / ED < 3) {
// If this was an unqualified lookup and we believe the callback
// object wouldn't have filtered out possible corrections, note
// that no correction was found.
- if (IsUnqualifiedLookup && !ValidatingCallback)
- (void)UnqualifiedTyposCorrected[Typo];
-
- return TypoCorrection();
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
+ IsUnqualifiedLookup && !ValidatingCallback);
}
// If only a single name remains, return that result.
if (BestResults.size() == 1) {
const TypoResultList &CorrectionList = BestResults.begin()->second;
const TypoCorrection &Result = CorrectionList.front();
- if (CorrectionList.size() != 1) return TypoCorrection();
+ if (CorrectionList.size() != 1)
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
// Don't correct to a keyword that's the same as the typo; the keyword
// wasn't actually in scope.
- if (ED == 0 && Result.isKeyword()) return TypoCorrection();
+ if (ED == 0 && Result.isKeyword())
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
// Record the correction for unqualified lookup.
if (IsUnqualifiedLookup)
@@ -4116,6 +4485,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
TypoCorrection TC = Result;
TC.setCorrectionRange(SS, TypoName);
+ checkCorrectionVisibility(*this, TC, TypoName.getName());
return TC;
}
else if (BestResults.size() > 1
@@ -4130,7 +4500,8 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// Don't correct to a keyword that's the same as the typo; the keyword
// wasn't actually in scope.
- if (ED == 0) return TypoCorrection();
+ if (ED == 0)
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
// Record the correction for unqualified lookup.
if (IsUnqualifiedLookup)
@@ -4146,7 +4517,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
if (IsUnqualifiedLookup && !ValidatingCallback)
(void)UnqualifiedTyposCorrected[Typo];
- return TypoCorrection();
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
}
void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) {
@@ -4166,7 +4537,7 @@ std::string TypoCorrection::getAsString(const LangOptions &LO) const {
std::string tmpBuffer;
llvm::raw_string_ostream PrefixOStream(tmpBuffer);
CorrectionNameSpec->print(PrefixOStream, PrintingPolicy(LO));
- CorrectionName.printName(PrefixOStream);
+ PrefixOStream << CorrectionName;
return PrefixOStream.str();
}
@@ -4190,3 +4561,122 @@ bool CorrectionCandidateCallback::ValidateCandidate(const TypoCorrection &candid
return WantTypeSpecifiers;
}
+
+FunctionCallFilterCCC::FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs,
+ bool HasExplicitTemplateArgs)
+ : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs) {
+ WantTypeSpecifiers = SemaRef.getLangOpts().CPlusPlus;
+ WantRemainingKeywords = false;
+}
+
+bool FunctionCallFilterCCC::ValidateCandidate(const TypoCorrection &candidate) {
+ if (!candidate.getCorrectionDecl())
+ return candidate.isKeyword();
+
+ for (TypoCorrection::const_decl_iterator DI = candidate.begin(),
+ DIEnd = candidate.end();
+ DI != DIEnd; ++DI) {
+ FunctionDecl *FD = 0;
+ NamedDecl *ND = (*DI)->getUnderlyingDecl();
+ if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
+ FD = FTD->getTemplatedDecl();
+ if (!HasExplicitTemplateArgs && !FD) {
+ if (!(FD = dyn_cast<FunctionDecl>(ND)) && isa<ValueDecl>(ND)) {
+ // If the Decl is neither a function nor a template function,
+ // determine if it is a pointer or reference to a function. If so,
+ // check against the number of arguments expected for the pointee.
+ QualType ValType = cast<ValueDecl>(ND)->getType();
+ if (ValType->isAnyPointerType() || ValType->isReferenceType())
+ ValType = ValType->getPointeeType();
+ if (const FunctionProtoType *FPT = ValType->getAs<FunctionProtoType>())
+ if (FPT->getNumArgs() == NumArgs)
+ return true;
+ }
+ }
+ if (FD && FD->getNumParams() >= NumArgs &&
+ FD->getMinRequiredArguments() <= NumArgs)
+ return true;
+ }
+ return false;
+}
+
+void Sema::diagnoseTypo(const TypoCorrection &Correction,
+ const PartialDiagnostic &TypoDiag,
+ bool ErrorRecovery) {
+ diagnoseTypo(Correction, TypoDiag, PDiag(diag::note_previous_decl),
+ ErrorRecovery);
+}
+
+/// Find which declaration we should import to provide the definition of
+/// the given declaration.
+static const NamedDecl *getDefinitionToImport(const NamedDecl *D) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+ return VD->getDefinition();
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ return FD->isDefined(FD) ? FD : 0;
+ if (const TagDecl *TD = dyn_cast<TagDecl>(D))
+ return TD->getDefinition();
+ if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
+ return ID->getDefinition();
+ if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
+ return PD->getDefinition();
+ if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
+ return getDefinitionToImport(TD->getTemplatedDecl());
+ return 0;
+}
+
+/// \brief Diagnose a successfully-corrected typo. Separated from the correction
+/// itself to allow external validation of the result, etc.
+///
+/// \param Correction The result of performing typo correction.
+/// \param TypoDiag The diagnostic to produce. This will have the corrected
+/// string added to it (and usually also a fixit).
+/// \param PrevNote A note to use when indicating the location of the entity to
+/// which we are correcting. Will have the correction string added to it.
+/// \param ErrorRecovery If \c true (the default), the caller is going to
+/// recover from the typo as if the corrected string had been typed.
+/// In this case, \c PDiag must be an error, and we will attach a fixit
+/// to it.
+void Sema::diagnoseTypo(const TypoCorrection &Correction,
+ const PartialDiagnostic &TypoDiag,
+ const PartialDiagnostic &PrevNote,
+ bool ErrorRecovery) {
+ std::string CorrectedStr = Correction.getAsString(getLangOpts());
+ std::string CorrectedQuotedStr = Correction.getQuoted(getLangOpts());
+ FixItHint FixTypo = FixItHint::CreateReplacement(
+ Correction.getCorrectionRange(), CorrectedStr);
+
+ // Maybe we're just missing a module import.
+ if (Correction.requiresImport()) {
+ NamedDecl *Decl = Correction.getCorrectionDecl();
+ assert(Decl && "import required but no declaration to import");
+
+ // Suggest importing a module providing the definition of this entity, if
+ // possible.
+ const NamedDecl *Def = getDefinitionToImport(Decl);
+ if (!Def)
+ Def = Decl;
+ Module *Owner = Def->getOwningModule();
+ assert(Owner && "definition of hidden declaration is not in a module");
+
+ Diag(Correction.getCorrectionRange().getBegin(),
+ diag::err_module_private_declaration)
+ << Def << Owner->getFullModuleName();
+ Diag(Def->getLocation(), diag::note_previous_declaration);
+
+ // Recover by implicitly importing this module.
+ if (!isSFINAEContext() && ErrorRecovery)
+ createImplicitModuleImport(Correction.getCorrectionRange().getBegin(),
+ Owner);
+ return;
+ }
+
+ Diag(Correction.getCorrectionRange().getBegin(), TypoDiag)
+ << CorrectedQuotedStr << (ErrorRecovery ? FixTypo : FixItHint());
+
+ NamedDecl *ChosenDecl =
+ Correction.isKeyword() ? 0 : Correction.getCorrectionDecl();
+ if (PrevNote.getDiagID() && ChosenDecl)
+ Diag(ChosenDecl->getLocation(), PrevNote)
+ << CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo);
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
index 91f0881ae09c..d9d9cec1b700 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
@@ -126,7 +126,7 @@ CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop,
DeclContext::lookup_result R = Proto->lookup(Prop->getDeclName());
for (unsigned I = 0, N = R.size(); I != N; ++I) {
if (ObjCPropertyDecl *ProtoProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
- S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier());
+ S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), true);
return;
}
}
@@ -208,7 +208,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
DeclContext::lookup_result R = Super->lookup(Res->getDeclName());
for (unsigned I = 0, N = R.size(); I != N; ++I) {
if (ObjCPropertyDecl *SuperProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
- DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier());
+ DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false);
FoundInSuper = true;
break;
}
@@ -321,6 +321,21 @@ static unsigned getOwnershipRule(unsigned attr) {
ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
}
+static const char *NameOfOwnershipAttribute(unsigned attr) {
+ if (attr & ObjCPropertyDecl::OBJC_PR_assign)
+ return "assign";
+ if (attr & ObjCPropertyDecl::OBJC_PR_retain )
+ return "retain";
+ if (attr & ObjCPropertyDecl::OBJC_PR_copy)
+ return "copy";
+ if (attr & ObjCPropertyDecl::OBJC_PR_weak)
+ return "weak";
+ if (attr & ObjCPropertyDecl::OBJC_PR_strong)
+ return "strong";
+ assert(attr & ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
+ return "unsafe_unretained";
+}
+
ObjCPropertyDecl *
Sema::HandlePropertyInClassExtension(Scope *S,
SourceLocation AtLoc,
@@ -434,6 +449,8 @@ Sema::HandlePropertyInClassExtension(Scope *S,
// with continuation class's readwrite property attribute!
unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();
if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
+ PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly;
+ PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite;
PIkind |= deduceWeakPropertyFromType(*this, PIDecl->getType());
unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes);
unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind);
@@ -442,6 +459,22 @@ Sema::HandlePropertyInClassExtension(Scope *S,
Diag(AtLoc, diag::warn_property_attr_mismatch);
Diag(PIDecl->getLocation(), diag::note_property_declare);
}
+ else if (getLangOpts().ObjCAutoRefCount) {
+ QualType PrimaryPropertyQT =
+ Context.getCanonicalType(PIDecl->getType()).getUnqualifiedType();
+ if (isa<ObjCObjectPointerType>(PrimaryPropertyQT)) {
+ bool PropertyIsWeak = ((PIkind & ObjCPropertyDecl::OBJC_PR_weak) != 0);
+ Qualifiers::ObjCLifetime PrimaryPropertyLifeTime =
+ PrimaryPropertyQT.getObjCLifetime();
+ if (PrimaryPropertyLifeTime == Qualifiers::OCL_None &&
+ (Attributes & ObjCDeclSpec::DQ_PR_weak) &&
+ !PropertyIsWeak) {
+ Diag(AtLoc, diag::warn_property_implicitly_mismatched);
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ }
+ }
+ }
+
DeclContext *DC = cast<DeclContext>(CCPrimary);
if (!ObjCPropertyDecl::findPropertyDecl(DC,
PIDecl->getDeclName().getAsIdentifierInfo())) {
@@ -529,8 +562,16 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
if (IDecl->ClassImplementsProtocol(PNSCopying, true))
Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
}
- if (T->isObjCObjectType())
- Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object);
+
+ if (T->isObjCObjectType()) {
+ SourceLocation StarLoc = TInfo->getTypeLoc().getLocEnd();
+ StarLoc = PP.getLocForEndOfToken(StarLoc);
+ Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object)
+ << FixItHint::CreateInsertion(StarLoc, "*");
+ T = Context.getObjCObjectPointerType(T);
+ SourceLocation TLoc = TInfo->getTypeLoc().getLocStart();
+ TInfo = Context.getTrivialTypeSourceInfo(T, TLoc);
+ }
DeclContext *DC = cast<DeclContext>(CDecl);
ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
@@ -714,73 +755,57 @@ static void setImpliedPropertyAttributeForReadOnlyProperty(
return;
}
-/// DiagnoseClassAndClassExtPropertyMismatch - diagnose inconsistant property
-/// attribute declared in primary class and attributes overridden in any of its
-/// class extensions.
+/// DiagnosePropertyMismatchDeclInProtocols - diagnose properties declared
+/// in inherited protocols with mismatched types. Since any of them can
+/// be candidate for synthesis.
static void
-DiagnoseClassAndClassExtPropertyMismatch(Sema &S, ObjCInterfaceDecl *ClassDecl,
- ObjCPropertyDecl *property) {
- unsigned Attributes = property->getPropertyAttributesAsWritten();
- bool warn = (Attributes & ObjCDeclSpec::DQ_PR_readonly);
- for (ObjCInterfaceDecl::known_extensions_iterator
- Ext = ClassDecl->known_extensions_begin(),
- ExtEnd = ClassDecl->known_extensions_end();
- Ext != ExtEnd; ++Ext) {
- ObjCPropertyDecl *ClassExtProperty = 0;
- DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
- for (unsigned I = 0, N = R.size(); I != N; ++I) {
- ClassExtProperty = dyn_cast<ObjCPropertyDecl>(R[0]);
- if (ClassExtProperty)
- break;
- }
-
- if (ClassExtProperty) {
- warn = false;
- unsigned classExtPropertyAttr =
- ClassExtProperty->getPropertyAttributesAsWritten();
- // We are issuing the warning that we postponed because class extensions
- // can override readonly->readwrite and 'setter' attributes originally
- // placed on class's property declaration now make sense in the overridden
- // property.
- if (Attributes & ObjCDeclSpec::DQ_PR_readonly) {
- if (!classExtPropertyAttr ||
- (classExtPropertyAttr &
- (ObjCDeclSpec::DQ_PR_readwrite|
- ObjCDeclSpec::DQ_PR_assign |
- ObjCDeclSpec::DQ_PR_unsafe_unretained |
- ObjCDeclSpec::DQ_PR_copy |
- ObjCDeclSpec::DQ_PR_retain |
- ObjCDeclSpec::DQ_PR_strong)))
- continue;
- warn = true;
- break;
- }
- }
+DiagnosePropertyMismatchDeclInProtocols(Sema &S, SourceLocation AtLoc,
+ ObjCInterfaceDecl *ClassDecl,
+ ObjCPropertyDecl *Property) {
+ ObjCInterfaceDecl::ProtocolPropertyMap PropMap;
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = ClassDecl->all_referenced_protocol_begin(),
+ E = ClassDecl->all_referenced_protocol_end(); PI != E; ++PI) {
+ if (const ObjCProtocolDecl *PDecl = (*PI)->getDefinition())
+ PDecl->collectInheritedProtocolProperties(Property, PropMap);
}
- if (warn) {
- unsigned setterAttrs = (ObjCDeclSpec::DQ_PR_assign |
- ObjCDeclSpec::DQ_PR_unsafe_unretained |
- ObjCDeclSpec::DQ_PR_copy |
- ObjCDeclSpec::DQ_PR_retain |
- ObjCDeclSpec::DQ_PR_strong);
- if (Attributes & setterAttrs) {
- const char * which =
- (Attributes & ObjCDeclSpec::DQ_PR_assign) ?
- "assign" :
- (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ?
- "unsafe_unretained" :
- (Attributes & ObjCDeclSpec::DQ_PR_copy) ?
- "copy" :
- (Attributes & ObjCDeclSpec::DQ_PR_retain) ?
- "retain" : "strong";
-
- S.Diag(property->getLocation(),
- diag::warn_objc_property_attr_mutually_exclusive)
- << "readonly" << which;
+ if (ObjCInterfaceDecl *SDecl = ClassDecl->getSuperClass())
+ while (SDecl) {
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = SDecl->all_referenced_protocol_begin(),
+ E = SDecl->all_referenced_protocol_end(); PI != E; ++PI) {
+ if (const ObjCProtocolDecl *PDecl = (*PI)->getDefinition())
+ PDecl->collectInheritedProtocolProperties(Property, PropMap);
+ }
+ SDecl = SDecl->getSuperClass();
}
- }
+ if (PropMap.empty())
+ return;
+ QualType RHSType = S.Context.getCanonicalType(Property->getType());
+ bool FirsTime = true;
+ for (ObjCInterfaceDecl::ProtocolPropertyMap::iterator
+ I = PropMap.begin(), E = PropMap.end(); I != E; I++) {
+ ObjCPropertyDecl *Prop = I->second;
+ QualType LHSType = S.Context.getCanonicalType(Prop->getType());
+ if (!S.Context.propertyTypesAreCompatible(LHSType, RHSType)) {
+ bool IncompatibleObjC = false;
+ QualType ConvertedType;
+ if (!S.isObjCPointerConversion(RHSType, LHSType, ConvertedType, IncompatibleObjC)
+ || IncompatibleObjC) {
+ if (FirsTime) {
+ S.Diag(Property->getLocation(), diag::warn_protocol_property_mismatch)
+ << Property->getType();
+ FirsTime = false;
+ }
+ S.Diag(Prop->getLocation(), diag::note_protocol_property_declare)
+ << Prop->getType();
+ }
+ }
+ }
+ if (!FirsTime && AtLoc.isValid())
+ S.Diag(AtLoc, diag::note_property_synthesize);
}
/// ActOnPropertyImplDecl - This routine performs semantic checks and
@@ -879,8 +904,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
}
}
}
-
- DiagnoseClassAndClassExtPropertyMismatch(*this, IDecl, property);
+ if (Synthesize && isa<ObjCProtocolDecl>(property->getDeclContext()))
+ DiagnosePropertyMismatchDeclInProtocols(*this, AtLoc, IDecl, property);
} else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
if (Synthesize) {
@@ -1027,8 +1052,14 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
PropertyIvarType, /*Dinfo=*/0,
ObjCIvarDecl::Private,
(Expr *)0, true);
- if (CompleteTypeErr)
+ if (RequireNonAbstractType(PropertyIvarLoc,
+ PropertyIvarType,
+ diag::err_abstract_type_in_decl,
+ AbstractSynthesizedIvarType)) {
+ Diag(property->getLocation(), diag::note_property_declare);
Ivar->setInvalidDecl();
+ } else if (CompleteTypeErr)
+ Ivar->setInvalidDecl();
ClassImpDecl->addDecl(Ivar);
IDecl->makeDeclVisibleInContext(Ivar);
@@ -1158,6 +1189,18 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
diag::warn_property_getter_owning_mismatch);
Diag(property->getLocation(), diag::note_property_declare);
}
+ if (getLangOpts().ObjCAutoRefCount && Synthesize)
+ switch (getterMethod->getMethodFamily()) {
+ case OMF_retain:
+ case OMF_retainCount:
+ case OMF_release:
+ case OMF_autorelease:
+ Diag(getterMethod->getLocation(), diag::err_arc_illegal_method_def)
+ << 1 << getterMethod->getSelector();
+ break;
+ default:
+ break;
+ }
}
if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
setterMethod->createImplicitParams(Context, IDecl);
@@ -1272,31 +1315,41 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
void
Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
ObjCPropertyDecl *SuperProperty,
- const IdentifierInfo *inheritedName) {
+ const IdentifierInfo *inheritedName,
+ bool OverridingProtocolProperty) {
ObjCPropertyDecl::PropertyAttributeKind CAttr =
- Property->getPropertyAttributes();
+ Property->getPropertyAttributes();
ObjCPropertyDecl::PropertyAttributeKind SAttr =
- SuperProperty->getPropertyAttributes();
- if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly)
- && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite))
- Diag(Property->getLocation(), diag::warn_readonly_property)
- << Property->getDeclName() << inheritedName;
- if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy)
- != (SAttr & ObjCPropertyDecl::OBJC_PR_copy))
- Diag(Property->getLocation(), diag::warn_property_attribute)
- << Property->getDeclName() << "copy" << inheritedName;
- else if (!(SAttr & ObjCPropertyDecl::OBJC_PR_readonly)){
- unsigned CAttrRetain =
- (CAttr &
- (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong));
- unsigned SAttrRetain =
- (SAttr &
- (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong));
- bool CStrong = (CAttrRetain != 0);
- bool SStrong = (SAttrRetain != 0);
- if (CStrong != SStrong)
+ SuperProperty->getPropertyAttributes();
+
+ // We allow readonly properties without an explicit ownership
+ // (assign/unsafe_unretained/weak/retain/strong/copy) in super class
+ // to be overridden by a property with any explicit ownership in the subclass.
+ if (!OverridingProtocolProperty &&
+ !getOwnershipRule(SAttr) && getOwnershipRule(CAttr))
+ ;
+ else {
+ if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly)
+ && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite))
+ Diag(Property->getLocation(), diag::warn_readonly_property)
+ << Property->getDeclName() << inheritedName;
+ if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy)
+ != (SAttr & ObjCPropertyDecl::OBJC_PR_copy))
Diag(Property->getLocation(), diag::warn_property_attribute)
- << Property->getDeclName() << "retain (or strong)" << inheritedName;
+ << Property->getDeclName() << "copy" << inheritedName;
+ else if (!(SAttr & ObjCPropertyDecl::OBJC_PR_readonly)){
+ unsigned CAttrRetain =
+ (CAttr &
+ (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong));
+ unsigned SAttrRetain =
+ (SAttr &
+ (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong));
+ bool CStrong = (CAttrRetain != 0);
+ bool SStrong = (SAttrRetain != 0);
+ if (CStrong != SStrong)
+ Diag(Property->getLocation(), diag::warn_property_attribute)
+ << Property->getDeclName() << "retain (or strong)" << inheritedName;
+ }
}
if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)
@@ -1378,110 +1431,6 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
return false;
}
-/// MatchOneProtocolPropertiesInClass - This routine goes thru the list
-/// of properties declared in a protocol and compares their attribute against
-/// the same property declared in the class or category.
-void
-Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl, ObjCProtocolDecl *PDecl) {
- if (!CDecl)
- return;
-
- // Category case.
- if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
- // FIXME: We should perform this check when the property in the category
- // is declared.
- assert (CatDecl && "MatchOneProtocolPropertiesInClass");
- if (!CatDecl->IsClassExtension())
- for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
- E = PDecl->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *ProtoProp = *P;
- DeclContext::lookup_result R
- = CatDecl->lookup(ProtoProp->getDeclName());
- for (unsigned I = 0, N = R.size(); I != N; ++I) {
- if (ObjCPropertyDecl *CatProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
- if (CatProp != ProtoProp) {
- // Property protocol already exist in class. Diagnose any mismatch.
- DiagnosePropertyMismatch(CatProp, ProtoProp,
- PDecl->getIdentifier());
- }
- }
- }
- }
- return;
- }
-
- // Class
- // FIXME: We should perform this check when the property in the class
- // is declared.
- ObjCInterfaceDecl *IDecl = cast<ObjCInterfaceDecl>(CDecl);
- for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
- E = PDecl->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *ProtoProp = *P;
- DeclContext::lookup_result R
- = IDecl->lookup(ProtoProp->getDeclName());
- for (unsigned I = 0, N = R.size(); I != N; ++I) {
- if (ObjCPropertyDecl *ClassProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
- if (ClassProp != ProtoProp) {
- // Property protocol already exist in class. Diagnose any mismatch.
- DiagnosePropertyMismatch(ClassProp, ProtoProp,
- PDecl->getIdentifier());
- }
- }
- }
- }
-}
-
-/// isPropertyReadonly - Return true if property is readonly, by searching
-/// for the property in the class and in its categories and implementations
-///
-bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl,
- ObjCInterfaceDecl *IDecl) {
- // by far the most common case.
- if (!PDecl->isReadOnly())
- return false;
- // Even if property is ready only, if interface has a user defined setter,
- // it is not considered read only.
- if (IDecl->getInstanceMethod(PDecl->getSetterName()))
- return false;
-
- // Main class has the property as 'readonly'. Must search
- // through the category list to see if the property's
- // attribute has been over-ridden to 'readwrite'.
- for (ObjCInterfaceDecl::visible_categories_iterator
- Cat = IDecl->visible_categories_begin(),
- CatEnd = IDecl->visible_categories_end();
- Cat != CatEnd; ++Cat) {
- if (Cat->getInstanceMethod(PDecl->getSetterName()))
- return false;
- ObjCPropertyDecl *P =
- Cat->FindPropertyDeclaration(PDecl->getIdentifier());
- if (P && !P->isReadOnly())
- return false;
- }
-
- // Also, check for definition of a setter method in the implementation if
- // all else failed.
- if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) {
- if (ObjCImplementationDecl *IMD =
- dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) {
- if (IMD->getInstanceMethod(PDecl->getSetterName()))
- return false;
- } else if (ObjCCategoryImplDecl *CIMD =
- dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
- if (CIMD->getInstanceMethod(PDecl->getSetterName()))
- return false;
- }
- }
- // Lastly, look through the implementation (if one is in scope).
- if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation())
- if (ImpDecl->getInstanceMethod(PDecl->getSetterName()))
- return false;
- // If all fails, look at the super class.
- if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass())
- return isPropertyReadonly(PDecl, SIDecl);
- return true;
-}
-
/// CollectImmediateProperties - This routine collects all properties in
/// the class and its conforming protocols; but not those in its super class.
void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
@@ -1588,6 +1537,19 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,
for (unsigned i = 0, e = PropertyOrder.size(); i != e; i++) {
ObjCPropertyDecl *Prop = PropertyOrder[i];
+ // Is there a matching property synthesize/dynamic?
+ if (Prop->isInvalidDecl() ||
+ Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional)
+ continue;
+ // Property may have been synthesized by user.
+ if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier()))
+ continue;
+ if (IMPDecl->getInstanceMethod(Prop->getGetterName())) {
+ if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
+ continue;
+ if (IMPDecl->getInstanceMethod(Prop->getSetterName()))
+ continue;
+ }
// If property to be implemented in the super class, ignore.
if (SuperPropMap[Prop->getIdentifier()]) {
ObjCPropertyDecl *PropInSuperClass = SuperPropMap[Prop->getIdentifier()];
@@ -1602,29 +1564,16 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,
}
continue;
}
- // Is there a matching property synthesize/dynamic?
- if (Prop->isInvalidDecl() ||
- Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional)
- continue;
if (ObjCPropertyImplDecl *PID =
- IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) {
+ IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) {
if (PID->getPropertyDecl() != Prop) {
Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property)
- << Prop->getIdentifier()->getName();
+ << Prop->getIdentifier()->getName();
if (!PID->getLocation().isInvalid())
Diag(PID->getLocation(), diag::note_property_synthesize);
}
continue;
}
- // Property may have been synthesized by user.
- if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier()))
- continue;
- if (IMPDecl->getInstanceMethod(Prop->getGetterName())) {
- if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
- continue;
- if (IMPDecl->getInstanceMethod(Prop->getSetterName()))
- continue;
- }
if (isa<ObjCProtocolDecl>(Prop->getDeclContext())) {
// We won't auto-synthesize properties declared in protocols.
Diag(IMPDecl->getLocation(),
@@ -1966,6 +1915,10 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
if (property->hasAttr<NSReturnsNotRetainedAttr>())
GetterMethod->addAttr(
::new (Context) NSReturnsNotRetainedAttr(Loc, Context));
+
+ if (property->hasAttr<ObjCReturnsInnerPointerAttr>())
+ GetterMethod->addAttr(
+ ::new (Context) ObjCReturnsInnerPointerAttr(Loc, Context));
if (getLangOpts().ObjCAutoRefCount)
CheckARCMethodDecl(GetterMethod);
@@ -2064,55 +2017,30 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
// FIXME: Improve the reported location.
if (!PDecl || PDecl->isInvalidDecl())
return;
-
+
+ if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+ (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
+ Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+ << "readonly" << "readwrite";
+
ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
- QualType PropertyTy = PropertyDecl->getType();
-
- if (getLangOpts().ObjCAutoRefCount &&
- (Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
- PropertyTy->isObjCRetainableType()) {
- // 'readonly' property with no obvious lifetime.
- // its life time will be determined by its backing ivar.
- unsigned rel = (ObjCDeclSpec::DQ_PR_unsafe_unretained |
- ObjCDeclSpec::DQ_PR_copy |
- ObjCDeclSpec::DQ_PR_retain |
- ObjCDeclSpec::DQ_PR_strong |
- ObjCDeclSpec::DQ_PR_weak |
- ObjCDeclSpec::DQ_PR_assign);
- if ((Attributes & rel) == 0)
+ QualType PropertyTy = PropertyDecl->getType();
+ unsigned PropertyOwnership = getOwnershipRule(Attributes);
+
+ if (Attributes & ObjCDeclSpec::DQ_PR_readonly) {
+ if (getLangOpts().ObjCAutoRefCount &&
+ PropertyTy->isObjCRetainableType() &&
+ !PropertyOwnership) {
+ // 'readonly' property with no obvious lifetime.
+ // its life time will be determined by its backing ivar.
return;
- }
-
- if (propertyInPrimaryClass) {
- // we postpone most property diagnosis until class's implementation
- // because, its readonly attribute may be overridden in its class
- // extensions making other attributes, which make no sense, to make sense.
- if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
- (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
- Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
- << "readonly" << "readwrite";
- }
- // readonly and readwrite/assign/retain/copy conflict.
- else if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
- (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
- ObjCDeclSpec::DQ_PR_assign |
- ObjCDeclSpec::DQ_PR_unsafe_unretained |
- ObjCDeclSpec::DQ_PR_copy |
- ObjCDeclSpec::DQ_PR_retain |
- ObjCDeclSpec::DQ_PR_strong))) {
- const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ?
- "readwrite" :
- (Attributes & ObjCDeclSpec::DQ_PR_assign) ?
- "assign" :
- (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ?
- "unsafe_unretained" :
- (Attributes & ObjCDeclSpec::DQ_PR_copy) ?
- "copy" : "retain";
-
- Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ?
- diag::err_objc_property_attr_mutually_exclusive :
- diag::warn_objc_property_attr_mutually_exclusive)
- << "readonly" << which;
+ }
+ else if (PropertyOwnership) {
+ if (!getSourceManager().isInSystemHeader(Loc))
+ Diag(Loc, diag::warn_objc_property_attr_mutually_exclusive)
+ << "readonly" << NameOfOwnershipAttribute(Attributes);
+ return;
+ }
}
// Check for copy or retain on non-object types.
@@ -2151,6 +2079,8 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
<< "assign" << "weak";
Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
}
+ if (PropertyDecl->getAttr<IBOutletCollectionAttr>())
+ Diag(Loc, diag::warn_iboutletcollection_property_assign);
} else if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) {
if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
index c815d4f9abc7..c63caf46b9e0 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
@@ -8,131 +8,516 @@
//===----------------------------------------------------------------------===//
/// \file
/// \brief This file implements semantic analysis for OpenMP directives and
-/// clauses
+/// clauses.
///
//===----------------------------------------------------------------------===//
#include "clang/Basic/OpenMPKinds.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclOpenMP.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtOpenMP.h"
+#include "clang/AST/StmtVisitor.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Initialization.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
using namespace clang;
+//===----------------------------------------------------------------------===//
+// Stack of data-sharing attributes for variables
+//===----------------------------------------------------------------------===//
+
namespace {
+/// \brief Default data sharing attributes, which can be applied to directive.
+enum DefaultDataSharingAttributes {
+ DSA_unspecified = 0, /// \brief Data sharing attribute not specified.
+ DSA_none = 1 << 0, /// \brief Default data sharing attribute 'none'.
+ DSA_shared = 1 << 1 /// \brief Default data sharing attribute 'shared'.
+};
+
+/// \brief Stack for tracking declarations used in OpenMP directives and
+/// clauses and their data-sharing attributes.
+class DSAStackTy {
+public:
+ struct DSAVarData {
+ OpenMPDirectiveKind DKind;
+ OpenMPClauseKind CKind;
+ DeclRefExpr *RefExpr;
+ DSAVarData() : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(0) { }
+ };
+private:
+ struct DSAInfo {
+ OpenMPClauseKind Attributes;
+ DeclRefExpr *RefExpr;
+ };
+ typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy;
+
+ struct SharingMapTy {
+ DeclSAMapTy SharingMap;
+ DefaultDataSharingAttributes DefaultAttr;
+ OpenMPDirectiveKind Directive;
+ DeclarationNameInfo DirectiveName;
+ Scope *CurScope;
+ SharingMapTy(OpenMPDirectiveKind DKind,
+ const DeclarationNameInfo &Name,
+ Scope *CurScope)
+ : SharingMap(), DefaultAttr(DSA_unspecified), Directive(DKind),
+ DirectiveName(Name), CurScope(CurScope) { }
+ SharingMapTy()
+ : SharingMap(), DefaultAttr(DSA_unspecified),
+ Directive(OMPD_unknown), DirectiveName(),
+ CurScope(0) { }
+ };
+
+ typedef SmallVector<SharingMapTy, 64> StackTy;
+
+ /// \brief Stack of used declaration and their data-sharing attributes.
+ StackTy Stack;
+ Sema &Actions;
+
+ typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator;
+
+ DSAVarData getDSA(StackTy::reverse_iterator Iter, VarDecl *D);
+public:
+ explicit DSAStackTy(Sema &S) : Stack(1), Actions(S) { }
+
+ void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
+ Scope *CurScope) {
+ Stack.push_back(SharingMapTy(DKind, DirName, CurScope));
+ }
+
+ void pop() {
+ assert(Stack.size() > 1 && "Data-sharing attributes stack is empty!");
+ Stack.pop_back();
+ }
+
+ /// \brief Adds explicit data sharing attribute to the specified declaration.
+ void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A);
+
+ /// \brief Checks if the variable is a local for OpenMP region.
+ bool isOpenMPLocal(VarDecl *D);
+
+ /// \brief Returns data sharing attributes from top of the stack for the
+ /// specified declaration.
+ DSAVarData getTopDSA(VarDecl *D);
+ /// \brief Returns data-sharing attributes for the specified declaration.
+ DSAVarData getImplicitDSA(VarDecl *D);
+ /// \brief Checks if the specified variables has \a CKind data-sharing
+ /// attribute in \a DKind directive.
+ DSAVarData hasDSA(VarDecl *D, OpenMPClauseKind CKind,
+ OpenMPDirectiveKind DKind = OMPD_unknown);
+
+
+ /// \brief Returns currently analyzed directive.
+ OpenMPDirectiveKind getCurrentDirective() const {
+ return Stack.back().Directive;
+ }
+
+ /// \brief Set default data sharing attribute to none.
+ void setDefaultDSANone() { Stack.back().DefaultAttr = DSA_none; }
+ /// \brief Set default data sharing attribute to shared.
+ void setDefaultDSAShared() { Stack.back().DefaultAttr = DSA_shared; }
+
+ DefaultDataSharingAttributes getDefaultDSA() const {
+ return Stack.back().DefaultAttr;
+ }
+
+ Scope *getCurScope() { return Stack.back().CurScope; }
+};
+} // end anonymous namespace.
+
+DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
+ VarDecl *D) {
+ DSAVarData DVar;
+ if (Iter == Stack.rend() - 1) {
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a region but not in construct]
+ // File-scope or namespace-scope variables referenced in called routines
+ // in the region are shared unless they appear in a threadprivate
+ // directive.
+ // TODO
+ if (!D->isFunctionOrMethodVarDecl())
+ DVar.CKind = OMPC_shared;
+
+ // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
+ // in a region but not in construct]
+ // Variables with static storage duration that are declared in called
+ // routines in the region are shared.
+ if (D->hasGlobalStorage())
+ DVar.CKind = OMPC_shared;
+
+ return DVar;
+ }
+ DVar.DKind = Iter->Directive;
+ // Explicitly specified attributes and local variables with predetermined
+ // attributes.
+ if (Iter->SharingMap.count(D)) {
+ DVar.RefExpr = Iter->SharingMap[D].RefExpr;
+ DVar.CKind = Iter->SharingMap[D].Attributes;
+ return DVar;
+ }
+
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, C/C++, implicitly determined, p.1]
+ // In a parallel or task construct, the data-sharing attributes of these
+ // variables are determined by the default clause, if present.
+ switch (Iter->DefaultAttr) {
+ case DSA_shared:
+ DVar.CKind = OMPC_shared;
+ return DVar;
+ case DSA_none:
+ return DVar;
+ case DSA_unspecified:
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, implicitly determined, p.2]
+ // In a parallel construct, if no default clause is present, these
+ // variables are shared.
+ if (DVar.DKind == OMPD_parallel) {
+ DVar.CKind = OMPC_shared;
+ return DVar;
+ }
- class VarDeclFilterCCC : public CorrectionCandidateCallback {
- private:
- Sema &Actions;
- public:
- VarDeclFilterCCC(Sema &S) : Actions(S) { }
- virtual bool ValidateCandidate(const TypoCorrection &Candidate) {
- NamedDecl *ND = Candidate.getCorrectionDecl();
- if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) {
- return VD->hasGlobalStorage() &&
- Actions.isDeclInScope(ND, Actions.getCurLexicalContext(),
- Actions.getCurScope());
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, implicitly determined, p.4]
+ // In a task construct, if no default clause is present, a variable that in
+ // the enclosing context is determined to be shared by all implicit tasks
+ // bound to the current team is shared.
+ // TODO
+ if (DVar.DKind == OMPD_task) {
+ DSAVarData DVarTemp;
+ for (StackTy::reverse_iterator I = Iter + 1,
+ EE = Stack.rend() - 1;
+ I != EE; ++I) {
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, implicitly determined, p.6]
+ // In a task construct, if no default clause is present, a variable
+ // whose data-sharing attribute is not determined by the rules above is
+ // firstprivate.
+ DVarTemp = getDSA(I, D);
+ if (DVarTemp.CKind != OMPC_shared) {
+ DVar.RefExpr = 0;
+ DVar.DKind = OMPD_task;
+ DVar.CKind = OMPC_firstprivate;
+ return DVar;
}
- return false;
+ if (I->Directive == OMPD_parallel) break;
}
- };
+ DVar.DKind = OMPD_task;
+ DVar.CKind =
+ (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
+ return DVar;
+ }
+ }
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, implicitly determined, p.3]
+ // For constructs other than task, if no default clause is present, these
+ // variables inherit their data-sharing attributes from the enclosing
+ // context.
+ return getDSA(Iter + 1, D);
}
-Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
- SourceLocation Loc,
- Scope *CurScope,
- ArrayRef<DeclarationNameInfo> IdList) {
- SmallVector<DeclRefExpr *, 5> Vars;
- for (ArrayRef<DeclarationNameInfo>::iterator I = IdList.begin(),
- E = IdList.end();
+
+void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
+ if (A == OMPC_threadprivate) {
+ Stack[0].SharingMap[D].Attributes = A;
+ Stack[0].SharingMap[D].RefExpr = E;
+ } else {
+ assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
+ Stack.back().SharingMap[D].Attributes = A;
+ Stack.back().SharingMap[D].RefExpr = E;
+ }
+}
+
+bool DSAStackTy::isOpenMPLocal(VarDecl *D) {
+ Scope *CurScope = getCurScope();
+ while (CurScope && !CurScope->isDeclScope(D))
+ CurScope = CurScope->getParent();
+ while (CurScope && !CurScope->isOpenMPDirectiveScope())
+ CurScope = CurScope->getParent();
+ bool isOpenMPLocal = !!CurScope;
+ if (!isOpenMPLocal) {
+ CurScope = getCurScope();
+ while (CurScope && !CurScope->isOpenMPDirectiveScope())
+ CurScope = CurScope->getParent();
+ isOpenMPLocal =
+ CurScope &&
+ isa<CapturedDecl>(D->getDeclContext()) &&
+ CurScope->getFnParent()->getEntity()->Encloses(D->getDeclContext());
+ }
+ return isOpenMPLocal;
+}
+
+DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
+ DSAVarData DVar;
+
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, C/C++, predetermined, p.1]
+ // Variables appearing in threadprivate directives are threadprivate.
+ if (D->getTLSKind() != VarDecl::TLS_None) {
+ DVar.CKind = OMPC_threadprivate;
+ return DVar;
+ }
+ if (Stack[0].SharingMap.count(D)) {
+ DVar.RefExpr = Stack[0].SharingMap[D].RefExpr;
+ DVar.CKind = OMPC_threadprivate;
+ return DVar;
+ }
+
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, C/C++, predetermined, p.1]
+ // Variables with automatic storage duration that are declared in a scope
+ // inside the construct are private.
+ if (isOpenMPLocal(D) && D->isLocalVarDecl() &&
+ (D->getStorageClass() == SC_Auto ||
+ D->getStorageClass() == SC_None)) {
+ DVar.CKind = OMPC_private;
+ return DVar;
+ }
+
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, C/C++, predetermined, p.4]
+ // Static data memebers are shared.
+ if (D->isStaticDataMember()) {
+ // Variables with const-qualified type having no mutable member may be listed
+ // in a firstprivate clause, even if they are static data members.
+ DSAVarData DVarTemp = hasDSA(D, OMPC_firstprivate);
+ if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
+ return DVar;
+
+ DVar.CKind = OMPC_shared;
+ return DVar;
+ }
+
+ QualType Type = D->getType().getNonReferenceType().getCanonicalType();
+ bool IsConstant = Type.isConstant(Actions.getASTContext());
+ while (Type->isArrayType()) {
+ QualType ElemType = cast<ArrayType>(Type.getTypePtr())->getElementType();
+ Type = ElemType.getNonReferenceType().getCanonicalType();
+ }
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, C/C++, predetermined, p.6]
+ // Variables with const qualified type having no mutable member are
+ // shared.
+ CXXRecordDecl *RD = Actions.getLangOpts().CPlusPlus ?
+ Type->getAsCXXRecordDecl() : 0;
+ if (IsConstant &&
+ !(Actions.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) {
+ // Variables with const-qualified type having no mutable member may be
+ // listed in a firstprivate clause, even if they are static data members.
+ DSAVarData DVarTemp = hasDSA(D, OMPC_firstprivate);
+ if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
+ return DVar;
+
+ DVar.CKind = OMPC_shared;
+ return DVar;
+ }
+
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, C/C++, predetermined, p.7]
+ // Variables with static storage duration that are declared in a scope
+ // inside the construct are shared.
+ if (isOpenMPLocal(D) && D->isStaticLocal()) {
+ DVar.CKind = OMPC_shared;
+ return DVar;
+ }
+
+ // Explicitly specified attributes and local variables with predetermined
+ // attributes.
+ if (Stack.back().SharingMap.count(D)) {
+ DVar.RefExpr = Stack.back().SharingMap[D].RefExpr;
+ DVar.CKind = Stack.back().SharingMap[D].Attributes;
+ }
+
+ return DVar;
+}
+
+DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D) {
+ return getDSA(Stack.rbegin() + 1, D);
+}
+
+DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, OpenMPClauseKind CKind,
+ OpenMPDirectiveKind DKind) {
+ for (StackTy::reverse_iterator I = Stack.rbegin() + 1,
+ E = Stack.rend() - 1;
I != E; ++I) {
- LookupResult Lookup(*this, *I, LookupOrdinaryName);
- LookupParsedName(Lookup, CurScope, NULL, true);
-
- if (Lookup.isAmbiguous())
- continue;
-
- VarDecl *VD;
- if (!Lookup.isSingleResult()) {
- VarDeclFilterCCC Validator(*this);
- TypoCorrection Corrected = CorrectTypo(*I, LookupOrdinaryName, CurScope,
- 0, Validator);
- std::string CorrectedStr = Corrected.getAsString(getLangOpts());
- std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts());
- if (Lookup.empty()) {
- if (Corrected.isResolved()) {
- Diag(I->getLoc(), diag::err_undeclared_var_use_suggest)
- << I->getName() << CorrectedQuotedStr
- << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr);
- } else {
- Diag(I->getLoc(), diag::err_undeclared_var_use)
- << I->getName();
- }
- } else {
- Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest)
- << I->getName() << Corrected.isResolved() << CorrectedQuotedStr
- << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr);
- }
- if (!Corrected.isResolved()) continue;
+ if (DKind != OMPD_unknown && DKind != I->Directive) continue;
+ DSAVarData DVar = getDSA(I, D);
+ if (DVar.CKind == CKind)
+ return DVar;
+ }
+ return DSAVarData();
+}
+
+void Sema::InitDataSharingAttributesStack() {
+ VarDataSharingAttributesStack = new DSAStackTy(*this);
+}
+
+#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
+
+void Sema::DestroyDataSharingAttributesStack() {
+ delete DSAStack;
+}
+
+void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
+ const DeclarationNameInfo &DirName,
+ Scope *CurScope) {
+ DSAStack->push(DKind, DirName, CurScope);
+ PushExpressionEvaluationContext(PotentiallyEvaluated);
+}
+
+void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
+ DSAStack->pop();
+ DiscardCleanupsInEvaluationContext();
+ PopExpressionEvaluationContext();
+}
+
+namespace {
+
+class VarDeclFilterCCC : public CorrectionCandidateCallback {
+private:
+ Sema &Actions;
+public:
+ VarDeclFilterCCC(Sema &S) : Actions(S) { }
+ virtual bool ValidateCandidate(const TypoCorrection &Candidate) {
+ NamedDecl *ND = Candidate.getCorrectionDecl();
+ if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) {
+ return VD->hasGlobalStorage() &&
+ Actions.isDeclInScope(ND, Actions.getCurLexicalContext(),
+ Actions.getCurScope());
+ }
+ return false;
+ }
+};
+}
+
+ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
+ CXXScopeSpec &ScopeSpec,
+ const DeclarationNameInfo &Id) {
+ LookupResult Lookup(*this, Id, LookupOrdinaryName);
+ LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
+
+ if (Lookup.isAmbiguous())
+ return ExprError();
+
+ VarDecl *VD;
+ if (!Lookup.isSingleResult()) {
+ VarDeclFilterCCC Validator(*this);
+ if (TypoCorrection Corrected = CorrectTypo(Id, LookupOrdinaryName, CurScope,
+ 0, Validator)) {
+ diagnoseTypo(Corrected,
+ PDiag(Lookup.empty()? diag::err_undeclared_var_use_suggest
+ : diag::err_omp_expected_var_arg_suggest)
+ << Id.getName());
VD = Corrected.getCorrectionDeclAs<VarDecl>();
} else {
- if (!(VD = Lookup.getAsSingle<VarDecl>())) {
- Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest)
- << I->getName() << 0;
- Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
- continue;
- }
+ Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
+ : diag::err_omp_expected_var_arg)
+ << Id.getName();
+ return ExprError();
+ }
+ } else {
+ if (!(VD = Lookup.getAsSingle<VarDecl>())) {
+ Diag(Id.getLoc(), diag::err_omp_expected_var_arg)
+ << Id.getName();
+ Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
+ return ExprError();
}
+ }
+ Lookup.suppressDiagnostics();
- // OpenMP [2.9.2, Syntax, C/C++]
- // Variables must be file-scope, namespace-scope, or static block-scope.
- if (!VD->hasGlobalStorage()) {
- Diag(I->getLoc(), diag::err_omp_global_var_arg)
- << getOpenMPDirectiveName(OMPD_threadprivate)
- << !VD->isStaticLocal();
- Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
- continue;
- }
-
- // OpenMP [2.9.2, Restrictions, C/C++, p.2]
- // A threadprivate directive for file-scope variables must appear outside
- // any definition or declaration.
- // OpenMP [2.9.2, Restrictions, C/C++, p.3]
- // A threadprivate directive for static class member variables must appear
- // in the class definition, in the same scope in which the member
- // variables are declared.
- // OpenMP [2.9.2, Restrictions, C/C++, p.4]
- // A threadprivate directive for namespace-scope variables must appear
- // outside any definition or declaration other than the namespace
- // definition itself.
- // OpenMP [2.9.2, Restrictions, C/C++, p.6]
- // A threadprivate directive for static block-scope variables must appear
- // in the scope of the variable and not in a nested scope.
- NamedDecl *ND = cast<NamedDecl>(VD);
- if (!isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
- Diag(I->getLoc(), diag::err_omp_var_scope)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
- Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
- continue;
- }
-
- // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
- // A threadprivate directive must lexically precede all references to any
- // of the variables in its list.
- if (VD->isUsed()) {
- Diag(I->getLoc(), diag::err_omp_var_used)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
- continue;
- }
-
- QualType ExprType = VD->getType().getNonReferenceType();
- DeclRefExpr *Var = cast<DeclRefExpr>(BuildDeclRefExpr(VD,
- ExprType,
- VK_RValue,
- I->getLoc()).take());
- Vars.push_back(Var);
- }
- if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, Vars)) {
+ // OpenMP [2.9.2, Syntax, C/C++]
+ // Variables must be file-scope, namespace-scope, or static block-scope.
+ if (!VD->hasGlobalStorage()) {
+ Diag(Id.getLoc(), diag::err_omp_global_var_arg)
+ << getOpenMPDirectiveName(OMPD_threadprivate)
+ << !VD->isStaticLocal();
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD;
+ return ExprError();
+ }
+
+ VarDecl *CanonicalVD = VD->getCanonicalDecl();
+ NamedDecl *ND = cast<NamedDecl>(CanonicalVD);
+ // OpenMP [2.9.2, Restrictions, C/C++, p.2]
+ // A threadprivate directive for file-scope variables must appear outside
+ // any definition or declaration.
+ if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
+ !getCurLexicalContext()->isTranslationUnit()) {
+ Diag(Id.getLoc(), diag::err_omp_var_scope)
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
+ return ExprError();
+ }
+ // OpenMP [2.9.2, Restrictions, C/C++, p.3]
+ // A threadprivate directive for static class member variables must appear
+ // in the class definition, in the same scope in which the member
+ // variables are declared.
+ if (CanonicalVD->isStaticDataMember() &&
+ !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
+ Diag(Id.getLoc(), diag::err_omp_var_scope)
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
+ return ExprError();
+ }
+ // OpenMP [2.9.2, Restrictions, C/C++, p.4]
+ // A threadprivate directive for namespace-scope variables must appear
+ // outside any definition or declaration other than the namespace
+ // definition itself.
+ if (CanonicalVD->getDeclContext()->isNamespace() &&
+ (!getCurLexicalContext()->isFileContext() ||
+ !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
+ Diag(Id.getLoc(), diag::err_omp_var_scope)
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
+ return ExprError();
+ }
+ // OpenMP [2.9.2, Restrictions, C/C++, p.6]
+ // A threadprivate directive for static block-scope variables must appear
+ // in the scope of the variable and not in a nested scope.
+ if (CanonicalVD->isStaticLocal() && CurScope &&
+ !isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
+ Diag(Id.getLoc(), diag::err_omp_var_scope)
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
+ return ExprError();
+ }
+
+ // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
+ // A threadprivate directive must lexically precede all references to any
+ // of the variables in its list.
+ if (VD->isUsed()) {
+ Diag(Id.getLoc(), diag::err_omp_var_used)
+ << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+ return ExprError();
+ }
+
+ QualType ExprType = VD->getType().getNonReferenceType();
+ ExprResult DE = BuildDeclRefExpr(VD, ExprType, VK_RValue, Id.getLoc());
+ DSAStack->addDSA(VD, cast<DeclRefExpr>(DE.get()), OMPC_threadprivate);
+ return DE;
+}
+
+Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
+ SourceLocation Loc,
+ ArrayRef<Expr *> VarList) {
+ if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
CurContext->addDecl(D);
return DeclGroupPtrTy::make(DeclGroupRef(D));
}
@@ -141,18 +526,19 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
SourceLocation Loc,
- ArrayRef<DeclRefExpr *> VarList) {
- SmallVector<DeclRefExpr *, 5> Vars;
- for (ArrayRef<DeclRefExpr *>::iterator I = VarList.begin(),
+ ArrayRef<Expr *> VarList) {
+ SmallVector<Expr *, 8> Vars;
+ for (ArrayRef<Expr *>::iterator I = VarList.begin(),
E = VarList.end();
I != E; ++I) {
- VarDecl *VD = cast<VarDecl>((*I)->getDecl());
- SourceLocation ILoc = (*I)->getLocation();
+ DeclRefExpr *DE = cast<DeclRefExpr>(*I);
+ VarDecl *VD = cast<VarDecl>(DE->getDecl());
+ SourceLocation ILoc = DE->getExprLoc();
// OpenMP [2.9.2, Restrictions, C/C++, p.10]
// A threadprivate variable must not have an incomplete type.
if (RequireCompleteType(ILoc, VD->getType(),
- diag::err_omp_incomplete_type)) {
+ diag::err_omp_threadprivate_incomplete_type)) {
continue;
}
@@ -160,15 +546,22 @@ OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
// A threadprivate variable must not have a reference type.
if (VD->getType()->isReferenceType()) {
Diag(ILoc, diag::err_omp_ref_type_arg)
- << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
- Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
+ << getOpenMPDirectiveName(OMPD_threadprivate)
+ << VD->getType();
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
continue;
}
// Check if this is a TLS variable.
if (VD->getTLSKind()) {
Diag(ILoc, diag::err_omp_var_thread_local) << VD;
- Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
continue;
}
@@ -179,3 +572,591 @@ OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
getCurLexicalContext(),
Loc, Vars);
}
+
+namespace {
+class DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> {
+ DSAStackTy *Stack;
+ Sema &Actions;
+ bool ErrorFound;
+ CapturedStmt *CS;
+ llvm::SmallVector<Expr *, 8> ImplicitFirstprivate;
+public:
+ void VisitDeclRefExpr(DeclRefExpr *E) {
+ if(VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
+ // Skip internally declared variables.
+ if (VD->isLocalVarDecl() && !CS->capturesVariable(VD)) return;
+
+ SourceLocation ELoc = E->getExprLoc();
+
+ OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
+ DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD);
+ if (DVar.CKind != OMPC_unknown) {
+ if (DKind == OMPD_task && DVar.CKind != OMPC_shared &&
+ DVar.CKind != OMPC_threadprivate && !DVar.RefExpr)
+ ImplicitFirstprivate.push_back(DVar.RefExpr);
+ return;
+ }
+ // The default(none) clause requires that each variable that is referenced
+ // in the construct, and does not have a predetermined data-sharing
+ // attribute, must have its data-sharing attribute explicitly determined
+ // by being listed in a data-sharing attribute clause.
+ if (DVar.CKind == OMPC_unknown && Stack->getDefaultDSA() == DSA_none &&
+ (DKind == OMPD_parallel || DKind == OMPD_task)) {
+ ErrorFound = true;
+ Actions.Diag(ELoc, diag::err_omp_no_dsa_for_variable) << VD;
+ return;
+ }
+
+ // OpenMP [2.9.3.6, Restrictions, p.2]
+ // A list item that appears in a reduction clause of the innermost
+ // enclosing worksharing or parallel construct may not be accessed in an
+ // explicit task.
+ // TODO:
+
+ // Define implicit data-sharing attributes for task.
+ DVar = Stack->getImplicitDSA(VD);
+ if (DKind == OMPD_task && DVar.CKind != OMPC_shared)
+ ImplicitFirstprivate.push_back(DVar.RefExpr);
+ }
+ }
+ void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
+ for (ArrayRef<OMPClause *>::iterator I = S->clauses().begin(),
+ E = S->clauses().end();
+ I != E; ++I)
+ if (OMPClause *C = *I)
+ for (StmtRange R = C->children(); R; ++R)
+ if (Stmt *Child = *R)
+ Visit(Child);
+ }
+ void VisitStmt(Stmt *S) {
+ for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();
+ I != E; ++I)
+ if (Stmt *Child = *I)
+ if (!isa<OMPExecutableDirective>(Child))
+ Visit(Child);
+ }
+
+ bool isErrorFound() { return ErrorFound; }
+ ArrayRef<Expr *> getImplicitFirstprivate() { return ImplicitFirstprivate; }
+
+ DSAAttrChecker(DSAStackTy *S, Sema &Actions, CapturedStmt *CS)
+ : Stack(S), Actions(Actions), ErrorFound(false), CS(CS) { }
+};
+}
+
+StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+
+ StmtResult Res = StmtError();
+
+ // Check default data sharing attributes for referenced variables.
+ DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt));
+ DSAChecker.Visit(cast<CapturedStmt>(AStmt)->getCapturedStmt());
+ if (DSAChecker.isErrorFound())
+ return StmtError();
+ // Generate list of implicitly defined firstprivate variables.
+ llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
+ ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
+
+ bool ErrorFound = false;
+ if (!DSAChecker.getImplicitFirstprivate().empty()) {
+ if (OMPClause *Implicit =
+ ActOnOpenMPFirstprivateClause(DSAChecker.getImplicitFirstprivate(),
+ SourceLocation(), SourceLocation(),
+ SourceLocation())) {
+ ClausesWithImplicit.push_back(Implicit);
+ ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
+ DSAChecker.getImplicitFirstprivate().size();
+ } else
+ ErrorFound = true;
+ }
+
+ switch (Kind) {
+ case OMPD_parallel:
+ Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt,
+ StartLoc, EndLoc);
+ break;
+ case OMPD_threadprivate:
+ case OMPD_task:
+ llvm_unreachable("OpenMP Directive is not allowed");
+ case OMPD_unknown:
+ case NUM_OPENMP_DIRECTIVES:
+ llvm_unreachable("Unknown OpenMP directive");
+ }
+
+ if (ErrorFound) return StmtError();
+ return Res;
+}
+
+StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return Owned(OMPParallelDirective::Create(Context, StartLoc, EndLoc,
+ Clauses, AStmt));
+}
+
+OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
+ unsigned Argument,
+ SourceLocation ArgumentLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ OMPClause *Res = 0;
+ switch (Kind) {
+ case OMPC_default:
+ Res =
+ ActOnOpenMPDefaultClause(static_cast<OpenMPDefaultClauseKind>(Argument),
+ ArgumentLoc, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_private:
+ case OMPC_firstprivate:
+ case OMPC_shared:
+ case OMPC_threadprivate:
+ case OMPC_unknown:
+ case NUM_OPENMP_CLAUSES:
+ llvm_unreachable("Clause is not allowed.");
+ }
+ return Res;
+}
+
+OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
+ SourceLocation KindKwLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ if (Kind == OMPC_DEFAULT_unknown) {
+ std::string Values;
+ std::string Sep(NUM_OPENMP_DEFAULT_KINDS > 1 ? ", " : "");
+ for (unsigned i = OMPC_DEFAULT_unknown + 1;
+ i < NUM_OPENMP_DEFAULT_KINDS; ++i) {
+ Values += "'";
+ Values += getOpenMPSimpleClauseTypeName(OMPC_default, i);
+ Values += "'";
+ switch (i) {
+ case NUM_OPENMP_DEFAULT_KINDS - 2:
+ Values += " or ";
+ break;
+ case NUM_OPENMP_DEFAULT_KINDS - 1:
+ break;
+ default:
+ Values += Sep;
+ break;
+ }
+ }
+ Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
+ << Values << getOpenMPClauseName(OMPC_default);
+ return 0;
+ }
+ switch (Kind) {
+ case OMPC_DEFAULT_none:
+ DSAStack->setDefaultDSANone();
+ break;
+ case OMPC_DEFAULT_shared:
+ DSAStack->setDefaultDSAShared();
+ break;
+ default:
+ break;
+ }
+ return new (Context) OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc,
+ EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
+ ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ OMPClause *Res = 0;
+ switch (Kind) {
+ case OMPC_private:
+ Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_firstprivate:
+ Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_shared:
+ Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_default:
+ case OMPC_threadprivate:
+ case OMPC_unknown:
+ case NUM_OPENMP_CLAUSES:
+ llvm_unreachable("Clause is not allowed.");
+ }
+ return Res;
+}
+
+OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ SmallVector<Expr *, 8> Vars;
+ for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
+ I != E; ++I) {
+ assert(*I && "NULL expr in OpenMP private clause.");
+ if (isa<DependentScopeDeclRefExpr>(*I)) {
+ // It will be analyzed later.
+ Vars.push_back(*I);
+ continue;
+ }
+
+ SourceLocation ELoc = (*I)->getExprLoc();
+ // OpenMP [2.1, C/C++]
+ // A list item is a variable name.
+ // OpenMP [2.9.3.3, Restrictions, p.1]
+ // A variable that is part of another variable (as an array or
+ // structure element) cannot appear in a private clause.
+ DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I);
+ if (!DE || !isa<VarDecl>(DE->getDecl())) {
+ Diag(ELoc, diag::err_omp_expected_var_name)
+ << (*I)->getSourceRange();
+ continue;
+ }
+ Decl *D = DE->getDecl();
+ VarDecl *VD = cast<VarDecl>(D);
+
+ QualType Type = VD->getType();
+ if (Type->isDependentType() || Type->isInstantiationDependentType()) {
+ // It will be analyzed later.
+ Vars.push_back(DE);
+ continue;
+ }
+
+ // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
+ // A variable that appears in a private clause must not have an incomplete
+ // type or a reference type.
+ if (RequireCompleteType(ELoc, Type,
+ diag::err_omp_private_incomplete_type)) {
+ continue;
+ }
+ if (Type->isReferenceType()) {
+ Diag(ELoc, diag::err_omp_clause_ref_type_arg)
+ << getOpenMPClauseName(OMPC_private) << Type;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
+ continue;
+ }
+
+ // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
+ // A variable of class type (or array thereof) that appears in a private
+ // clause requires an accesible, unambiguous default constructor for the
+ // class type.
+ while (Type.getNonReferenceType()->isArrayType()) {
+ Type = cast<ArrayType>(
+ Type.getNonReferenceType().getTypePtr())->getElementType();
+ }
+ CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
+ Type.getNonReferenceType()->getAsCXXRecordDecl() : 0;
+ if (RD) {
+ CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
+ PartialDiagnostic PD =
+ PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
+ if (!CD ||
+ CheckConstructorAccess(ELoc, CD,
+ InitializedEntity::InitializeTemporary(Type),
+ CD->getAccess(), PD) == AR_inaccessible ||
+ CD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_private) << 0;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
+ Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+ continue;
+ }
+ MarkFunctionReferenced(ELoc, CD);
+ DiagnoseUseOfDecl(CD, ELoc);
+
+ CXXDestructorDecl *DD = RD->getDestructor();
+ if (DD) {
+ if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
+ DD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_private) << 4;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
+ Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+ continue;
+ }
+ MarkFunctionReferenced(ELoc, DD);
+ DiagnoseUseOfDecl(DD, ELoc);
+ }
+ }
+
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct]
+ // Variables with the predetermined data-sharing attributes may not be
+ // listed in data-sharing attributes clauses, except for the cases
+ // listed below. For these exceptions only, listing a predetermined
+ // variable in a data-sharing attribute clause is allowed and overrides
+ // the variable's predetermined data-sharing attributes.
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+ if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
+ Diag(ELoc, diag::err_omp_wrong_dsa)
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_private);
+ if (DVar.RefExpr) {
+ Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
+ << getOpenMPClauseName(DVar.CKind);
+ } else {
+ Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
+ << getOpenMPClauseName(DVar.CKind);
+ }
+ continue;
+ }
+
+ DSAStack->addDSA(VD, DE, OMPC_private);
+ Vars.push_back(DE);
+ }
+
+ if (Vars.empty()) return 0;
+
+ return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
+}
+
+OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ SmallVector<Expr *, 8> Vars;
+ for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
+ I != E; ++I) {
+ assert(*I && "NULL expr in OpenMP firstprivate clause.");
+ if (isa<DependentScopeDeclRefExpr>(*I)) {
+ // It will be analyzed later.
+ Vars.push_back(*I);
+ continue;
+ }
+
+ SourceLocation ELoc = (*I)->getExprLoc();
+ // OpenMP [2.1, C/C++]
+ // A list item is a variable name.
+ // OpenMP [2.9.3.3, Restrictions, p.1]
+ // A variable that is part of another variable (as an array or
+ // structure element) cannot appear in a private clause.
+ DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I);
+ if (!DE || !isa<VarDecl>(DE->getDecl())) {
+ Diag(ELoc, diag::err_omp_expected_var_name)
+ << (*I)->getSourceRange();
+ continue;
+ }
+ Decl *D = DE->getDecl();
+ VarDecl *VD = cast<VarDecl>(D);
+
+ QualType Type = VD->getType();
+ if (Type->isDependentType() || Type->isInstantiationDependentType()) {
+ // It will be analyzed later.
+ Vars.push_back(DE);
+ continue;
+ }
+
+ // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
+ // A variable that appears in a private clause must not have an incomplete
+ // type or a reference type.
+ if (RequireCompleteType(ELoc, Type,
+ diag::err_omp_firstprivate_incomplete_type)) {
+ continue;
+ }
+ if (Type->isReferenceType()) {
+ Diag(ELoc, diag::err_omp_clause_ref_type_arg)
+ << getOpenMPClauseName(OMPC_firstprivate) << Type;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
+ continue;
+ }
+
+ // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
+ // A variable of class type (or array thereof) that appears in a private
+ // clause requires an accesible, unambiguous copy constructor for the
+ // class type.
+ Type = Context.getBaseElementType(Type);
+ CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
+ Type.getNonReferenceType()->getAsCXXRecordDecl() : 0;
+ if (RD) {
+ CXXConstructorDecl *CD = LookupCopyingConstructor(RD, 0);
+ PartialDiagnostic PD =
+ PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
+ if (!CD ||
+ CheckConstructorAccess(ELoc, CD,
+ InitializedEntity::InitializeTemporary(Type),
+ CD->getAccess(), PD) == AR_inaccessible ||
+ CD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_firstprivate) << 1;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
+ Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+ continue;
+ }
+ MarkFunctionReferenced(ELoc, CD);
+ DiagnoseUseOfDecl(CD, ELoc);
+
+ CXXDestructorDecl *DD = RD->getDestructor();
+ if (DD) {
+ if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
+ DD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_firstprivate) << 4;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+ diag::note_defined_here) << VD;
+ Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+ continue;
+ }
+ MarkFunctionReferenced(ELoc, DD);
+ DiagnoseUseOfDecl(DD, ELoc);
+ }
+ }
+
+ // If StartLoc and EndLoc are invalid - this is an implicit firstprivate
+ // variable and it was checked already.
+ if (StartLoc.isValid() && EndLoc.isValid()) {
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+ Type = Type.getNonReferenceType().getCanonicalType();
+ bool IsConstant = Type.isConstant(Context);
+ Type = Context.getBaseElementType(Type);
+ // OpenMP [2.4.13, Data-sharing Attribute Clauses]
+ // A list item that specifies a given variable may not appear in more
+ // than one clause on the same directive, except that a variable may be
+ // specified in both firstprivate and lastprivate clauses.
+ // TODO: add processing for lastprivate.
+ if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
+ DVar.RefExpr) {
+ Diag(ELoc, diag::err_omp_wrong_dsa)
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_firstprivate);
+ Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
+ << getOpenMPClauseName(DVar.CKind);
+ continue;
+ }
+
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct]
+ // Variables with the predetermined data-sharing attributes may not be
+ // listed in data-sharing attributes clauses, except for the cases
+ // listed below. For these exceptions only, listing a predetermined
+ // variable in a data-sharing attribute clause is allowed and overrides
+ // the variable's predetermined data-sharing attributes.
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, C/C++, p.2]
+ // Variables with const-qualified type having no mutable member may be
+ // listed in a firstprivate clause, even if they are static data members.
+ if (!(IsConstant || VD->isStaticDataMember()) && !DVar.RefExpr &&
+ DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
+ Diag(ELoc, diag::err_omp_wrong_dsa)
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_firstprivate);
+ Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
+ << getOpenMPClauseName(DVar.CKind);
+ continue;
+ }
+
+ // OpenMP [2.9.3.4, Restrictions, p.2]
+ // A list item that is private within a parallel region must not appear
+ // in a firstprivate clause on a worksharing construct if any of the
+ // worksharing regions arising from the worksharing construct ever bind
+ // to any of the parallel regions arising from the parallel construct.
+ // OpenMP [2.9.3.4, Restrictions, p.3]
+ // A list item that appears in a reduction clause of a parallel construct
+ // must not appear in a firstprivate clause on a worksharing or task
+ // construct if any of the worksharing or task regions arising from the
+ // worksharing or task construct ever bind to any of the parallel regions
+ // arising from the parallel construct.
+ // OpenMP [2.9.3.4, Restrictions, p.4]
+ // A list item that appears in a reduction clause in worksharing
+ // construct must not appear in a firstprivate clause in a task construct
+ // encountered during execution of any of the worksharing regions arising
+ // from the worksharing construct.
+ // TODO:
+ }
+
+ DSAStack->addDSA(VD, DE, OMPC_firstprivate);
+ Vars.push_back(DE);
+ }
+
+ if (Vars.empty()) return 0;
+
+ return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
+ Vars);
+}
+
+OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ SmallVector<Expr *, 8> Vars;
+ for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
+ I != E; ++I) {
+ assert(*I && "NULL expr in OpenMP shared clause.");
+ if (isa<DependentScopeDeclRefExpr>(*I)) {
+ // It will be analyzed later.
+ Vars.push_back(*I);
+ continue;
+ }
+
+ SourceLocation ELoc = (*I)->getExprLoc();
+ // OpenMP [2.1, C/C++]
+ // A list item is a variable name.
+ // OpenMP [2.9.3.4, Restrictions, p.1]
+ // A variable that is part of another variable (as an array or
+ // structure element) cannot appear in a private clause.
+ DeclRefExpr *DE = dyn_cast<DeclRefExpr>(*I);
+ if (!DE || !isa<VarDecl>(DE->getDecl())) {
+ Diag(ELoc, diag::err_omp_expected_var_name)
+ << (*I)->getSourceRange();
+ continue;
+ }
+ Decl *D = DE->getDecl();
+ VarDecl *VD = cast<VarDecl>(D);
+
+ QualType Type = VD->getType();
+ if (Type->isDependentType() || Type->isInstantiationDependentType()) {
+ // It will be analyzed later.
+ Vars.push_back(DE);
+ continue;
+ }
+
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct]
+ // Variables with the predetermined data-sharing attributes may not be
+ // listed in data-sharing attributes clauses, except for the cases
+ // listed below. For these exceptions only, listing a predetermined
+ // variable in a data-sharing attribute clause is allowed and overrides
+ // the variable's predetermined data-sharing attributes.
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+ if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared && DVar.RefExpr) {
+ Diag(ELoc, diag::err_omp_wrong_dsa)
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_shared);
+ Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
+ << getOpenMPClauseName(DVar.CKind);
+ continue;
+ }
+
+ DSAStack->addDSA(VD, DE, OMPC_shared);
+ Vars.push_back(DE);
+ }
+
+ if (Vars.empty()) return 0;
+
+ return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
+}
+
+#undef DSAStack
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
index 529ba127cbab..802f2b7290b3 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
@@ -43,8 +44,15 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl,
SourceLocation Loc = SourceLocation(),
const DeclarationNameLoc &LocInfo = DeclarationNameLoc()){
if (S.DiagnoseUseOfDecl(FoundDecl, Loc))
+ return ExprError();
+ // If FoundDecl is different from Fn (such as if one is a template
+ // and the other a specialization), make sure DiagnoseUseOfDecl is
+ // called on both.
+ // FIXME: This would be more comprehensively addressed by modifying
+ // DiagnoseUseOfDecl to accept both the FoundDecl and the decl
+ // being used.
+ if (FoundDecl != Fn && S.DiagnoseUseOfDecl(Fn, Loc))
return ExprError();
-
DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, false, Fn->getType(),
VK_LValue, Loc, LocInfo);
if (HadMultipleCandidates)
@@ -74,7 +82,8 @@ static OverloadingResult
IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
UserDefinedConversionSequence& User,
OverloadCandidateSet& Conversions,
- bool AllowExplicit);
+ bool AllowExplicit,
+ bool AllowObjCConversionOnExplicit);
static ImplicitConversionSequence::CompareKind
@@ -441,9 +450,9 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
}
}
-/// DebugPrint - Print this standard conversion sequence to standard
+/// dump - Print this standard conversion sequence to standard
/// error. Useful for debugging overloading issues.
-void StandardConversionSequence::DebugPrint() const {
+void StandardConversionSequence::dump() const {
raw_ostream &OS = llvm::errs();
bool PrintedSomething = false;
if (First != ICK_Identity) {
@@ -480,12 +489,12 @@ void StandardConversionSequence::DebugPrint() const {
}
}
-/// DebugPrint - Print this user-defined conversion sequence to standard
+/// dump - Print this user-defined conversion sequence to standard
/// error. Useful for debugging overloading issues.
-void UserDefinedConversionSequence::DebugPrint() const {
+void UserDefinedConversionSequence::dump() const {
raw_ostream &OS = llvm::errs();
if (Before.First || Before.Second || Before.Third) {
- Before.DebugPrint();
+ Before.dump();
OS << " -> ";
}
if (ConversionFunction)
@@ -494,22 +503,24 @@ void UserDefinedConversionSequence::DebugPrint() const {
OS << "aggregate initialization";
if (After.First || After.Second || After.Third) {
OS << " -> ";
- After.DebugPrint();
+ After.dump();
}
}
-/// DebugPrint - Print this implicit conversion sequence to standard
+/// dump - Print this implicit conversion sequence to standard
/// error. Useful for debugging overloading issues.
-void ImplicitConversionSequence::DebugPrint() const {
+void ImplicitConversionSequence::dump() const {
raw_ostream &OS = llvm::errs();
+ if (isStdInitializerListElement())
+ OS << "Worst std::initializer_list element conversion: ";
switch (ConversionKind) {
case StandardConversion:
OS << "Standard conversion: ";
- Standard.DebugPrint();
+ Standard.dump();
break;
case UserDefinedConversion:
OS << "User-defined conversion: ";
- UserDefined.DebugPrint();
+ UserDefined.dump();
break;
case EllipsisConversion:
OS << "Ellipsis conversion";
@@ -541,13 +552,13 @@ AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) {
}
namespace {
- // Structure used by OverloadCandidate::DeductionFailureInfo to store
+ // Structure used by DeductionFailureInfo to store
// template argument information.
struct DFIArguments {
TemplateArgument FirstArg;
TemplateArgument SecondArg;
};
- // Structure used by OverloadCandidate::DeductionFailureInfo to store
+ // Structure used by DeductionFailureInfo to store
// template parameter and template argument information.
struct DFIParamWithArguments : DFIArguments {
TemplateParameter Param;
@@ -556,11 +567,10 @@ namespace {
/// \brief Convert from Sema's representation of template deduction information
/// to the form used in overload-candidate information.
-OverloadCandidate::DeductionFailureInfo
-static MakeDeductionFailureInfo(ASTContext &Context,
- Sema::TemplateDeductionResult TDK,
- TemplateDeductionInfo &Info) {
- OverloadCandidate::DeductionFailureInfo Result;
+DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context,
+ Sema::TemplateDeductionResult TDK,
+ TemplateDeductionInfo &Info) {
+ DeductionFailureInfo Result;
Result.Result = static_cast<unsigned>(TDK);
Result.HasDiagnostic = false;
Result.Data = 0;
@@ -618,7 +628,7 @@ static MakeDeductionFailureInfo(ASTContext &Context,
return Result;
}
-void OverloadCandidate::DeductionFailureInfo::Destroy() {
+void DeductionFailureInfo::Destroy() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
@@ -652,15 +662,13 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
}
}
-PartialDiagnosticAt *
-OverloadCandidate::DeductionFailureInfo::getSFINAEDiagnostic() {
+PartialDiagnosticAt *DeductionFailureInfo::getSFINAEDiagnostic() {
if (HasDiagnostic)
return static_cast<PartialDiagnosticAt*>(static_cast<void*>(Diagnostic));
return 0;
}
-TemplateParameter
-OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
+TemplateParameter DeductionFailureInfo::getTemplateParameter() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
@@ -688,8 +696,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
return TemplateParameter();
}
-TemplateArgumentList *
-OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
+TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
@@ -715,7 +722,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
return 0;
}
-const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
+const TemplateArgument *DeductionFailureInfo::getFirstArg() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
@@ -741,8 +748,7 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
return 0;
}
-const TemplateArgument *
-OverloadCandidate::DeductionFailureInfo::getSecondArg() {
+const TemplateArgument *DeductionFailureInfo::getSecondArg() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
@@ -768,8 +774,7 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
return 0;
}
-Expr *
-OverloadCandidate::DeductionFailureInfo::getExpr() {
+Expr *DeductionFailureInfo::getExpr() {
if (static_cast<Sema::TemplateDeductionResult>(Result) ==
Sema::TDK_FailedOverloadResolution)
return static_cast<Expr*>(Data);
@@ -854,11 +859,11 @@ static bool checkPlaceholderForOverload(Sema &S, Expr *&E,
/// checkArgPlaceholdersForOverload - Check a set of call operands for
/// placeholders.
-static bool checkArgPlaceholdersForOverload(Sema &S, Expr **args,
- unsigned numArgs,
+static bool checkArgPlaceholdersForOverload(Sema &S,
+ MultiExprArg Args,
UnbridgedCastsSet &unbridged) {
- for (unsigned i = 0; i != numArgs; ++i)
- if (checkPlaceholderForOverload(S, args[i], &unbridged))
+ for (unsigned i = 0, e = Args.size(); i != e; ++i)
+ if (checkPlaceholderForOverload(S, Args[i], &unbridged))
return true;
return false;
@@ -970,21 +975,16 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
return Ovl_Overload;
}
-static bool canBeOverloaded(const FunctionDecl &D) {
- if (D.getAttr<OverloadableAttr>())
- return true;
- if (D.isExternC())
+bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
+ bool UseUsingDeclRules) {
+ // C++ [basic.start.main]p2: This function shall not be overloaded.
+ if (New->isMain())
return false;
- // Main cannot be overloaded (basic.start.main).
- if (D.isMain())
+ // MSVCRT user defined entry points cannot be overloaded.
+ if (New->isMSVCRTEntryPoint())
return false;
- return true;
-}
-
-static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
- bool UseUsingDeclRules) {
FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
@@ -995,8 +995,8 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
return true;
// Is the function New an overload of the function Old?
- QualType OldQType = S.Context.getCanonicalType(Old->getType());
- QualType NewQType = S.Context.getCanonicalType(New->getType());
+ QualType OldQType = Context.getCanonicalType(Old->getType());
+ QualType NewQType = Context.getCanonicalType(New->getType());
// Compare the signatures (C++ 1.3.10) of the two functions to
// determine whether they are overloads. If we find any mismatch
@@ -1017,7 +1017,7 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
if (OldQType != NewQType &&
(OldType->getNumArgs() != NewType->getNumArgs() ||
OldType->isVariadic() != NewType->isVariadic() ||
- !S.FunctionArgTypesAreEqual(OldType, NewType)))
+ !FunctionArgTypesAreEqual(OldType, NewType)))
return true;
// C++ [temp.over.link]p4:
@@ -1033,9 +1033,9 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
// However, we don't consider either of these when deciding whether
// a member introduced by a shadow declaration is hidden.
if (!UseUsingDeclRules && NewTemplate &&
- (!S.TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
- OldTemplate->getTemplateParameters(),
- false, S.TPL_TemplateMatch) ||
+ (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
+ OldTemplate->getTemplateParameters(),
+ false, TPL_TemplateMatch) ||
OldType->getResultType() != NewType->getResultType()))
return true;
@@ -1061,9 +1061,9 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
// declarations with the same name, the same parameter-type-list, and
// the same template parameter lists cannot be overloaded if any of
// them, but not all, have a ref-qualifier (8.3.5).
- S.Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
+ Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
<< NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
- S.Diag(OldMethod->getLocation(), diag::note_previous_declaration);
+ Diag(OldMethod->getLocation(), diag::note_previous_declaration);
}
return true;
}
@@ -1072,10 +1072,16 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
// function yet (because we haven't yet resolved whether this is a static
// or non-static member function). Add it now, on the assumption that this
// is a redeclaration of OldMethod.
+ unsigned OldQuals = OldMethod->getTypeQualifiers();
unsigned NewQuals = NewMethod->getTypeQualifiers();
- if (NewMethod->isConstexpr() && !isa<CXXConstructorDecl>(NewMethod))
+ if (!getLangOpts().CPlusPlus1y && NewMethod->isConstexpr() &&
+ !isa<CXXConstructorDecl>(NewMethod))
NewQuals |= Qualifiers::Const;
- if (OldMethod->getTypeQualifiers() != NewQuals)
+
+ // We do not allow overloading based off of '__restrict'.
+ OldQuals &= ~Qualifiers::Restrict;
+ NewQuals &= ~Qualifiers::Restrict;
+ if (OldQuals != NewQuals)
return true;
}
@@ -1083,19 +1089,6 @@ static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
return false;
}
-bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
- bool UseUsingDeclRules) {
- if (!shouldTryToOverload(*this, New, Old, UseUsingDeclRules))
- return false;
-
- // If both of the functions are extern "C", then they are not
- // overloads.
- if (!canBeOverloaded(*Old) && !canBeOverloaded(*New))
- return false;
-
- return true;
-}
-
/// \brief Checks availability of the function depending on the current
/// function context. Inside an unavailable function, unavailability is ignored.
///
@@ -1115,7 +1108,8 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
bool AllowExplicit,
bool InOverloadResolution,
bool CStyle,
- bool AllowObjCWritebackConversion) {
+ bool AllowObjCWritebackConversion,
+ bool AllowObjCConversionOnExplicit) {
ImplicitConversionSequence ICS;
if (SuppressUserConversions) {
@@ -1129,7 +1123,7 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
OverloadCandidateSet Conversions(From->getExprLoc());
OverloadingResult UserDefResult
= IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions,
- AllowExplicit);
+ AllowExplicit, AllowObjCConversionOnExplicit);
if (UserDefResult == OR_Success) {
ICS.setUserDefined();
@@ -1218,7 +1212,8 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
bool AllowExplicit,
bool InOverloadResolution,
bool CStyle,
- bool AllowObjCWritebackConversion) {
+ bool AllowObjCWritebackConversion,
+ bool AllowObjCConversionOnExplicit) {
ImplicitConversionSequence ICS;
if (IsStandardConversion(S, From, ToType, InOverloadResolution,
ICS.Standard, CStyle, AllowObjCWritebackConversion)){
@@ -1262,7 +1257,8 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
return TryUserDefinedConversion(S, From, ToType, SuppressUserConversions,
AllowExplicit, InOverloadResolution, CStyle,
- AllowObjCWritebackConversion);
+ AllowObjCWritebackConversion,
+ AllowObjCConversionOnExplicit);
}
ImplicitConversionSequence
@@ -1275,7 +1271,8 @@ Sema::TryImplicitConversion(Expr *From, QualType ToType,
return clang::TryImplicitConversion(*this, From, ToType,
SuppressUserConversions, AllowExplicit,
InOverloadResolution, CStyle,
- AllowObjCWritebackConversion);
+ AllowObjCWritebackConversion,
+ /*AllowObjCConversionOnExplicit=*/false);
}
/// PerformImplicitConversion - Perform an implicit conversion of the
@@ -1307,7 +1304,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
AllowExplicit,
/*InOverloadResolution=*/false,
/*CStyle=*/false,
- AllowObjCWritebackConversion);
+ AllowObjCWritebackConversion,
+ /*AllowObjCConversionOnExplicit=*/false);
return PerformImplicitConversion(From, ToType, ICS, Action);
}
@@ -1591,7 +1589,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// Integral conversions (C++ 4.7).
SCS.Second = ICK_Integral_Conversion;
FromType = ToType.getUnqualifiedType();
- } else if (FromType->isAnyComplexType() && ToType->isComplexType()) {
+ } else if (FromType->isAnyComplexType() && ToType->isAnyComplexType()) {
// Complex conversions (C99 6.3.1.6)
SCS.Second = ICK_Complex_Conversion;
FromType = ToType.getUnqualifiedType();
@@ -2596,48 +2594,16 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
/// FunctionArgTypesAreEqual - This routine checks two function proto types
/// for equality of their argument types. Caller has already checked that
-/// they have same number of arguments. This routine assumes that Objective-C
-/// pointer types which only differ in their protocol qualifiers are equal.
-/// If the parameters are different, ArgPos will have the parameter index
-/// of the first different parameter.
+/// they have same number of arguments. If the parameters are different,
+/// ArgPos will have the parameter index of the first different parameter.
bool Sema::FunctionArgTypesAreEqual(const FunctionProtoType *OldType,
const FunctionProtoType *NewType,
unsigned *ArgPos) {
- if (!getLangOpts().ObjC1) {
- for (FunctionProtoType::arg_type_iterator O = OldType->arg_type_begin(),
- N = NewType->arg_type_begin(),
- E = OldType->arg_type_end(); O && (O != E); ++O, ++N) {
- if (!Context.hasSameType(*O, *N)) {
- if (ArgPos) *ArgPos = O - OldType->arg_type_begin();
- return false;
- }
- }
- return true;
- }
-
for (FunctionProtoType::arg_type_iterator O = OldType->arg_type_begin(),
N = NewType->arg_type_begin(),
E = OldType->arg_type_end(); O && (O != E); ++O, ++N) {
- QualType ToType = (*O);
- QualType FromType = (*N);
- if (!Context.hasSameType(ToType, FromType)) {
- if (const PointerType *PTTo = ToType->getAs<PointerType>()) {
- if (const PointerType *PTFr = FromType->getAs<PointerType>())
- if ((PTTo->getPointeeType()->isObjCQualifiedIdType() &&
- PTFr->getPointeeType()->isObjCQualifiedIdType()) ||
- (PTTo->getPointeeType()->isObjCQualifiedClassType() &&
- PTFr->getPointeeType()->isObjCQualifiedClassType()))
- continue;
- }
- else if (const ObjCObjectPointerType *PTTo =
- ToType->getAs<ObjCObjectPointerType>()) {
- if (const ObjCObjectPointerType *PTFr =
- FromType->getAs<ObjCObjectPointerType>())
- if (Context.hasSameUnqualifiedType(
- PTTo->getObjectType()->getBaseType(),
- PTFr->getObjectType()->getBaseType()))
- continue;
- }
+ if (!Context.hasSameType(O->getUnqualifiedType(),
+ N->getUnqualifiedType())) {
if (ArgPos) *ArgPos = O - OldType->arg_type_begin();
return false;
}
@@ -2824,6 +2790,18 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
return false;
}
+/// Determine whether the lifetime conversion between the two given
+/// qualifiers sets is nontrivial.
+static bool isNonTrivialObjCLifetimeConversion(Qualifiers FromQuals,
+ Qualifiers ToQuals) {
+ // Converting anything to const __unsafe_unretained is trivial.
+ if (ToQuals.hasConst() &&
+ ToQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
+ return false;
+
+ return true;
+}
+
/// IsQualificationConversion - Determines whether the conversion from
/// an rvalue of type FromType to ToType is a qualification conversion
/// (C++ 4.4).
@@ -2865,7 +2843,8 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
if (FromQuals.getObjCLifetime() != ToQuals.getObjCLifetime() &&
UnwrappedAnyPointer) {
if (ToQuals.compatiblyIncludesObjCLifetime(FromQuals)) {
- ObjCLifetimeConversion = true;
+ if (isNonTrivialObjCLifetimeConversion(FromQuals, ToQuals))
+ ObjCLifetimeConversion = true;
FromQuals.removeObjCLifetime();
ToQuals.removeObjCLifetime();
} else {
@@ -3030,11 +3009,18 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
/// \param AllowExplicit true if the conversion should consider C++0x
/// "explicit" conversion functions as well as non-explicit conversion
/// functions (C++0x [class.conv.fct]p2).
+///
+/// \param AllowObjCConversionOnExplicit true if the conversion should
+/// allow an extra Objective-C pointer conversion on uses of explicit
+/// constructors. Requires \c AllowExplicit to also be set.
static OverloadingResult
IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
UserDefinedConversionSequence &User,
OverloadCandidateSet &CandidateSet,
- bool AllowExplicit) {
+ bool AllowExplicit,
+ bool AllowObjCConversionOnExplicit) {
+ assert(AllowExplicit || !AllowObjCConversionOnExplicit);
+
// Whether we will only visit constructors.
bool ConstructorsOnly = false;
@@ -3067,7 +3053,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
unsigned NumArgs = 1;
bool ListInitializing = false;
if (InitListExpr *InitList = dyn_cast<InitListExpr>(From)) {
- // But first, see if there is an init-list-contructor that will work.
+ // But first, see if there is an init-list-constructor that will work.
OverloadingResult Result = IsInitializerListConstructorConversion(
S, From, ToType, ToRecordDecl, User, CandidateSet, AllowExplicit);
if (Result != OR_No_Viable_Function)
@@ -3161,10 +3147,12 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
if (ConvTemplate)
S.AddTemplateConversionCandidate(ConvTemplate, FoundDecl,
ActingContext, From, ToType,
- CandidateSet);
+ CandidateSet,
+ AllowObjCConversionOnExplicit);
else
S.AddConversionCandidate(Conv, FoundDecl, ActingContext,
- From, ToType, CandidateSet);
+ From, ToType, CandidateSet,
+ AllowObjCConversionOnExplicit);
}
}
}
@@ -3251,15 +3239,19 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
OverloadCandidateSet CandidateSet(From->getExprLoc());
OverloadingResult OvResult =
IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined,
- CandidateSet, false);
+ CandidateSet, false, false);
if (OvResult == OR_Ambiguous)
Diag(From->getLocStart(),
diag::err_typecheck_ambiguous_condition)
<< From->getType() << ToType << From->getSourceRange();
- else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty())
- Diag(From->getLocStart(),
- diag::err_typecheck_nonviable_condition)
- << From->getType() << ToType << From->getSourceRange();
+ else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) {
+ if (!RequireCompleteType(From->getLocStart(), ToType,
+ diag::err_typecheck_nonviable_condition_incomplete,
+ From->getType(), From->getSourceRange()))
+ Diag(From->getLocStart(),
+ diag::err_typecheck_nonviable_condition)
+ << From->getType() << From->getSourceRange() << ToType;
+ }
else
return false;
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From);
@@ -3364,9 +3356,7 @@ CompareImplicitConversionSequences(Sema &S,
// list-initialization sequence L2 if L1 converts to std::initializer_list<X>
// for some X and L2 does not.
if (Result == ImplicitConversionSequence::Indistinguishable &&
- !ICS1.isBad() &&
- ICS1.isListInitializationSequence() &&
- ICS2.isListInitializationSequence()) {
+ !ICS1.isBad()) {
if (ICS1.isStdInitializerListElement() &&
!ICS2.isStdInitializerListElement())
return ImplicitConversionSequence::Better;
@@ -4019,9 +4009,11 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
// space 2.
if (T1Quals.getObjCLifetime() != T2Quals.getObjCLifetime() &&
T1Quals.compatiblyIncludesObjCLifetime(T2Quals)) {
+ if (isNonTrivialObjCLifetimeConversion(T2Quals, T1Quals))
+ ObjCLifetimeConversion = true;
+
T1Quals.removeObjCLifetime();
T2Quals.removeObjCLifetime();
- ObjCLifetimeConversion = true;
}
if (T1Quals == T2Quals)
@@ -4105,10 +4097,12 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
if (ConvTemplate)
S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC,
- Init, DeclType, CandidateSet);
+ Init, DeclType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/false);
else
S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
- DeclType, CandidateSet);
+ DeclType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/false);
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
@@ -4390,7 +4384,8 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
/*AllowExplicit=*/false,
/*InOverloadResolution=*/false,
/*CStyle=*/false,
- /*AllowObjCWritebackConversion=*/false);
+ /*AllowObjCWritebackConversion=*/false,
+ /*AllowObjCConversionOnExplicit=*/false);
// Of course, that's still a reference binding.
if (ICS.isStandard()) {
@@ -4445,7 +4440,6 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
ImplicitConversionSequence Result;
Result.setBad(BadConversionSequence::no_conversion, From, ToType);
- Result.setListInitializationSequence();
// We need a complete type for what follows. Incomplete types can never be
// initialized from init lists.
@@ -4491,7 +4485,6 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
Result.Standard.setAllToTypes(ToType);
}
- Result.setListInitializationSequence();
Result.setStdInitializerListElement(toStdInitializerList);
return Result;
}
@@ -4504,12 +4497,11 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
// implicit conversion sequence is a user-defined conversion sequence.
if (ToType->isRecordType() && !ToType->isAggregateType()) {
// This function can deal with initializer lists.
- Result = TryUserDefinedConversion(S, From, ToType, SuppressUserConversions,
- /*AllowExplicit=*/false,
- InOverloadResolution, /*CStyle=*/false,
- AllowObjCWritebackConversion);
- Result.setListInitializationSequence();
- return Result;
+ return TryUserDefinedConversion(S, From, ToType, SuppressUserConversions,
+ /*AllowExplicit=*/false,
+ InOverloadResolution, /*CStyle=*/false,
+ AllowObjCWritebackConversion,
+ /*AllowObjCConversionOnExplicit=*/false);
}
// C++11 [over.ics.list]p4:
@@ -4572,11 +4564,11 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
= S.CompareReferenceRelationship(From->getLocStart(), T1, T2, dummy1,
dummy2, dummy3);
- if (RefRelationship >= Sema::Ref_Related)
- return TryReferenceInit(S, Init, ToType,
- /*FIXME:*/From->getLocStart(),
+ if (RefRelationship >= Sema::Ref_Related) {
+ return TryReferenceInit(S, Init, ToType, /*FIXME*/From->getLocStart(),
SuppressUserConversions,
/*AllowExplicit=*/false);
+ }
}
// Otherwise, we bind the reference to a temporary created from the
@@ -4626,7 +4618,6 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
Result.Standard.setFromType(ToType);
Result.Standard.setAllToTypes(ToType);
}
- Result.setListInitializationSequence();
return Result;
}
@@ -4662,7 +4653,8 @@ TryCopyInitialization(Sema &S, Expr *From, QualType ToType,
/*AllowExplicit=*/false,
InOverloadResolution,
/*CStyle=*/false,
- AllowObjCWritebackConversion);
+ AllowObjCWritebackConversion,
+ /*AllowObjCConversionOnExplicit=*/false);
}
static bool TryCopyInitialization(const CanQualType FromQTy,
@@ -4857,14 +4849,13 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
/// expression From to bool (C++0x [conv]p3).
static ImplicitConversionSequence
TryContextuallyConvertToBool(Sema &S, Expr *From) {
- // FIXME: This is pretty broken.
return TryImplicitConversion(S, From, S.Context.BoolTy,
- // FIXME: Are these flags correct?
/*SuppressUserConversions=*/false,
/*AllowExplicit=*/true,
/*InOverloadResolution=*/false,
/*CStyle=*/false,
- /*AllowObjCWritebackConversion=*/false);
+ /*AllowObjCWritebackConversion=*/false,
+ /*AllowObjCConversionOnExplicit=*/false);
}
/// PerformContextuallyConvertToBool - Perform a contextual conversion
@@ -5009,17 +5000,13 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
break;
case NK_Constant_Narrowing:
- Diag(From->getLocStart(),
- isSFINAEContext() ? diag::err_cce_narrowing_sfinae :
- diag::err_cce_narrowing)
+ Diag(From->getLocStart(), diag::ext_cce_narrowing)
<< CCE << /*Constant*/1
<< PreNarrowingValue.getAsString(Context, PreNarrowingType) << T;
break;
case NK_Type_Narrowing:
- Diag(From->getLocStart(),
- isSFINAEContext() ? diag::err_cce_narrowing_sfinae :
- diag::err_cce_narrowing)
+ Diag(From->getLocStart(), diag::ext_cce_narrowing)
<< CCE << /*Constant*/0 << From->getType() << T;
break;
}
@@ -5079,7 +5066,8 @@ TryContextuallyConvertToObjCPointer(Sema &S, Expr *From) {
/*AllowExplicit=*/true,
/*InOverloadResolution=*/false,
/*CStyle=*/false,
- /*AllowObjCWritebackConversion=*/false);
+ /*AllowObjCWritebackConversion=*/false,
+ /*AllowObjCConversionOnExplicit=*/true);
// Strip off any final conversions to 'id'.
switch (ICS.getKind()) {
@@ -5116,34 +5104,157 @@ ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) {
/// Determine whether the provided type is an integral type, or an enumeration
/// type of a permitted flavor.
-static bool isIntegralOrEnumerationType(QualType T, bool AllowScopedEnum) {
- return AllowScopedEnum ? T->isIntegralOrEnumerationType()
- : T->isIntegralOrUnscopedEnumerationType();
+bool Sema::ICEConvertDiagnoser::match(QualType T) {
+ return AllowScopedEnumerations ? T->isIntegralOrEnumerationType()
+ : T->isIntegralOrUnscopedEnumerationType();
+}
+
+static ExprResult
+diagnoseAmbiguousConversion(Sema &SemaRef, SourceLocation Loc, Expr *From,
+ Sema::ContextualImplicitConverter &Converter,
+ QualType T, UnresolvedSetImpl &ViableConversions) {
+
+ if (Converter.Suppress)
+ return ExprError();
+
+ Converter.diagnoseAmbiguous(SemaRef, Loc, T) << From->getSourceRange();
+ for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
+ CXXConversionDecl *Conv =
+ cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl());
+ QualType ConvTy = Conv->getConversionType().getNonReferenceType();
+ Converter.noteAmbiguous(SemaRef, Conv, ConvTy);
+ }
+ return SemaRef.Owned(From);
+}
+
+static bool
+diagnoseNoViableConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From,
+ Sema::ContextualImplicitConverter &Converter,
+ QualType T, bool HadMultipleCandidates,
+ UnresolvedSetImpl &ExplicitConversions) {
+ if (ExplicitConversions.size() == 1 && !Converter.Suppress) {
+ DeclAccessPair Found = ExplicitConversions[0];
+ CXXConversionDecl *Conversion =
+ cast<CXXConversionDecl>(Found->getUnderlyingDecl());
+
+ // The user probably meant to invoke the given explicit
+ // conversion; use it.
+ QualType ConvTy = Conversion->getConversionType().getNonReferenceType();
+ std::string TypeStr;
+ ConvTy.getAsStringInternal(TypeStr, SemaRef.getPrintingPolicy());
+
+ Converter.diagnoseExplicitConv(SemaRef, Loc, T, ConvTy)
+ << FixItHint::CreateInsertion(From->getLocStart(),
+ "static_cast<" + TypeStr + ">(")
+ << FixItHint::CreateInsertion(
+ SemaRef.PP.getLocForEndOfToken(From->getLocEnd()), ")");
+ Converter.noteExplicitConv(SemaRef, Conversion, ConvTy);
+
+ // If we aren't in a SFINAE context, build a call to the
+ // explicit conversion function.
+ if (SemaRef.isSFINAEContext())
+ return true;
+
+ SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+ ExprResult Result = SemaRef.BuildCXXMemberCallExpr(From, Found, Conversion,
+ HadMultipleCandidates);
+ if (Result.isInvalid())
+ return true;
+ // Record usage of conversion in an implicit cast.
+ From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(),
+ CK_UserDefinedConversion, Result.get(), 0,
+ Result.get()->getValueKind());
+ }
+ return false;
+}
+
+static bool recordConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From,
+ Sema::ContextualImplicitConverter &Converter,
+ QualType T, bool HadMultipleCandidates,
+ DeclAccessPair &Found) {
+ CXXConversionDecl *Conversion =
+ cast<CXXConversionDecl>(Found->getUnderlyingDecl());
+ SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+
+ QualType ToType = Conversion->getConversionType().getNonReferenceType();
+ if (!Converter.SuppressConversion) {
+ if (SemaRef.isSFINAEContext())
+ return true;
+
+ Converter.diagnoseConversion(SemaRef, Loc, T, ToType)
+ << From->getSourceRange();
+ }
+
+ ExprResult Result = SemaRef.BuildCXXMemberCallExpr(From, Found, Conversion,
+ HadMultipleCandidates);
+ if (Result.isInvalid())
+ return true;
+ // Record usage of conversion in an implicit cast.
+ From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(),
+ CK_UserDefinedConversion, Result.get(), 0,
+ Result.get()->getValueKind());
+ return false;
+}
+
+static ExprResult finishContextualImplicitConversion(
+ Sema &SemaRef, SourceLocation Loc, Expr *From,
+ Sema::ContextualImplicitConverter &Converter) {
+ if (!Converter.match(From->getType()) && !Converter.Suppress)
+ Converter.diagnoseNoMatch(SemaRef, Loc, From->getType())
+ << From->getSourceRange();
+
+ return SemaRef.DefaultLvalueConversion(From);
+}
+
+static void
+collectViableConversionCandidates(Sema &SemaRef, Expr *From, QualType ToType,
+ UnresolvedSetImpl &ViableConversions,
+ OverloadCandidateSet &CandidateSet) {
+ for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
+ DeclAccessPair FoundDecl = ViableConversions[I];
+ NamedDecl *D = FoundDecl.getDecl();
+ CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ CXXConversionDecl *Conv;
+ FunctionTemplateDecl *ConvTemplate;
+ if ((ConvTemplate = dyn_cast<FunctionTemplateDecl>(D)))
+ Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+ else
+ Conv = cast<CXXConversionDecl>(D);
+
+ if (ConvTemplate)
+ SemaRef.AddTemplateConversionCandidate(
+ ConvTemplate, FoundDecl, ActingContext, From, ToType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/false);
+ else
+ SemaRef.AddConversionCandidate(Conv, FoundDecl, ActingContext, From,
+ ToType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/false);
+ }
}
-/// \brief Attempt to convert the given expression to an integral or
-/// enumeration type.
+/// \brief Attempt to convert the given expression to a type which is accepted
+/// by the given converter.
///
-/// This routine will attempt to convert an expression of class type to an
-/// integral or enumeration type, if that class type only has a single
-/// conversion to an integral or enumeration type.
+/// This routine will attempt to convert an expression of class type to a
+/// type accepted by the specified converter. In C++11 and before, the class
+/// must have a single non-explicit conversion function converting to a matching
+/// type. In C++1y, there can be multiple such conversion functions, but only
+/// one target type.
///
/// \param Loc The source location of the construct that requires the
/// conversion.
///
/// \param From The expression we're converting from.
///
-/// \param Diagnoser Used to output any diagnostics.
-///
-/// \param AllowScopedEnumerations Specifies whether conversions to scoped
-/// enumerations should be considered.
+/// \param Converter Used to control and diagnose the conversion process.
///
/// \returns The expression, converted to an integral or enumeration type if
/// successful.
-ExprResult
-Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
- ICEConvertDiagnoser &Diagnoser,
- bool AllowScopedEnumerations) {
+ExprResult Sema::PerformContextualImplicitConversion(
+ SourceLocation Loc, Expr *From, ContextualImplicitConverter &Converter) {
// We can't perform any more checking for type-dependent expressions.
if (From->isTypeDependent())
return Owned(From);
@@ -5151,158 +5262,180 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
// Process placeholders immediately.
if (From->hasPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(From);
- if (result.isInvalid()) return result;
+ if (result.isInvalid())
+ return result;
From = result.take();
}
- // If the expression already has integral or enumeration type, we're golden.
+ // If the expression already has a matching type, we're golden.
QualType T = From->getType();
- if (isIntegralOrEnumerationType(T, AllowScopedEnumerations))
+ if (Converter.match(T))
return DefaultLvalueConversion(From);
// FIXME: Check for missing '()' if T is a function type?
- // If we don't have a class type in C++, there's no way we can get an
- // expression of integral or enumeration type.
+ // We can only perform contextual implicit conversions on objects of class
+ // type.
const RecordType *RecordTy = T->getAs<RecordType>();
if (!RecordTy || !getLangOpts().CPlusPlus) {
- if (!Diagnoser.Suppress)
- Diagnoser.diagnoseNotInt(*this, Loc, T) << From->getSourceRange();
+ if (!Converter.Suppress)
+ Converter.diagnoseNoMatch(*this, Loc, T) << From->getSourceRange();
return Owned(From);
}
// We must have a complete class type.
struct TypeDiagnoserPartialDiag : TypeDiagnoser {
- ICEConvertDiagnoser &Diagnoser;
+ ContextualImplicitConverter &Converter;
Expr *From;
-
- TypeDiagnoserPartialDiag(ICEConvertDiagnoser &Diagnoser, Expr *From)
- : TypeDiagnoser(Diagnoser.Suppress), Diagnoser(Diagnoser), From(From) {}
-
+
+ TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter, Expr *From)
+ : TypeDiagnoser(Converter.Suppress), Converter(Converter), From(From) {}
+
virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
- Diagnoser.diagnoseIncomplete(S, Loc, T) << From->getSourceRange();
+ Converter.diagnoseIncomplete(S, Loc, T) << From->getSourceRange();
}
- } IncompleteDiagnoser(Diagnoser, From);
+ } IncompleteDiagnoser(Converter, From);
if (RequireCompleteType(Loc, T, IncompleteDiagnoser))
return Owned(From);
// Look for a conversion to an integral or enumeration type.
- UnresolvedSet<4> ViableConversions;
+ UnresolvedSet<4>
+ ViableConversions; // These are *potentially* viable in C++1y.
UnresolvedSet<4> ExplicitConversions;
std::pair<CXXRecordDecl::conversion_iterator,
- CXXRecordDecl::conversion_iterator> Conversions
- = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
+ CXXRecordDecl::conversion_iterator> Conversions =
+ cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
+
+ bool HadMultipleCandidates =
+ (std::distance(Conversions.first, Conversions.second) > 1);
+
+ // To check that there is only one target type, in C++1y:
+ QualType ToType;
+ bool HasUniqueTargetType = true;
+
+ // Collect explicit or viable (potentially in C++1y) conversions.
+ for (CXXRecordDecl::conversion_iterator I = Conversions.first,
+ E = Conversions.second;
+ I != E; ++I) {
+ NamedDecl *D = (*I)->getUnderlyingDecl();
+ CXXConversionDecl *Conversion;
+ FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
+ if (ConvTemplate) {
+ if (getLangOpts().CPlusPlus1y)
+ Conversion = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+ else
+ continue; // C++11 does not consider conversion operator templates(?).
+ } else
+ Conversion = cast<CXXConversionDecl>(D);
- bool HadMultipleCandidates
- = (std::distance(Conversions.first, Conversions.second) > 1);
+ assert((!ConvTemplate || getLangOpts().CPlusPlus1y) &&
+ "Conversion operator templates are considered potentially "
+ "viable in C++1y");
- for (CXXRecordDecl::conversion_iterator
- I = Conversions.first, E = Conversions.second; I != E; ++I) {
- if (CXXConversionDecl *Conversion
- = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
- if (isIntegralOrEnumerationType(
- Conversion->getConversionType().getNonReferenceType(),
- AllowScopedEnumerations)) {
- if (Conversion->isExplicit())
+ QualType CurToType = Conversion->getConversionType().getNonReferenceType();
+ if (Converter.match(CurToType) || ConvTemplate) {
+
+ if (Conversion->isExplicit()) {
+ // FIXME: For C++1y, do we need this restriction?
+ // cf. diagnoseNoViableConversion()
+ if (!ConvTemplate)
ExplicitConversions.addDecl(I.getDecl(), I.getAccess());
- else
- ViableConversions.addDecl(I.getDecl(), I.getAccess());
+ } else {
+ if (!ConvTemplate && getLangOpts().CPlusPlus1y) {
+ if (ToType.isNull())
+ ToType = CurToType.getUnqualifiedType();
+ else if (HasUniqueTargetType &&
+ (CurToType.getUnqualifiedType() != ToType))
+ HasUniqueTargetType = false;
+ }
+ ViableConversions.addDecl(I.getDecl(), I.getAccess());
}
}
}
- switch (ViableConversions.size()) {
- case 0:
- if (ExplicitConversions.size() == 1 && !Diagnoser.Suppress) {
- DeclAccessPair Found = ExplicitConversions[0];
- CXXConversionDecl *Conversion
- = cast<CXXConversionDecl>(Found->getUnderlyingDecl());
+ if (getLangOpts().CPlusPlus1y) {
+ // C++1y [conv]p6:
+ // ... An expression e of class type E appearing in such a context
+ // is said to be contextually implicitly converted to a specified
+ // type T and is well-formed if and only if e can be implicitly
+ // converted to a type T that is determined as follows: E is searched
+ // for conversion functions whose return type is cv T or reference to
+ // cv T such that T is allowed by the context. There shall be
+ // exactly one such T.
- // The user probably meant to invoke the given explicit
- // conversion; use it.
- QualType ConvTy
- = Conversion->getConversionType().getNonReferenceType();
- std::string TypeStr;
- ConvTy.getAsStringInternal(TypeStr, getPrintingPolicy());
+ // If no unique T is found:
+ if (ToType.isNull()) {
+ if (diagnoseNoViableConversion(*this, Loc, From, Converter, T,
+ HadMultipleCandidates,
+ ExplicitConversions))
+ return ExprError();
+ return finishContextualImplicitConversion(*this, Loc, From, Converter);
+ }
- Diagnoser.diagnoseExplicitConv(*this, Loc, T, ConvTy)
- << FixItHint::CreateInsertion(From->getLocStart(),
- "static_cast<" + TypeStr + ">(")
- << FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()),
- ")");
- Diagnoser.noteExplicitConv(*this, Conversion, ConvTy);
+ // If more than one unique Ts are found:
+ if (!HasUniqueTargetType)
+ return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T,
+ ViableConversions);
- // If we aren't in a SFINAE context, build a call to the
- // explicit conversion function.
- if (isSFINAEContext())
- return ExprError();
+ // If one unique T is found:
+ // First, build a candidate set from the previously recorded
+ // potentially viable conversions.
+ OverloadCandidateSet CandidateSet(Loc);
+ collectViableConversionCandidates(*this, From, ToType, ViableConversions,
+ CandidateSet);
- CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
- ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion,
- HadMultipleCandidates);
- if (Result.isInvalid())
+ // Then, perform overload resolution over the candidate set.
+ OverloadCandidateSet::iterator Best;
+ switch (CandidateSet.BestViableFunction(*this, Loc, Best)) {
+ case OR_Success: {
+ // Apply this conversion.
+ DeclAccessPair Found =
+ DeclAccessPair::make(Best->Function, Best->FoundDecl.getAccess());
+ if (recordConversion(*this, Loc, From, Converter, T,
+ HadMultipleCandidates, Found))
return ExprError();
- // Record usage of conversion in an implicit cast.
- From = ImplicitCastExpr::Create(Context, Result.get()->getType(),
- CK_UserDefinedConversion,
- Result.get(), 0,
- Result.get()->getValueKind());
+ break;
}
-
- // We'll complain below about a non-integral condition type.
- break;
-
- case 1: {
- // Apply this conversion.
- DeclAccessPair Found = ViableConversions[0];
- CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
-
- CXXConversionDecl *Conversion
- = cast<CXXConversionDecl>(Found->getUnderlyingDecl());
- QualType ConvTy
- = Conversion->getConversionType().getNonReferenceType();
- if (!Diagnoser.SuppressConversion) {
- if (isSFINAEContext())
+ case OR_Ambiguous:
+ return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T,
+ ViableConversions);
+ case OR_No_Viable_Function:
+ if (diagnoseNoViableConversion(*this, Loc, From, Converter, T,
+ HadMultipleCandidates,
+ ExplicitConversions))
return ExprError();
-
- Diagnoser.diagnoseConversion(*this, Loc, T, ConvTy)
- << From->getSourceRange();
+ // fall through 'OR_Deleted' case.
+ case OR_Deleted:
+ // We'll complain below about a non-integral condition type.
+ break;
}
+ } else {
+ switch (ViableConversions.size()) {
+ case 0: {
+ if (diagnoseNoViableConversion(*this, Loc, From, Converter, T,
+ HadMultipleCandidates,
+ ExplicitConversions))
+ return ExprError();
- ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion,
- HadMultipleCandidates);
- if (Result.isInvalid())
- return ExprError();
- // Record usage of conversion in an implicit cast.
- From = ImplicitCastExpr::Create(Context, Result.get()->getType(),
- CK_UserDefinedConversion,
- Result.get(), 0,
- Result.get()->getValueKind());
- break;
- }
-
- default:
- if (Diagnoser.Suppress)
- return ExprError();
-
- Diagnoser.diagnoseAmbiguous(*this, Loc, T) << From->getSourceRange();
- for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
- CXXConversionDecl *Conv
- = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl());
- QualType ConvTy = Conv->getConversionType().getNonReferenceType();
- Diagnoser.noteAmbiguous(*this, Conv, ConvTy);
+ // We'll complain below about a non-integral condition type.
+ break;
+ }
+ case 1: {
+ // Apply this conversion.
+ DeclAccessPair Found = ViableConversions[0];
+ if (recordConversion(*this, Loc, From, Converter, T,
+ HadMultipleCandidates, Found))
+ return ExprError();
+ break;
+ }
+ default:
+ return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T,
+ ViableConversions);
}
- return Owned(From);
- }
-
- if (!isIntegralOrEnumerationType(From->getType(), AllowScopedEnumerations) &&
- !Diagnoser.Suppress) {
- Diagnoser.diagnoseNotInt(*this, Loc, From->getType())
- << From->getSourceRange();
}
- return DefaultLvalueConversion(From);
+ return finishContextualImplicitConversion(*this, Loc, From, Converter);
}
/// AddOverloadCandidate - Adds the given function to the set of
@@ -5348,10 +5481,18 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
if (!CandidateSet.isNewCandidate(Function))
return;
+ // C++11 [class.copy]p11: [DR1402]
+ // A defaulted move constructor that is defined as deleted is ignored by
+ // overload resolution.
+ CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function);
+ if (Constructor && Constructor->isDefaulted() && Constructor->isDeleted() &&
+ Constructor->isMoveConstructor())
+ return;
+
// Overload resolution is always an unevaluated context.
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
- if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function)){
+ if (Constructor) {
// C++ [class.copy]p3:
// A member function template is never instantiated to perform the copy
// of a class object to an object of its class type.
@@ -5437,7 +5578,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
}
/// \brief Add all of the function declarations in the given function set to
-/// the overload canddiate set.
+/// the overload candidate set.
void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
@@ -5526,6 +5667,13 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
if (!CandidateSet.isNewCandidate(Method))
return;
+ // C++11 [class.copy]p23: [DR1402]
+ // A defaulted move assignment operator that is defined as deleted is
+ // ignored by overload resolution.
+ if (Method->isDefaulted() && Method->isDeleted() &&
+ Method->isMoveAssignmentOperator())
+ return;
+
// Overload resolution is always an unevaluated context.
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
@@ -5708,6 +5856,45 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
SuppressUserConversions);
}
+/// Determine whether this is an allowable conversion from the result
+/// of an explicit conversion operator to the expected type, per C++
+/// [over.match.conv]p1 and [over.match.ref]p1.
+///
+/// \param ConvType The return type of the conversion function.
+///
+/// \param ToType The type we are converting to.
+///
+/// \param AllowObjCPointerConversion Allow a conversion from one
+/// Objective-C pointer to another.
+///
+/// \returns true if the conversion is allowable, false otherwise.
+static bool isAllowableExplicitConversion(Sema &S,
+ QualType ConvType, QualType ToType,
+ bool AllowObjCPointerConversion) {
+ QualType ToNonRefType = ToType.getNonReferenceType();
+
+ // Easy case: the types are the same.
+ if (S.Context.hasSameUnqualifiedType(ConvType, ToNonRefType))
+ return true;
+
+ // Allow qualification conversions.
+ bool ObjCLifetimeConversion;
+ if (S.IsQualificationConversion(ConvType, ToNonRefType, /*CStyle*/false,
+ ObjCLifetimeConversion))
+ return true;
+
+ // If we're not allowed to consider Objective-C pointer conversions,
+ // we're done.
+ if (!AllowObjCPointerConversion)
+ return false;
+
+ // Is this an Objective-C pointer conversion?
+ bool IncompatibleObjC = false;
+ QualType ConvertedType;
+ return S.isObjCPointerConversion(ConvType, ToNonRefType, ConvertedType,
+ IncompatibleObjC);
+}
+
/// AddConversionCandidate - Add a C++ conversion function as a
/// candidate in the candidate set (C++ [over.match.conv],
/// C++ [over.match.copy]). From is the expression we're converting from,
@@ -5719,7 +5906,8 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
- OverloadCandidateSet& CandidateSet) {
+ OverloadCandidateSet& CandidateSet,
+ bool AllowObjCConversionOnExplicit) {
assert(!Conversion->getDescribedFunctionTemplate() &&
"Conversion function templates use AddTemplateConversionCandidate");
QualType ConvType = Conversion->getConversionType().getNonReferenceType();
@@ -5734,6 +5922,14 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
ConvType = Conversion->getConversionType().getNonReferenceType();
}
+ // Per C++ [over.match.conv]p1, [over.match.ref]p1, an explicit conversion
+ // operator is only a candidate if its return type is the target type or
+ // can be converted to the target type with a qualification conversion.
+ if (Conversion->isExplicit() &&
+ !isAllowableExplicitConversion(*this, ConvType, ToType,
+ AllowObjCConversionOnExplicit))
+ return;
+
// Overload resolution is always an unevaluated context.
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
@@ -5868,7 +6064,8 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingDC,
Expr *From, QualType ToType,
- OverloadCandidateSet &CandidateSet) {
+ OverloadCandidateSet &CandidateSet,
+ bool AllowObjCConversionOnExplicit) {
assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) &&
"Only conversion function templates permitted here");
@@ -5897,7 +6094,7 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
// template argument deduction as a candidate.
assert(Specialization && "Missing function template specialization?");
AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType,
- CandidateSet);
+ CandidateSet, AllowObjCConversionOnExplicit);
}
/// AddSurrogateCandidate - Adds a "surrogate" candidate function that
@@ -6119,6 +6316,8 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
}
}
+namespace {
+
/// BuiltinCandidateTypeSet - A set of types that will be used for the
/// candidate operator functions for built-in operators (C++
/// [over.built]). The types are separated into pointer types and
@@ -6208,6 +6407,8 @@ public:
bool hasNullPtrType() const { return HasNullPtrType; }
};
+} // end anonymous namespace
+
/// AddPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty to
/// the set of pointer types along with any more-qualified variants of
/// that type. For example, if @p Ty is "int const *", this routine
@@ -7560,11 +7761,10 @@ public:
/// on the operator @p Op and the arguments given. For example, if the
/// operator is a binary '+', this routine might add "int
/// operator+(int, int)" to cover integer addition.
-void
-Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
- SourceLocation OpLoc,
- llvm::ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet) {
+void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc,
+ ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet) {
// Find all of the types that the arguments can convert to, but only
// if the operator we're looking at has built-in operator candidates
// that make use of these types. Also record whether we encounter non-record
@@ -7869,7 +8069,8 @@ isBetterOverloadCandidate(Sema &S,
Loc,
isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion
: TPOC_Call,
- Cand1.ExplicitCallArguments))
+ Cand1.ExplicitCallArguments,
+ Cand2.ExplicitCallArguments))
return BetterTemplate == Cand1.Function->getPrimaryTemplate();
}
@@ -8024,7 +8225,7 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
return isTemplate ? oc_function_template : oc_function;
}
-void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) {
+void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) {
const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn);
if (!Ctor) return;
@@ -8047,7 +8248,7 @@ void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType) {
MaybeEmitInheritedConstructorNote(*this, Fn);
}
-//Notes the location of all overload candidates designated through
+// Notes the location of all overload candidates designated through
// OverloadedExpr
void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) {
assert(OverloadedExpr->getType() == Context.OverloadTy);
@@ -8310,30 +8511,52 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
MaybeEmitInheritedConstructorNote(S, Fn);
}
-void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
- unsigned NumFormalArgs) {
- // TODO: treat calls to a missing default constructor as a special case
-
+/// Additional arity mismatch diagnosis specific to a function overload
+/// candidates. This is not covered by the more general DiagnoseArityMismatch()
+/// over a candidate in any candidate set.
+bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand,
+ unsigned NumArgs) {
FunctionDecl *Fn = Cand->Function;
- const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
-
unsigned MinParams = Fn->getMinRequiredArguments();
// With invalid overloaded operators, it's possible that we think we
- // have an arity mismatch when it fact it looks like we have the
+ // have an arity mismatch when in fact it looks like we have the
// right number of arguments, because only overloaded operators have
// the weird behavior of overloading member and non-member functions.
// Just don't report anything.
if (Fn->isInvalidDecl() &&
Fn->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
- return;
+ return true;
- // at least / at most / exactly
- unsigned mode, modeCount;
- if (NumFormalArgs < MinParams) {
+ if (NumArgs < MinParams) {
assert((Cand->FailureKind == ovl_fail_too_few_arguments) ||
(Cand->FailureKind == ovl_fail_bad_deduction &&
Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments));
+ } else {
+ assert((Cand->FailureKind == ovl_fail_too_many_arguments) ||
+ (Cand->FailureKind == ovl_fail_bad_deduction &&
+ Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments));
+ }
+
+ return false;
+}
+
+/// General arity mismatch diagnosis over a candidate in a candidate set.
+void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
+ assert(isa<FunctionDecl>(D) &&
+ "The templated declaration should at least be a function"
+ " when diagnosing bad template argument deduction due to too many"
+ " or too few arguments");
+
+ FunctionDecl *Fn = cast<FunctionDecl>(D);
+
+ // TODO: treat calls to a missing default constructor as a special case
+ const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
+ unsigned MinParams = Fn->getMinRequiredArguments();
+
+ // at least / at most / exactly
+ unsigned mode, modeCount;
+ if (NumFormalArgs < MinParams) {
if (MinParams != FnTy->getNumArgs() ||
FnTy->isVariadic() || FnTy->isTemplateVariadic())
mode = 0; // "at least"
@@ -8341,9 +8564,6 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
mode = 2; // "exactly"
modeCount = MinParams;
} else {
- assert((Cand->FailureKind == ovl_fail_too_many_arguments) ||
- (Cand->FailureKind == ovl_fail_bad_deduction &&
- Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments));
if (MinParams != FnTy->getNumArgs())
mode = 1; // "at most"
else
@@ -8365,25 +8585,42 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
MaybeEmitInheritedConstructorNote(S, Fn);
}
+/// Arity mismatch diagnosis specific to a function overload candidate.
+void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
+ unsigned NumFormalArgs) {
+ if (!CheckArityMismatch(S, Cand, NumFormalArgs))
+ DiagnoseArityMismatch(S, Cand->Function, NumFormalArgs);
+}
+
+TemplateDecl *getDescribedTemplate(Decl *Templated) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Templated))
+ return FD->getDescribedFunctionTemplate();
+ else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Templated))
+ return RD->getDescribedClassTemplate();
+
+ llvm_unreachable("Unsupported: Getting the described template declaration"
+ " for bad deduction diagnosis");
+}
+
/// Diagnose a failed template-argument deduction.
-void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
+void DiagnoseBadDeduction(Sema &S, Decl *Templated,
+ DeductionFailureInfo &DeductionFailure,
unsigned NumArgs) {
- FunctionDecl *Fn = Cand->Function; // pattern
-
- TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter();
+ TemplateParameter Param = DeductionFailure.getTemplateParameter();
NamedDecl *ParamD;
(ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
(ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
(ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
- switch (Cand->DeductionFailure.Result) {
+ switch (DeductionFailure.Result) {
case Sema::TDK_Success:
llvm_unreachable("TDK_success while diagnosing bad deduction");
case Sema::TDK_Incomplete: {
assert(ParamD && "no parameter found for incomplete deduction result");
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction)
- << ParamD->getDeclName();
- MaybeEmitInheritedConstructorNote(S, Fn);
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_incomplete_deduction)
+ << ParamD->getDeclName();
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
}
@@ -8391,7 +8628,7 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
assert(ParamD && "no parameter found for bad qualifiers deduction result");
TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD);
- QualType Param = Cand->DeductionFailure.getFirstArg()->getAsType();
+ QualType Param = DeductionFailure.getFirstArg()->getAsType();
// Param will have been canonicalized, but it should just be a
// qualified version of ParamD, so move the qualifiers to that.
@@ -8404,11 +8641,11 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
// about that. It also doesn't matter as much, because it won't
// have any template parameters in it (because deduction isn't
// done on dependent types).
- QualType Arg = Cand->DeductionFailure.getSecondArg()->getAsType();
+ QualType Arg = DeductionFailure.getSecondArg()->getAsType();
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified)
- << ParamD->getDeclName() << Arg << NonCanonParam;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ S.Diag(Templated->getLocation(), diag::note_ovl_candidate_underqualified)
+ << ParamD->getDeclName() << Arg << NonCanonParam;
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
}
@@ -8423,20 +8660,20 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
which = 2;
}
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction)
- << which << ParamD->getDeclName()
- << *Cand->DeductionFailure.getFirstArg()
- << *Cand->DeductionFailure.getSecondArg();
- MaybeEmitInheritedConstructorNote(S, Fn);
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_inconsistent_deduction)
+ << which << ParamD->getDeclName() << *DeductionFailure.getFirstArg()
+ << *DeductionFailure.getSecondArg();
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
}
case Sema::TDK_InvalidExplicitArguments:
assert(ParamD && "no parameter found for invalid explicit arguments");
if (ParamD->getDeclName())
- S.Diag(Fn->getLocation(),
+ S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch_named)
- << ParamD->getDeclName();
+ << ParamD->getDeclName();
else {
int index = 0;
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
@@ -8446,35 +8683,36 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
index = NTTP->getIndex();
else
index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex();
- S.Diag(Fn->getLocation(),
+ S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
- << (index + 1);
+ << (index + 1);
}
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
- DiagnoseArityMismatch(S, Cand, NumArgs);
+ DiagnoseArityMismatch(S, Templated, NumArgs);
return;
case Sema::TDK_InstantiationDepth:
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth);
- MaybeEmitInheritedConstructorNote(S, Fn);
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_instantiation_depth);
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
case Sema::TDK_SubstitutionFailure: {
// Format the template argument list into the argument string.
SmallString<128> TemplateArgString;
if (TemplateArgumentList *Args =
- Cand->DeductionFailure.getTemplateArgumentList()) {
+ DeductionFailure.getTemplateArgumentList()) {
TemplateArgString = " ";
TemplateArgString += S.getTemplateArgumentBindingsText(
- Fn->getDescribedFunctionTemplate()->getTemplateParameters(), *Args);
+ getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
}
// If this candidate was disabled by enable_if, say so.
- PartialDiagnosticAt *PDiag = Cand->DeductionFailure.getSFINAEDiagnostic();
+ PartialDiagnosticAt *PDiag = DeductionFailure.getSFINAEDiagnostic();
if (PDiag && PDiag->second.getDiagID() ==
diag::err_typename_nested_not_found_enable_if) {
// FIXME: Use the source range of the condition, and the fully-qualified
@@ -8495,25 +8733,25 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
PDiag->second.EmitToString(S.getDiagnostics(), SFINAEArgString);
}
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure)
- << TemplateArgString << SFINAEArgString << R;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_substitution_failure)
+ << TemplateArgString << SFINAEArgString << R;
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
}
case Sema::TDK_FailedOverloadResolution: {
- OverloadExpr::FindResult R =
- OverloadExpr::find(Cand->DeductionFailure.getExpr());
- S.Diag(Fn->getLocation(),
+ OverloadExpr::FindResult R = OverloadExpr::find(DeductionFailure.getExpr());
+ S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_failed_overload_resolution)
- << R.Expression->getName();
+ << R.Expression->getName();
return;
}
case Sema::TDK_NonDeducedMismatch: {
// FIXME: Provide a source location to indicate what we couldn't match.
- TemplateArgument FirstTA = *Cand->DeductionFailure.getFirstArg();
- TemplateArgument SecondTA = *Cand->DeductionFailure.getSecondArg();
+ TemplateArgument FirstTA = *DeductionFailure.getFirstArg();
+ TemplateArgument SecondTA = *DeductionFailure.getSecondArg();
if (FirstTA.getKind() == TemplateArgument::Template &&
SecondTA.getKind() == TemplateArgument::Template) {
TemplateName FirstTN = FirstTA.getAsTemplate();
@@ -8528,26 +8766,42 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
// 2) The diagnostic printer only attempts to find a better
// name for types, not decls.
// Ideally, this should folded into the diagnostic printer.
- S.Diag(Fn->getLocation(),
+ S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_non_deduced_mismatch_qualified)
<< FirstTN.getAsTemplateDecl() << SecondTN.getAsTemplateDecl();
return;
}
}
}
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch)
- << FirstTA << SecondTA;
+ // FIXME: For generic lambda parameters, check if the function is a lambda
+ // call operator, and if so, emit a prettier and more informative
+ // diagnostic that mentions 'auto' and lambda in addition to
+ // (or instead of?) the canonical template type parameters.
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_non_deduced_mismatch)
+ << FirstTA << SecondTA;
return;
}
// TODO: diagnose these individually, then kill off
// note_ovl_candidate_bad_deduction, which is uselessly vague.
case Sema::TDK_MiscellaneousDeductionFailure:
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
- MaybeEmitInheritedConstructorNote(S, Fn);
+ S.Diag(Templated->getLocation(), diag::note_ovl_candidate_bad_deduction);
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
}
}
+/// Diagnose a failed template-argument deduction, for function calls.
+void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, unsigned NumArgs) {
+ unsigned TDK = Cand->DeductionFailure.Result;
+ if (TDK == Sema::TDK_TooFewArguments || TDK == Sema::TDK_TooManyArguments) {
+ if (CheckArityMismatch(S, Cand, NumArgs))
+ return;
+ }
+ DiagnoseBadDeduction(S, Cand->Function, // pattern
+ Cand->DeductionFailure, NumArgs);
+}
+
/// CUDA: diagnose an invalid call across targets.
void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
FunctionDecl *Caller = cast<FunctionDecl>(S.CurContext);
@@ -8695,7 +8949,7 @@ void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
}
}
-SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
+static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
if (Cand->Function)
return Cand->Function->getLocation();
if (Cand->IsSurrogate)
@@ -8703,8 +8957,7 @@ SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
return SourceLocation();
}
-static unsigned
-RankDeductionFailure(const OverloadCandidate::DeductionFailureInfo &DFI) {
+static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
switch ((Sema::TemplateDeductionResult)DFI.Result) {
case Sema::TDK_Success:
llvm_unreachable("TDK_success while diagnosing bad deduction");
@@ -8997,6 +9250,108 @@ void OverloadCandidateSet::NoteCandidates(Sema &S,
S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I);
}
+static SourceLocation
+GetLocationForCandidate(const TemplateSpecCandidate *Cand) {
+ return Cand->Specialization ? Cand->Specialization->getLocation()
+ : SourceLocation();
+}
+
+struct CompareTemplateSpecCandidatesForDisplay {
+ Sema &S;
+ CompareTemplateSpecCandidatesForDisplay(Sema &S) : S(S) {}
+
+ bool operator()(const TemplateSpecCandidate *L,
+ const TemplateSpecCandidate *R) {
+ // Fast-path this check.
+ if (L == R)
+ return false;
+
+ // Assuming that both candidates are not matches...
+
+ // Sort by the ranking of deduction failures.
+ if (L->DeductionFailure.Result != R->DeductionFailure.Result)
+ return RankDeductionFailure(L->DeductionFailure) <
+ RankDeductionFailure(R->DeductionFailure);
+
+ // Sort everything else by location.
+ SourceLocation LLoc = GetLocationForCandidate(L);
+ SourceLocation RLoc = GetLocationForCandidate(R);
+
+ // Put candidates without locations (e.g. builtins) at the end.
+ if (LLoc.isInvalid())
+ return false;
+ if (RLoc.isInvalid())
+ return true;
+
+ return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc);
+ }
+};
+
+/// Diagnose a template argument deduction failure.
+/// We are treating these failures as overload failures due to bad
+/// deductions.
+void TemplateSpecCandidate::NoteDeductionFailure(Sema &S) {
+ DiagnoseBadDeduction(S, Specialization, // pattern
+ DeductionFailure, /*NumArgs=*/0);
+}
+
+void TemplateSpecCandidateSet::destroyCandidates() {
+ for (iterator i = begin(), e = end(); i != e; ++i) {
+ i->DeductionFailure.Destroy();
+ }
+}
+
+void TemplateSpecCandidateSet::clear() {
+ destroyCandidates();
+ Candidates.clear();
+}
+
+/// NoteCandidates - When no template specialization match is found, prints
+/// diagnostic messages containing the non-matching specializations that form
+/// the candidate set.
+/// This is analoguous to OverloadCandidateSet::NoteCandidates() with
+/// OCD == OCD_AllCandidates and Cand->Viable == false.
+void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) {
+ // Sort the candidates by position (assuming no candidate is a match).
+ // Sorting directly would be prohibitive, so we make a set of pointers
+ // and sort those.
+ SmallVector<TemplateSpecCandidate *, 32> Cands;
+ Cands.reserve(size());
+ for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
+ if (Cand->Specialization)
+ Cands.push_back(Cand);
+ // Otherwise, this is a non matching builtin candidate. We do not,
+ // in general, want to list every possible builtin candidate.
+ }
+
+ std::sort(Cands.begin(), Cands.end(),
+ CompareTemplateSpecCandidatesForDisplay(S));
+
+ // FIXME: Perhaps rename OverloadsShown and getShowOverloads()
+ // for generalization purposes (?).
+ const OverloadsShown ShowOverloads = S.Diags.getShowOverloads();
+
+ SmallVectorImpl<TemplateSpecCandidate *>::iterator I, E;
+ unsigned CandsShown = 0;
+ for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
+ TemplateSpecCandidate *Cand = *I;
+
+ // Set an arbitrary limit on the number of candidates we'll spam
+ // the user with. FIXME: This limit should depend on details of the
+ // candidate list.
+ if (CandsShown >= 4 && ShowOverloads == Ovl_Best)
+ break;
+ ++CandsShown;
+
+ assert(Cand->Specialization &&
+ "Non-matching built-in candidates are not added to Cands.");
+ Cand->NoteDeductionFailure(S);
+ }
+
+ if (I != E)
+ S.Diag(Loc, diag::note_ovl_too_many_candidates) << int(E - I);
+}
+
// [PossiblyAFunctionType] --> [Return]
// NonFunctionType --> NonFunctionType
// R (A) --> R(A)
@@ -9034,47 +9389,51 @@ class AddressOfFunctionResolver
bool TargetTypeIsNonStaticMemberFunction;
bool FoundNonTemplateFunction;
+ bool StaticMemberFunctionFromBoundPointer;
OverloadExpr::FindResult OvlExprInfo;
OverloadExpr *OvlExpr;
TemplateArgumentListInfo OvlExplicitTemplateArgs;
SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
+ TemplateSpecCandidateSet FailedCandidates;
public:
- AddressOfFunctionResolver(Sema &S, Expr* SourceExpr,
- const QualType& TargetType, bool Complain)
- : S(S), SourceExpr(SourceExpr), TargetType(TargetType),
- Complain(Complain), Context(S.getASTContext()),
- TargetTypeIsNonStaticMemberFunction(
- !!TargetType->getAs<MemberPointerType>()),
- FoundNonTemplateFunction(false),
- OvlExprInfo(OverloadExpr::find(SourceExpr)),
- OvlExpr(OvlExprInfo.Expression)
- {
+ AddressOfFunctionResolver(Sema &S, Expr *SourceExpr,
+ const QualType &TargetType, bool Complain)
+ : S(S), SourceExpr(SourceExpr), TargetType(TargetType),
+ Complain(Complain), Context(S.getASTContext()),
+ TargetTypeIsNonStaticMemberFunction(
+ !!TargetType->getAs<MemberPointerType>()),
+ FoundNonTemplateFunction(false),
+ StaticMemberFunctionFromBoundPointer(false),
+ OvlExprInfo(OverloadExpr::find(SourceExpr)),
+ OvlExpr(OvlExprInfo.Expression),
+ FailedCandidates(OvlExpr->getNameLoc()) {
ExtractUnqualifiedFunctionTypeFromTargetType();
-
- if (!TargetFunctionType->isFunctionType()) {
- if (OvlExpr->hasExplicitTemplateArgs()) {
- DeclAccessPair dap;
- 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;
- }
+
+ if (TargetFunctionType->isFunctionType()) {
+ if (UnresolvedMemberExpr *UME = dyn_cast<UnresolvedMemberExpr>(OvlExpr))
+ if (!UME->isImplicitAccess() &&
+ !S.ResolveSingleFunctionTemplateSpecialization(UME))
+ StaticMemberFunctionFromBoundPointer = true;
+ } else if (OvlExpr->hasExplicitTemplateArgs()) {
+ DeclAccessPair dap;
+ 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));
- }
+ Matches.push_back(std::make_pair(dap, Fn));
}
return;
}
@@ -9128,14 +9487,16 @@ private:
// function template specialization, which is added to the set of
// overloaded functions considered.
FunctionDecl *Specialization = 0;
- TemplateDeductionInfo Info(OvlExpr->getNameLoc());
+ TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (Sema::TemplateDeductionResult Result
= S.DeduceTemplateArguments(FunctionTemplate,
&OvlExplicitTemplateArgs,
TargetFunctionType, Specialization,
Info, /*InOverloadResolution=*/true)) {
- // FIXME: make a note of the failed deduction for diagnostics.
- (void)Result;
+ // Make a note of the failed deduction for diagnostics.
+ FailedCandidates.addCandidate()
+ .set(FunctionTemplate->getTemplatedDecl(),
+ MakeDeductionFailureInfo(Context, Result, Info));
return false;
}
@@ -9239,15 +9600,15 @@ private:
for (unsigned I = 0, E = Matches.size(); I != E; ++I)
MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess());
- UnresolvedSetIterator Result =
- S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(),
- TPOC_Other, 0, SourceExpr->getLocStart(),
- S.PDiag(),
- S.PDiag(diag::err_addr_ovl_ambiguous)
- << Matches[0].second->getDeclName(),
- S.PDiag(diag::note_ovl_candidate)
- << (unsigned) oc_function_template,
- Complain, TargetFunctionType);
+ // TODO: It looks like FailedCandidates does not serve much purpose
+ // here, since the no_viable diagnostic has index 0.
+ UnresolvedSetIterator Result = S.getMostSpecialized(
+ MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates,
+ SourceExpr->getLocStart(), S.PDiag(),
+ S.PDiag(diag::err_addr_ovl_ambiguous) << Matches[0]
+ .second->getDeclName(),
+ S.PDiag(diag::note_ovl_candidate) << (unsigned)oc_function_template,
+ Complain, TargetFunctionType);
if (Result != MatchesCopy.end()) {
// Make it the first and only element
@@ -9276,14 +9637,27 @@ public:
S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable)
<< OvlExpr->getName() << TargetFunctionType
<< OvlExpr->getSourceRange();
- S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType);
- }
-
+ if (FailedCandidates.empty())
+ S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType);
+ else {
+ // We have some deduction failure messages. Use them to diagnose
+ // the function templates, and diagnose the non-template candidates
+ // normally.
+ for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
+ IEnd = OvlExpr->decls_end();
+ I != IEnd; ++I)
+ if (FunctionDecl *Fun =
+ dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()))
+ S.NoteOverloadCandidate(Fun, TargetFunctionType);
+ FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart());
+ }
+ }
+
bool IsInvalidFormOfPointerToMemberFunction() const {
return TargetTypeIsNonStaticMemberFunction &&
!OvlExprInfo.HasFormOfMemberPointer;
}
-
+
void ComplainIsInvalidFormOfPointerToMemberFunction() const {
// TODO: Should we condition this on whether any functions might
// have matched, or is it more appropriate to do that in callers?
@@ -9291,7 +9665,17 @@ public:
S.Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier)
<< TargetType << OvlExpr->getSourceRange();
}
-
+
+ bool IsStaticMemberFunctionFromBoundPointer() const {
+ return StaticMemberFunctionFromBoundPointer;
+ }
+
+ void ComplainIsStaticMemberFunctionFromBoundPointer() const {
+ S.Diag(OvlExpr->getLocStart(),
+ diag::err_invalid_form_pointer_member_function)
+ << OvlExpr->getSourceRange();
+ }
+
void ComplainOfInvalidConversion() const {
S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_not_func_ptrref)
<< OvlExpr->getName() << TargetType;
@@ -9359,8 +9743,12 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
Fn = Resolver.getMatchingFunctionDecl();
assert(Fn);
FoundResult = *Resolver.getMatchingFunctionAccessPair();
- if (Complain)
- CheckAddressOfMemberAccess(AddressOfExpr, FoundResult);
+ if (Complain) {
+ if (Resolver.IsStaticMemberFunctionFromBoundPointer())
+ Resolver.ComplainIsStaticMemberFunctionFromBoundPointer();
+ else
+ CheckAddressOfMemberAccess(AddressOfExpr, FoundResult);
+ }
}
if (pHadMultipleCandidates)
@@ -9375,6 +9763,9 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
/// 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.
+///
+/// If no template-ids are found, no diagnostics are emitted and NULL is
+/// returned.
FunctionDecl *
Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
bool Complain,
@@ -9392,6 +9783,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
TemplateArgumentListInfo ExplicitTemplateArgs;
ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+ TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc());
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
@@ -9414,13 +9806,16 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
// function template specialization, which is added to the set of
// overloaded functions considered.
FunctionDecl *Specialization = 0;
- TemplateDeductionInfo Info(ovl->getNameLoc());
+ TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
Specialization, Info,
/*InOverloadResolution=*/true)) {
- // FIXME: make a note of the failed deduction for diagnostics.
- (void)Result;
+ // Make a note of the failed deduction for diagnostics.
+ // TODO: Actually use the failed-deduction info?
+ FailedCandidates.addCandidate()
+ .set(FunctionTemplate->getTemplatedDecl(),
+ MakeDeductionFailureInfo(Context, Result, Info));
continue;
}
@@ -9623,6 +10018,19 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
CandidateSet, PartialOverloading);
}
+/// Determine whether a declaration with the specified name could be moved into
+/// a different namespace.
+static bool canBeDeclaredInNamespace(const DeclarationName &Name) {
+ switch (Name.getCXXOverloadedOperator()) {
+ case OO_New: case OO_Array_New:
+ case OO_Delete: case OO_Array_Delete:
+ return false;
+
+ default:
+ return true;
+ }
+}
+
/// Attempt to recover from an ill-formed use of a non-dependent name in a
/// template, where the non-dependent name was declared after the template
/// was defined. This is common in code written for a compilers which do not
@@ -9675,22 +10083,24 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc,
AssociatedNamespaces,
AssociatedClasses);
Sema::AssociatedNamespaceSet SuggestedNamespaces;
- DeclContext *Std = SemaRef.getStdNamespace();
- for (Sema::AssociatedNamespaceSet::iterator
- it = AssociatedNamespaces.begin(),
- end = AssociatedNamespaces.end(); it != end; ++it) {
- // Never suggest declaring a function within namespace 'std'.
- if (Std && Std->Encloses(*it))
- continue;
-
- // Never suggest declaring a function within a namespace with a reserved
- // name, like __gnu_cxx.
- NamespaceDecl *NS = dyn_cast<NamespaceDecl>(*it);
- if (NS &&
- NS->getQualifiedNameAsString().find("__") != std::string::npos)
- continue;
+ if (canBeDeclaredInNamespace(R.getLookupName())) {
+ DeclContext *Std = SemaRef.getStdNamespace();
+ for (Sema::AssociatedNamespaceSet::iterator
+ it = AssociatedNamespaces.begin(),
+ end = AssociatedNamespaces.end(); it != end; ++it) {
+ // Never suggest declaring a function within namespace 'std'.
+ if (Std && Std->Encloses(*it))
+ continue;
- SuggestedNamespaces.insert(*it);
+ // Never suggest declaring a function within a namespace with a
+ // reserved name, like __gnu_cxx.
+ NamespaceDecl *NS = dyn_cast<NamespaceDecl>(*it);
+ if (NS &&
+ NS->getQualifiedNameAsString().find("__") != std::string::npos)
+ continue;
+
+ SuggestedNamespaces.insert(*it);
+ }
}
SemaRef.Diag(R.getNameLoc(), diag::err_not_found_by_two_phase_lookup)
@@ -9739,67 +10149,6 @@ DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op,
}
namespace {
-// Callback to limit the allowed keywords and to only accept typo corrections
-// that are keywords or whose decls refer to functions (or template functions)
-// that accept the given number of arguments.
-class RecoveryCallCCC : public CorrectionCandidateCallback {
- public:
- RecoveryCallCCC(Sema &SemaRef, unsigned NumArgs, bool HasExplicitTemplateArgs)
- : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs) {
- WantTypeSpecifiers = SemaRef.getLangOpts().CPlusPlus;
- WantRemainingKeywords = false;
- }
-
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
- if (!candidate.getCorrectionDecl())
- return candidate.isKeyword();
-
- for (TypoCorrection::const_decl_iterator DI = candidate.begin(),
- DIEnd = candidate.end(); DI != DIEnd; ++DI) {
- FunctionDecl *FD = 0;
- NamedDecl *ND = (*DI)->getUnderlyingDecl();
- if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
- FD = FTD->getTemplatedDecl();
- if (!HasExplicitTemplateArgs && !FD) {
- if (!(FD = dyn_cast<FunctionDecl>(ND)) && isa<ValueDecl>(ND)) {
- // If the Decl is neither a function nor a template function,
- // determine if it is a pointer or reference to a function. If so,
- // check against the number of arguments expected for the pointee.
- QualType ValType = cast<ValueDecl>(ND)->getType();
- if (ValType->isAnyPointerType() || ValType->isReferenceType())
- ValType = ValType->getPointeeType();
- if (const FunctionProtoType *FPT = ValType->getAs<FunctionProtoType>())
- if (FPT->getNumArgs() == NumArgs)
- return true;
- }
- }
- if (FD && FD->getNumParams() >= NumArgs &&
- FD->getMinRequiredArguments() <= NumArgs)
- return true;
- }
- return false;
- }
-
- private:
- unsigned NumArgs;
- bool HasExplicitTemplateArgs;
-};
-
-// Callback that effectively disabled typo correction
-class NoTypoCorrectionCCC : public CorrectionCandidateCallback {
- public:
- NoTypoCorrectionCCC() {
- WantTypeSpecifiers = false;
- WantExpressionKeywords = false;
- WantCXXNamedCasts = false;
- WantRemainingKeywords = false;
- }
-
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
- return false;
- }
-};
-
class BuildRecoveryCallExprRAII {
Sema &SemaRef;
public:
@@ -9848,7 +10197,8 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
Sema::LookupOrdinaryName);
- RecoveryCallCCC Validator(SemaRef, Args.size(), ExplicitTemplateArgs != 0);
+ FunctionCallFilterCCC Validator(SemaRef, Args.size(),
+ ExplicitTemplateArgs != 0);
NoTypoCorrectionCCC RejectAll;
CorrectionCandidateCallback *CCC = AllowTypoCorrection ?
(CorrectionCandidateCallback*)&Validator :
@@ -9890,7 +10240,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
/// \returns true when an the ExprResult output parameter has been set.
bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
UnresolvedLookupExpr *ULE,
- Expr **Args, unsigned NumArgs,
+ MultiExprArg Args,
SourceLocation RParenLoc,
OverloadCandidateSet *CandidateSet,
ExprResult *Result) {
@@ -9913,15 +10263,14 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
#endif
UnbridgedCastsSet UnbridgedCasts;
- if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts)) {
+ if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts)) {
*Result = ExprError();
return true;
}
// Add the functions denoted by the callee to the set of candidate
// functions, including those from argument-dependent lookup.
- AddOverloadedCallCandidates(ULE, llvm::makeArrayRef(Args, NumArgs),
- *CandidateSet);
+ AddOverloadedCallCandidates(ULE, Args, *CandidateSet);
// If we found nothing, try to recover.
// BuildRecoveryCallExpr diagnoses the error itself, so we just bail
@@ -9933,8 +10282,7 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
// classes.
if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() &&
(isa<FunctionDecl>(CurContext) || isa<CXXRecordDecl>(CurContext))) {
- CallExpr *CE = new (Context) CallExpr(Context, Fn,
- llvm::makeArrayRef(Args, NumArgs),
+ CallExpr *CE = new (Context) CallExpr(Context, Fn, Args,
Context.DependentTy, VK_RValue,
RParenLoc);
CE->setTypeDependent(true);
@@ -9954,7 +10302,7 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
+ MultiExprArg Args,
SourceLocation RParenLoc,
Expr *ExecConfig,
OverloadCandidateSet *CandidateSet,
@@ -9962,8 +10310,7 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
OverloadingResult OverloadResult,
bool AllowTypoCorrection) {
if (CandidateSet->empty())
- return BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc,
- llvm::MutableArrayRef<Expr *>(Args, NumArgs),
+ return BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc, Args,
RParenLoc, /*EmptyLookup=*/true,
AllowTypoCorrection);
@@ -9974,16 +10321,15 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
if (SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc()))
return ExprError();
Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
- return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs,
- RParenLoc, ExecConfig);
+ return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc,
+ ExecConfig);
}
case OR_No_Viable_Function: {
// Try to recover by looking for viable functions which the user might
// have meant to call.
ExprResult Recovery = BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc,
- llvm::MutableArrayRef<Expr *>(Args, NumArgs),
- RParenLoc,
+ Args, RParenLoc,
/*EmptyLookup=*/false,
AllowTypoCorrection);
if (!Recovery.isInvalid())
@@ -9992,16 +10338,14 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
SemaRef.Diag(Fn->getLocStart(),
diag::err_ovl_no_viable_function_in_call)
<< ULE->getName() << Fn->getSourceRange();
- CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates,
- llvm::makeArrayRef(Args, NumArgs));
+ CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args);
break;
}
case OR_Ambiguous:
SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_ambiguous_call)
<< ULE->getName() << Fn->getSourceRange();
- CandidateSet->NoteCandidates(SemaRef, OCD_ViableCandidates,
- llvm::makeArrayRef(Args, NumArgs));
+ CandidateSet->NoteCandidates(SemaRef, OCD_ViableCandidates, Args);
break;
case OR_Deleted: {
@@ -10010,15 +10354,14 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
<< ULE->getName()
<< SemaRef.getDeletedOrUnavailableSuffix((*Best)->Function)
<< Fn->getSourceRange();
- CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates,
- llvm::makeArrayRef(Args, NumArgs));
+ CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args);
// We emitted an error for the unvailable/deleted function call but keep
// the call in the AST.
FunctionDecl *FDecl = (*Best)->Function;
Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
- return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs,
- RParenLoc, ExecConfig);
+ return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc,
+ ExecConfig);
}
}
@@ -10035,22 +10378,22 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn,
UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
+ MultiExprArg Args,
SourceLocation RParenLoc,
Expr *ExecConfig,
bool AllowTypoCorrection) {
OverloadCandidateSet CandidateSet(Fn->getExprLoc());
ExprResult result;
- if (buildOverloadedCallSet(S, Fn, ULE, Args, NumArgs, LParenLoc,
- &CandidateSet, &result))
+ if (buildOverloadedCallSet(S, Fn, ULE, Args, LParenLoc, &CandidateSet,
+ &result))
return result;
OverloadCandidateSet::iterator Best;
OverloadingResult OverloadResult =
CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best);
- return FinishOverloadedCallExpr(*this, S, Fn, ULE, LParenLoc, Args, NumArgs,
+ return FinishOverloadedCallExpr(*this, S, Fn, ULE, LParenLoc, Args,
RParenLoc, ExecConfig, &CandidateSet,
&Best, OverloadResult,
AllowTypoCorrection);
@@ -10180,17 +10523,17 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
Input = InputInit.take();
}
- // Determine the result type.
- QualType ResultTy = FnDecl->getResultType();
- ExprValueKind VK = Expr::getValueKindForType(ResultTy);
- ResultTy = ResultTy.getNonLValueExprType(Context);
-
// Build the actual expression node.
ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, Best->FoundDecl,
HadMultipleCandidates, OpLoc);
if (FnExpr.isInvalid())
return ExprError();
+ // Determine the result type.
+ QualType ResultTy = FnDecl->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
+
Args[0] = Input;
CallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), ArgsArray,
@@ -10414,11 +10757,6 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Args[1] = RHS = Arg1.takeAs<Expr>();
}
- // Determine the result type.
- QualType ResultTy = FnDecl->getResultType();
- ExprValueKind VK = Expr::getValueKindForType(ResultTy);
- ResultTy = ResultTy.getNonLValueExprType(Context);
-
// Build the actual expression node.
ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl,
Best->FoundDecl,
@@ -10426,6 +10764,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (FnExpr.isInvalid())
return ExprError();
+ // Determine the result type.
+ QualType ResultTy = FnDecl->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
+
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),
Args, ResultTy, VK, OpLoc,
@@ -10481,6 +10824,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Diag(OpLoc, diag::err_ovl_no_viable_oper)
<< BinaryOperator::getOpcodeStr(Opc)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ if (Args[0]->getType()->isIncompleteType()) {
+ Diag(OpLoc, diag::note_assign_lhs_incomplete)
+ << Args[0]->getType()
+ << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ }
} else {
// This is an erroneous use of an operator which can be overloaded by
// a non-member function. Check for non-member operators which were
@@ -10621,11 +10969,6 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
Args[1] = InputInit.takeAs<Expr>();
- // Determine the result type
- QualType ResultTy = FnDecl->getResultType();
- ExprValueKind VK = Expr::getValueKindForType(ResultTy);
- ResultTy = ResultTy.getNonLValueExprType(Context);
-
// Build the actual expression node.
DeclarationNameInfo OpLocInfo(OpName, LLoc);
OpLocInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
@@ -10637,6 +10980,11 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
if (FnExpr.isInvalid())
return ExprError();
+ // Determine the result type
+ QualType ResultTy = FnDecl->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
+
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
FnExpr.take(), Args,
@@ -10716,8 +11064,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
/// member function.
ExprResult
Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
- SourceLocation LParenLoc, Expr **Args,
- unsigned NumArgs, SourceLocation RParenLoc) {
+ SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation RParenLoc) {
assert(MemExprE->getType() == Context.BoundMemberTy ||
MemExprE->getType() == Context.OverloadTy);
@@ -10758,8 +11107,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
}
CXXMemberCallExpr *call
- = new (Context) CXXMemberCallExpr(Context, MemExprE,
- llvm::makeArrayRef(Args, NumArgs),
+ = new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
resultType, valueKind, RParenLoc);
if (CheckCallReturnType(proto->getResultType(),
@@ -10767,14 +11115,17 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
call, 0))
return ExprError();
- if (ConvertArgumentsForCall(call, op, 0, proto, Args, NumArgs, RParenLoc))
+ if (ConvertArgumentsForCall(call, op, 0, proto, Args, RParenLoc))
+ return ExprError();
+
+ if (CheckOtherCall(call, proto))
return ExprError();
return MaybeBindToTemporary(call);
}
UnbridgedCastsSet UnbridgedCasts;
- if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts))
+ if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts))
return ExprError();
MemberExpr *MemExpr;
@@ -10818,7 +11169,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
// Microsoft supports direct constructor calls.
if (getLangOpts().MicrosoftExt && isa<CXXConstructorDecl>(Func)) {
AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(),
- llvm::makeArrayRef(Args, NumArgs), CandidateSet);
+ Args, CandidateSet);
} else if ((Method = dyn_cast<CXXMethodDecl>(Func))) {
// If explicit template arguments were provided, we can't call a
// non-template member function.
@@ -10826,15 +11177,13 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
continue;
AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType,
- ObjectClassification,
- llvm::makeArrayRef(Args, NumArgs), CandidateSet,
+ ObjectClassification, Args, CandidateSet,
/*SuppressUserConversions=*/false);
} else {
AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func),
I.getPair(), ActingDC, TemplateArgs,
ObjectType, ObjectClassification,
- llvm::makeArrayRef(Args, NumArgs),
- CandidateSet,
+ Args, CandidateSet,
/*SuppressUsedConversions=*/false);
}
}
@@ -10852,22 +11201,29 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()))
return ExprError();
+ // If FoundDecl is different from Method (such as if one is a template
+ // and the other a specialization), make sure DiagnoseUseOfDecl is
+ // called on both.
+ // FIXME: This would be more comprehensively addressed by modifying
+ // DiagnoseUseOfDecl to accept both the FoundDecl and the decl
+ // being used.
+ if (Method != FoundDecl.getDecl() &&
+ DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc()))
+ return ExprError();
break;
case OR_No_Viable_Function:
Diag(UnresExpr->getMemberLoc(),
diag::err_ovl_no_viable_member_function_in_call)
<< DeclName << MemExprE->getSourceRange();
- CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
- llvm::makeArrayRef(Args, NumArgs));
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
// FIXME: Leaking incoming expressions!
return ExprError();
case OR_Ambiguous:
Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call)
<< DeclName << MemExprE->getSourceRange();
- CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
- llvm::makeArrayRef(Args, NumArgs));
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
// FIXME: Leaking incoming expressions!
return ExprError();
@@ -10877,8 +11233,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
<< DeclName
<< getDeletedOrUnavailableSuffix(Best->Function)
<< MemExprE->getSourceRange();
- CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
- llvm::makeArrayRef(Args, NumArgs));
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
// FIXME: Leaking incoming expressions!
return ExprError();
}
@@ -10888,8 +11243,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
// If overload resolution picked a static member, build a
// non-member call based on that function.
if (Method->isStatic()) {
- return BuildResolvedCallExpr(MemExprE, Method, LParenLoc,
- Args, NumArgs, RParenLoc);
+ return BuildResolvedCallExpr(MemExprE, Method, LParenLoc, Args,
+ RParenLoc);
}
MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens());
@@ -10901,8 +11256,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
assert(Method && "Member call to something that isn't a method?");
CXXMemberCallExpr *TheCall =
- new (Context) CXXMemberCallExpr(Context, MemExprE,
- llvm::makeArrayRef(Args, NumArgs),
+ new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
ResultType, VK, RParenLoc);
// Check for a valid return type.
@@ -10925,11 +11279,11 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
// Convert the rest of the arguments
const FunctionProtoType *Proto =
Method->getType()->getAs<FunctionProtoType>();
- if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, NumArgs,
+ if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args,
RParenLoc))
return ExprError();
- DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs);
+ DiagnoseSentinelCalls(Method, LParenLoc, Args);
if (CheckFunctionCall(Method, TheCall, Proto))
return ExprError();
@@ -10958,14 +11312,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
ExprResult
Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
+ MultiExprArg Args,
SourceLocation RParenLoc) {
if (checkPlaceholderForOverload(*this, Obj))
return ExprError();
ExprResult Object = Owned(Obj);
UnbridgedCastsSet UnbridgedCasts;
- if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts))
+ if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts))
return ExprError();
assert(Object.get()->getType()->isRecordType() && "Requires object type argument");
@@ -10992,8 +11346,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
AddMethodCandidate(Oper.getPair(), Object.get()->getType(),
- Object.get()->Classify(Context),
- llvm::makeArrayRef(Args, NumArgs), CandidateSet,
+ Object.get()->Classify(Context),
+ Args, CandidateSet,
/*SuppressUserConversions=*/ false);
}
@@ -11040,8 +11394,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
{
AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto,
- Object.get(), llvm::makeArrayRef(Args, NumArgs),
- CandidateSet);
+ Object.get(), Args, CandidateSet);
}
}
}
@@ -11066,16 +11419,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
Diag(Object.get()->getLocStart(),
diag::err_ovl_no_viable_object_call)
<< Object.get()->getType() << Object.get()->getSourceRange();
- CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
- llvm::makeArrayRef(Args, NumArgs));
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
break;
case OR_Ambiguous:
Diag(Object.get()->getLocStart(),
diag::err_ovl_ambiguous_object_call)
<< Object.get()->getType() << Object.get()->getSourceRange();
- CandidateSet.NoteCandidates(*this, OCD_ViableCandidates,
- llvm::makeArrayRef(Args, NumArgs));
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args);
break;
case OR_Deleted:
@@ -11085,8 +11436,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
<< Object.get()->getType()
<< getDeletedOrUnavailableSuffix(Best->Function)
<< Object.get()->getSourceRange();
- CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
- llvm::makeArrayRef(Args, NumArgs));
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
break;
}
@@ -11105,7 +11455,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
if (DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc))
return ExprError();
-
+ assert(Conv == Best->FoundDecl.getDecl() &&
+ "Found Decl & conversion-to-functionptr should be same, right?!");
// We selected one of the surrogate functions that converts the
// object parameter to a function pointer. Perform the conversion
// on the object argument, then let ActOnCallExpr finish the job.
@@ -11121,8 +11472,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
CK_UserDefinedConversion,
Call.get(), 0, VK_RValue));
- return ActOnCallExpr(S, Call.get(), LParenLoc, MultiExprArg(Args, NumArgs),
- RParenLoc);
+ return ActOnCallExpr(S, Call.get(), LParenLoc, Args, RParenLoc);
}
CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
@@ -11140,21 +11490,6 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
Method->getType()->getAs<FunctionProtoType>();
unsigned NumArgsInProto = Proto->getNumArgs();
- unsigned NumArgsToCheck = NumArgs;
-
- // Build the full argument list for the method call (the
- // implicit object parameter is placed at the beginning of the
- // list).
- Expr **MethodArgs;
- if (NumArgs < NumArgsInProto) {
- NumArgsToCheck = NumArgsInProto;
- MethodArgs = new Expr*[NumArgsInProto + 1];
- } else {
- MethodArgs = new Expr*[NumArgs + 1];
- }
- MethodArgs[0] = Object.get();
- for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
- MethodArgs[ArgIdx + 1] = Args[ArgIdx];
DeclarationNameInfo OpLocInfo(
Context.DeclarationNames.getCXXOperatorName(OO_Call), LParenLoc);
@@ -11166,17 +11501,23 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
if (NewFn.isInvalid())
return true;
+ // Build the full argument list for the method call (the implicit object
+ // parameter is placed at the beginning of the list).
+ llvm::OwningArrayPtr<Expr *> MethodArgs(new Expr*[Args.size() + 1]);
+ MethodArgs[0] = Object.get();
+ std::copy(Args.begin(), Args.end(), &MethodArgs[1]);
+
// Once we've built TheCall, all of the expressions are properly
// owned.
QualType ResultTy = Method->getResultType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
- CXXOperatorCallExpr *TheCall =
- new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.take(),
- llvm::makeArrayRef(MethodArgs, NumArgs+1),
- ResultTy, VK, RParenLoc, false);
- delete [] MethodArgs;
+ CXXOperatorCallExpr *TheCall = new (Context)
+ CXXOperatorCallExpr(Context, OO_Call, NewFn.take(),
+ llvm::makeArrayRef(MethodArgs.get(), Args.size() + 1),
+ ResultTy, VK, RParenLoc, false);
+ MethodArgs.reset();
if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall,
Method))
@@ -11184,10 +11525,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
// We may have default arguments. If so, we need to allocate more
// slots in the call for them.
- if (NumArgs < NumArgsInProto)
+ if (Args.size() < NumArgsInProto)
TheCall->setNumArgs(Context, NumArgsInProto + 1);
- else if (NumArgs > NumArgsInProto)
- NumArgsToCheck = NumArgsInProto;
bool IsError = false;
@@ -11202,9 +11541,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
TheCall->setArg(0, Object.take());
// Check the argument types.
- for (unsigned i = 0; i != NumArgsToCheck; i++) {
+ for (unsigned i = 0; i != NumArgsInProto; i++) {
Expr *Arg;
- if (i < NumArgs) {
+ if (i < Args.size()) {
Arg = Args[i];
// Pass the argument.
@@ -11234,7 +11573,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
// If this is a variadic call, handle args passed through "...".
if (Proto->isVariadic()) {
// Promote the arguments (C99 6.5.2.2p7).
- for (unsigned i = NumArgsInProto; i < NumArgs; i++) {
+ for (unsigned i = NumArgsInProto, e = Args.size(); i < e; i++) {
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0);
IsError |= Arg.isInvalid();
TheCall->setArg(i + 1, Arg.take());
@@ -11243,7 +11582,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
if (IsError) return true;
- DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs);
+ DiagnoseSentinelCalls(Method, LParenLoc, Args);
if (CheckFunctionCall(Method, TheCall, Proto))
return true;
@@ -11255,7 +11594,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
/// (if one exists), where @c Base is an expression of class type and
/// @c Member is the name of the member we're trying to find.
ExprResult
-Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
+Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
+ bool *NoArrowOperatorFound) {
assert(Base->getType()->isRecordType() &&
"left-hand side must have class type");
@@ -11299,10 +11639,21 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
break;
case OR_No_Viable_Function:
- if (CandidateSet.empty())
+ if (CandidateSet.empty()) {
+ QualType BaseType = Base->getType();
+ if (NoArrowOperatorFound) {
+ // Report this specific error to the caller instead of emitting a
+ // diagnostic, as requested.
+ *NoArrowOperatorFound = true;
+ return ExprError();
+ }
Diag(OpLoc, diag::err_typecheck_member_reference_arrow)
- << Base->getType() << Base->getSourceRange();
- else
+ << BaseType << Base->getSourceRange();
+ if (BaseType->isRecordType() && !BaseType->isPointerType()) {
+ Diag(OpLoc, diag::note_typecheck_member_reference_suggestion)
+ << FixItHint::CreateReplacement(OpLoc, ".");
+ }
+ } else
Diag(OpLoc, diag::err_ovl_no_viable_oper)
<< "operator->" << Base->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Base);
@@ -11473,7 +11824,7 @@ Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc,
/*NeedsADL=*/true, /*Overloaded=*/false,
FoundNames.begin(), FoundNames.end());
- bool CandidateSetError = buildOverloadedCallSet(S, Fn, Fn, &Range, 1, Loc,
+ bool CandidateSetError = buildOverloadedCallSet(S, Fn, Fn, Range, Loc,
CandidateSet, CallExpr);
if (CandidateSet->empty() || CandidateSetError) {
*CallExpr = ExprError();
@@ -11487,7 +11838,7 @@ Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc,
*CallExpr = ExprError();
return FRS_NoViableFunction;
}
- *CallExpr = FinishOverloadedCallExpr(*this, S, Fn, Fn, Loc, &Range, 1,
+ *CallExpr = FinishOverloadedCallExpr(*this, S, Fn, Fn, Loc, Range,
Loc, 0, CandidateSet, &Best,
OverloadResult,
/*AllowTypoCorrection=*/false);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
index 054d557e92d0..af74f0d4a3e8 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
@@ -101,6 +101,25 @@ namespace {
resultIndex);
}
+ if (ChooseExpr *ce = dyn_cast<ChooseExpr>(e)) {
+ assert(!ce->isConditionDependent());
+
+ Expr *LHS = ce->getLHS(), *RHS = ce->getRHS();
+ Expr *&rebuiltExpr = ce->isConditionTrue() ? LHS : RHS;
+ rebuiltExpr = rebuild(rebuiltExpr);
+
+ return new (S.Context) ChooseExpr(ce->getBuiltinLoc(),
+ ce->getCond(),
+ LHS, RHS,
+ rebuiltExpr->getType(),
+ rebuiltExpr->getValueKind(),
+ rebuiltExpr->getObjectKind(),
+ ce->getRParenLoc(),
+ ce->isConditionTrue(),
+ rebuiltExpr->isTypeDependent(),
+ rebuiltExpr->isValueDependent());
+ }
+
llvm_unreachable("bad expression to rebuild!");
}
};
@@ -575,9 +594,9 @@ bool ObjCPropertyOpBuilder::findSetter(bool warn) {
RefExpr->getImplicitPropertyGetter()->getSelector()
.getIdentifierInfoForSlot(0);
SetterSelector =
- SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
- S.PP.getSelectorTable(),
- getterName);
+ SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),
+ S.PP.getSelectorTable(),
+ getterName);
return false;
}
}
@@ -711,6 +730,16 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
op = opResult.take();
assert(op && "successful assignment left argument invalid?");
}
+ else if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(op)) {
+ Expr *Initializer = OVE->getSourceExpr();
+ // passing C++11 style initialized temporaries to objc++ properties
+ // requires special treatment by removing OpaqueValueExpr so type
+ // conversion takes place and adding the OpaqueValueExpr later on.
+ if (isa<InitListExpr>(Initializer) &&
+ Initializer->getType()->isVoidType()) {
+ op = Initializer;
+ }
+ }
}
// Arguments.
@@ -882,8 +911,8 @@ ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {
S.Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
SyntacticForm->getLocStart());
if (Level != DiagnosticsEngine::Ignored)
- S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr,
- SyntacticRefExpr->isMessagingGetter());
+ S.recordUseOfEvaluatedWeak(SyntacticRefExpr,
+ SyntacticRefExpr->isMessagingGetter());
}
return PseudoOpBuilder::complete(SyntacticForm);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
index 248665ac86cb..9bd8678c876a 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
@@ -65,7 +65,7 @@ StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc,
StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc,
SourceLocation EndLoc) {
- DeclGroupRef DG = dg.getAsVal<DeclGroupRef>();
+ DeclGroupRef DG = dg.get();
// If we have an invalid decl, just return an error.
if (DG.isNull()) return StmtError();
@@ -74,7 +74,7 @@ StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc,
}
void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
- DeclGroupRef DG = dg.getAsVal<DeclGroupRef>();
+ DeclGroupRef DG = dg.get();
// If we don't have a declaration, or we have an invalid declaration,
// just return.
@@ -93,9 +93,6 @@ void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
return;
}
- // suppress any potential 'unused variable' warning.
- var->setUsed();
-
// foreach variables are never actually initialized in the way that
// the parser came up with.
var->setInit(0);
@@ -294,11 +291,10 @@ sema::CompoundScopeInfo &Sema::getCurCompoundScope() const {
return getCurFunction()->CompoundScopes.back();
}
-StmtResult
-Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
- MultiStmtArg elts, bool isStmtExpr) {
- unsigned NumElts = elts.size();
- Stmt **Elts = elts.data();
+StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+ ArrayRef<Stmt *> Elts, bool isStmtExpr) {
+ const unsigned NumElts = Elts.size();
+
// If we're in C89 mode, check that we don't have any decls after stmts. If
// so, emit an extension diagnostic.
if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) {
@@ -335,9 +331,7 @@ Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
DiagnoseEmptyLoopBody(Elts[i], Elts[i + 1]);
}
- return Owned(new (Context) CompoundStmt(Context,
- llvm::makeArrayRef(Elts, NumElts),
- L, R));
+ return Owned(new (Context) CompoundStmt(Context, Elts, L, R));
}
StmtResult
@@ -592,52 +586,50 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
public:
SwitchConvertDiagnoser(Expr *Cond)
- : ICEConvertDiagnoser(false, true), Cond(Cond) { }
+ : ICEConvertDiagnoser(/*AllowScopedEnumerations*/true, false, true),
+ Cond(Cond) {}
- virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
- QualType T) {
+ virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) {
return S.Diag(Loc, diag::err_typecheck_statement_requires_integer) << T;
}
- virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
- QualType T) {
+ virtual SemaDiagnosticBuilder diagnoseIncomplete(
+ Sema &S, SourceLocation Loc, QualType T) {
return S.Diag(Loc, diag::err_switch_incomplete_class_type)
<< T << Cond->getSourceRange();
}
- virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
- QualType T,
- QualType ConvTy) {
+ virtual SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
return S.Diag(Loc, diag::err_switch_explicit_conversion) << T << ConvTy;
}
- virtual DiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
- QualType ConvTy) {
+ virtual SemaDiagnosticBuilder noteExplicitConv(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
return S.Diag(Conv->getLocation(), diag::note_switch_conversion)
<< ConvTy->isEnumeralType() << ConvTy;
}
- virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
- QualType T) {
+ virtual SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
+ QualType T) {
return S.Diag(Loc, diag::err_switch_multiple_conversions) << T;
}
- virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
- QualType ConvTy) {
+ virtual SemaDiagnosticBuilder noteAmbiguous(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
return S.Diag(Conv->getLocation(), diag::note_switch_conversion)
<< ConvTy->isEnumeralType() << ConvTy;
}
- virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,
- QualType T,
- QualType ConvTy) {
- return DiagnosticBuilder::getEmpty();
+ virtual SemaDiagnosticBuilder diagnoseConversion(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ llvm_unreachable("conversion functions are permitted");
}
} SwitchDiagnoser(Cond);
- CondResult
- = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond, SwitchDiagnoser,
- /*AllowScopedEnumerations*/ true);
+ CondResult =
+ PerformContextualImplicitConversion(SwitchLoc, Cond, SwitchDiagnoser);
if (CondResult.isInvalid()) return StmtError();
Cond = CondResult.take();
@@ -1122,9 +1114,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
void
Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
Expr *SrcExpr) {
- unsigned DIAG = diag::warn_not_in_enum_assignement;
- if (Diags.getDiagnosticLevel(DIAG, SrcExpr->getExprLoc())
- == DiagnosticsEngine::Ignored)
+ if (Diags.getDiagnosticLevel(diag::warn_not_in_enum_assignment,
+ SrcExpr->getExprLoc()) ==
+ DiagnosticsEngine::Ignored)
return;
if (const EnumType *ET = DstType->getAs<EnumType>())
@@ -1133,13 +1125,14 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
if (!SrcExpr->isTypeDependent() && !SrcExpr->isValueDependent() &&
SrcExpr->isIntegerConstantExpr(Context)) {
// Get the bitwidth of the enum value before promotions.
- unsigned DstWith = Context.getIntWidth(DstType);
+ unsigned DstWidth = Context.getIntWidth(DstType);
bool DstIsSigned = DstType->isSignedIntegerOrEnumerationType();
llvm::APSInt RhsVal = SrcExpr->EvaluateKnownConstInt(Context);
+ AdjustAPSInt(RhsVal, DstWidth, DstIsSigned);
const EnumDecl *ED = ET->getDecl();
- typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64>
- EnumValsTy;
+ typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64>
+ EnumValsTy;
EnumValsTy EnumVals;
// Gather all enum values, set their type and sort them,
@@ -1147,21 +1140,21 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin();
EDI != ED->enumerator_end(); ++EDI) {
llvm::APSInt Val = EDI->getInitVal();
- AdjustAPSInt(Val, DstWith, DstIsSigned);
+ AdjustAPSInt(Val, DstWidth, DstIsSigned);
EnumVals.push_back(std::make_pair(Val, *EDI));
}
if (EnumVals.empty())
return;
std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals);
EnumValsTy::iterator EIend =
- std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);
+ std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);
- // See which case values aren't in enum.
+ // See which values aren't in the enum.
EnumValsTy::const_iterator EI = EnumVals.begin();
while (EI != EIend && EI->first < RhsVal)
EI++;
if (EI == EIend || EI->first != RhsVal) {
- Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignement)
+ Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)
<< DstType;
}
}
@@ -1220,77 +1213,77 @@ namespace {
// of the excluded constructs are used.
class DeclExtractor : public EvaluatedExprVisitor<DeclExtractor> {
llvm::SmallPtrSet<VarDecl*, 8> &Decls;
- SmallVector<SourceRange, 10> &Ranges;
+ SmallVectorImpl<SourceRange> &Ranges;
bool Simple;
-public:
- typedef EvaluatedExprVisitor<DeclExtractor> Inherited;
-
- DeclExtractor(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls,
- SmallVector<SourceRange, 10> &Ranges) :
- Inherited(S.Context),
- Decls(Decls),
- Ranges(Ranges),
- Simple(true) {}
+ public:
+ typedef EvaluatedExprVisitor<DeclExtractor> Inherited;
- bool isSimple() { return Simple; }
+ DeclExtractor(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls,
+ SmallVectorImpl<SourceRange> &Ranges) :
+ Inherited(S.Context),
+ Decls(Decls),
+ Ranges(Ranges),
+ Simple(true) {}
- // Replaces the method in EvaluatedExprVisitor.
- void VisitMemberExpr(MemberExpr* E) {
- Simple = false;
- }
+ bool isSimple() { return Simple; }
- // Any Stmt not whitelisted will cause the condition to be marked complex.
- void VisitStmt(Stmt *S) {
- Simple = false;
- }
+ // Replaces the method in EvaluatedExprVisitor.
+ void VisitMemberExpr(MemberExpr* E) {
+ Simple = false;
+ }
- void VisitBinaryOperator(BinaryOperator *E) {
- Visit(E->getLHS());
- Visit(E->getRHS());
- }
+ // Any Stmt not whitelisted will cause the condition to be marked complex.
+ void VisitStmt(Stmt *S) {
+ Simple = false;
+ }
- void VisitCastExpr(CastExpr *E) {
- Visit(E->getSubExpr());
- }
+ void VisitBinaryOperator(BinaryOperator *E) {
+ Visit(E->getLHS());
+ Visit(E->getRHS());
+ }
- void VisitUnaryOperator(UnaryOperator *E) {
- // Skip checking conditionals with derefernces.
- if (E->getOpcode() == UO_Deref)
- Simple = false;
- else
+ void VisitCastExpr(CastExpr *E) {
Visit(E->getSubExpr());
- }
+ }
- void VisitConditionalOperator(ConditionalOperator *E) {
- Visit(E->getCond());
- Visit(E->getTrueExpr());
- Visit(E->getFalseExpr());
- }
+ void VisitUnaryOperator(UnaryOperator *E) {
+ // Skip checking conditionals with derefernces.
+ if (E->getOpcode() == UO_Deref)
+ Simple = false;
+ else
+ Visit(E->getSubExpr());
+ }
- void VisitParenExpr(ParenExpr *E) {
- Visit(E->getSubExpr());
- }
+ void VisitConditionalOperator(ConditionalOperator *E) {
+ Visit(E->getCond());
+ Visit(E->getTrueExpr());
+ Visit(E->getFalseExpr());
+ }
- void VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
- Visit(E->getOpaqueValue()->getSourceExpr());
- Visit(E->getFalseExpr());
- }
+ void VisitParenExpr(ParenExpr *E) {
+ Visit(E->getSubExpr());
+ }
+
+ void VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
+ Visit(E->getOpaqueValue()->getSourceExpr());
+ Visit(E->getFalseExpr());
+ }
- void VisitIntegerLiteral(IntegerLiteral *E) { }
- void VisitFloatingLiteral(FloatingLiteral *E) { }
- void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { }
- void VisitCharacterLiteral(CharacterLiteral *E) { }
- void VisitGNUNullExpr(GNUNullExpr *E) { }
- void VisitImaginaryLiteral(ImaginaryLiteral *E) { }
+ void VisitIntegerLiteral(IntegerLiteral *E) { }
+ void VisitFloatingLiteral(FloatingLiteral *E) { }
+ void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { }
+ void VisitCharacterLiteral(CharacterLiteral *E) { }
+ void VisitGNUNullExpr(GNUNullExpr *E) { }
+ void VisitImaginaryLiteral(ImaginaryLiteral *E) { }
- void VisitDeclRefExpr(DeclRefExpr *E) {
- VarDecl *VD = dyn_cast<VarDecl>(E->getDecl());
- if (!VD) return;
+ void VisitDeclRefExpr(DeclRefExpr *E) {
+ VarDecl *VD = dyn_cast<VarDecl>(E->getDecl());
+ if (!VD) return;
- Ranges.push_back(E->getSourceRange());
+ Ranges.push_back(E->getSourceRange());
- Decls.insert(VD);
- }
+ Decls.insert(VD);
+ }
}; // end class DeclExtractor
@@ -1300,66 +1293,67 @@ public:
llvm::SmallPtrSet<VarDecl*, 8> &Decls;
bool FoundDecl;
-public:
- typedef EvaluatedExprVisitor<DeclMatcher> Inherited;
+ public:
+ typedef EvaluatedExprVisitor<DeclMatcher> Inherited;
- DeclMatcher(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls, Stmt *Statement) :
- Inherited(S.Context), Decls(Decls), FoundDecl(false) {
- if (!Statement) return;
+ DeclMatcher(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls,
+ Stmt *Statement) :
+ Inherited(S.Context), Decls(Decls), FoundDecl(false) {
+ if (!Statement) return;
- Visit(Statement);
- }
+ Visit(Statement);
+ }
- void VisitReturnStmt(ReturnStmt *S) {
- FoundDecl = true;
- }
+ void VisitReturnStmt(ReturnStmt *S) {
+ FoundDecl = true;
+ }
- void VisitBreakStmt(BreakStmt *S) {
- FoundDecl = true;
- }
+ void VisitBreakStmt(BreakStmt *S) {
+ FoundDecl = true;
+ }
- void VisitGotoStmt(GotoStmt *S) {
- FoundDecl = true;
- }
+ void VisitGotoStmt(GotoStmt *S) {
+ FoundDecl = true;
+ }
- void VisitCastExpr(CastExpr *E) {
- if (E->getCastKind() == CK_LValueToRValue)
- CheckLValueToRValueCast(E->getSubExpr());
- else
- Visit(E->getSubExpr());
- }
+ void VisitCastExpr(CastExpr *E) {
+ if (E->getCastKind() == CK_LValueToRValue)
+ CheckLValueToRValueCast(E->getSubExpr());
+ else
+ Visit(E->getSubExpr());
+ }
- void CheckLValueToRValueCast(Expr *E) {
- E = E->IgnoreParenImpCasts();
+ void CheckLValueToRValueCast(Expr *E) {
+ E = E->IgnoreParenImpCasts();
- if (isa<DeclRefExpr>(E)) {
- return;
- }
+ if (isa<DeclRefExpr>(E)) {
+ return;
+ }
- if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
- Visit(CO->getCond());
- CheckLValueToRValueCast(CO->getTrueExpr());
- CheckLValueToRValueCast(CO->getFalseExpr());
- return;
- }
+ if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
+ Visit(CO->getCond());
+ CheckLValueToRValueCast(CO->getTrueExpr());
+ CheckLValueToRValueCast(CO->getFalseExpr());
+ return;
+ }
- if (BinaryConditionalOperator *BCO =
- dyn_cast<BinaryConditionalOperator>(E)) {
- CheckLValueToRValueCast(BCO->getOpaqueValue()->getSourceExpr());
- CheckLValueToRValueCast(BCO->getFalseExpr());
- return;
- }
+ if (BinaryConditionalOperator *BCO =
+ dyn_cast<BinaryConditionalOperator>(E)) {
+ CheckLValueToRValueCast(BCO->getOpaqueValue()->getSourceExpr());
+ CheckLValueToRValueCast(BCO->getFalseExpr());
+ return;
+ }
- Visit(E);
- }
+ Visit(E);
+ }
- void VisitDeclRefExpr(DeclRefExpr *E) {
- if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()))
- if (Decls.count(VD))
- FoundDecl = true;
- }
+ void VisitDeclRefExpr(DeclRefExpr *E) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()))
+ if (Decls.count(VD))
+ FoundDecl = true;
+ }
- bool FoundDeclInUse() { return FoundDecl; }
+ bool FoundDeclInUse() { return FoundDecl; }
}; // end class DeclMatcher
@@ -1411,7 +1405,7 @@ public:
// Load SourceRanges into diagnostic if there is room.
// Otherwise, load the SourceRange of the conditional expression.
if (Ranges.size() <= PartialDiagnostic::MaxArguments)
- for (SmallVector<SourceRange, 10>::iterator I = Ranges.begin(),
+ for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(),
E = Ranges.end();
I != E; ++I)
PDiag << *I;
@@ -1421,6 +1415,104 @@ public:
S.Diag(Ranges.begin()->getBegin(), PDiag);
}
+ // If Statement is an incemement or decrement, return true and sets the
+ // variables Increment and DRE.
+ bool ProcessIterationStmt(Sema &S, Stmt* Statement, bool &Increment,
+ DeclRefExpr *&DRE) {
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(Statement)) {
+ switch (UO->getOpcode()) {
+ default: return false;
+ case UO_PostInc:
+ case UO_PreInc:
+ Increment = true;
+ break;
+ case UO_PostDec:
+ case UO_PreDec:
+ Increment = false;
+ break;
+ }
+ DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr());
+ return DRE;
+ }
+
+ if (CXXOperatorCallExpr *Call = dyn_cast<CXXOperatorCallExpr>(Statement)) {
+ FunctionDecl *FD = Call->getDirectCallee();
+ if (!FD || !FD->isOverloadedOperator()) return false;
+ switch (FD->getOverloadedOperator()) {
+ default: return false;
+ case OO_PlusPlus:
+ Increment = true;
+ break;
+ case OO_MinusMinus:
+ Increment = false;
+ break;
+ }
+ DRE = dyn_cast<DeclRefExpr>(Call->getArg(0));
+ return DRE;
+ }
+
+ return false;
+ }
+
+ // A visitor to determine if a continue statement is a subexpression.
+ class ContinueFinder : public EvaluatedExprVisitor<ContinueFinder> {
+ bool Found;
+ public:
+ ContinueFinder(Sema &S, Stmt* Body) :
+ Inherited(S.Context),
+ Found(false) {
+ Visit(Body);
+ }
+
+ typedef EvaluatedExprVisitor<ContinueFinder> Inherited;
+
+ void VisitContinueStmt(ContinueStmt* E) {
+ Found = true;
+ }
+
+ bool ContinueFound() { return Found; }
+
+ }; // end class ContinueFinder
+
+ // Emit a warning when a loop increment/decrement appears twice per loop
+ // iteration. The conditions which trigger this warning are:
+ // 1) The last statement in the loop body and the third expression in the
+ // for loop are both increment or both decrement of the same variable
+ // 2) No continue statements in the loop body.
+ void CheckForRedundantIteration(Sema &S, Expr *Third, Stmt *Body) {
+ // Return when there is nothing to check.
+ if (!Body || !Third) return;
+
+ if (S.Diags.getDiagnosticLevel(diag::warn_redundant_loop_iteration,
+ Third->getLocStart())
+ == DiagnosticsEngine::Ignored)
+ return;
+
+ // Get the last statement from the loop body.
+ CompoundStmt *CS = dyn_cast<CompoundStmt>(Body);
+ if (!CS || CS->body_empty()) return;
+ Stmt *LastStmt = CS->body_back();
+ if (!LastStmt) return;
+
+ bool LoopIncrement, LastIncrement;
+ DeclRefExpr *LoopDRE, *LastDRE;
+
+ if (!ProcessIterationStmt(S, Third, LoopIncrement, LoopDRE)) return;
+ if (!ProcessIterationStmt(S, LastStmt, LastIncrement, LastDRE)) return;
+
+ // Check that the two statements are both increments or both decrements
+ // on the same varaible.
+ if (LoopIncrement != LastIncrement ||
+ LoopDRE->getDecl() != LastDRE->getDecl()) return;
+
+ if (ContinueFinder(S, Body).ContinueFound()) return;
+
+ S.Diag(LastDRE->getLocation(), diag::warn_redundant_loop_iteration)
+ << LastDRE->getDecl() << LastIncrement;
+ S.Diag(LoopDRE->getLocation(), diag::note_loop_iteration_here)
+ << LoopIncrement;
+ }
+
} // end namespace
StmtResult
@@ -1447,6 +1539,7 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
}
CheckForLoopConditionalStatement(*this, second.get(), third.get(), Body);
+ CheckForRedundantIteration(*this, third.get(), Body);
ExprResult SecondResult(second.release());
VarDecl *ConditionVar = 0;
@@ -1618,6 +1711,9 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
<< First->getSourceRange());
FirstType = static_cast<Expr*>(First)->getType();
+ if (FirstType.isConstQualified())
+ Diag(ForLoc, diag::err_selector_element_const_type)
+ << FirstType << First->getSourceRange();
}
if (!FirstType->isDependentType() &&
!FirstType->isObjCObjectPointerType() &&
@@ -1738,10 +1834,10 @@ StmtResult
Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
Stmt *First, SourceLocation ColonLoc, Expr *Range,
SourceLocation RParenLoc, BuildForRangeKind Kind) {
- if (!First || !Range)
+ if (!First)
return StmtError();
- if (ObjCEnumerationCollection(Range))
+ if (Range && ObjCEnumerationCollection(Range))
return ActOnObjCForCollectionStmt(ForLoc, First, Range, RParenLoc);
DeclStmt *DS = dyn_cast<DeclStmt>(First);
@@ -1751,11 +1847,13 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
Diag(DS->getStartLoc(), diag::err_type_defined_in_for_range);
return StmtError();
}
- if (DS->getSingleDecl()->isInvalidDecl())
- return StmtError();
- if (DiagnoseUnexpandedParameterPack(Range, UPPC_Expression))
+ Decl *LoopVar = DS->getSingleDecl();
+ if (LoopVar->isInvalidDecl() || !Range ||
+ DiagnoseUnexpandedParameterPack(Range, UPPC_Expression)) {
+ LoopVar->setInvalidDecl();
return StmtError();
+ }
// Build auto && __range = range-init
SourceLocation RangeLoc = Range->getLocStart();
@@ -1763,15 +1861,20 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
Context.getAutoRRefDeductType(),
"__range");
if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
- diag::err_for_range_deduction_failure))
+ diag::err_for_range_deduction_failure)) {
+ LoopVar->setInvalidDecl();
return StmtError();
+ }
// Claim the type doesn't contain auto: we've already done the checking.
DeclGroupPtrTy RangeGroup =
- BuildDeclaratorGroup((Decl**)&RangeVar, 1, /*TypeMayContainAuto=*/false);
+ BuildDeclaratorGroup(llvm::MutableArrayRef<Decl *>((Decl **)&RangeVar, 1),
+ /*TypeMayContainAuto=*/ false);
StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc);
- if (RangeDecl.isInvalid())
+ if (RangeDecl.isInvalid()) {
+ LoopVar->setInvalidDecl();
return StmtError();
+ }
return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(),
/*BeginEndDecl=*/0, /*Cond=*/0, /*Inc=*/0, DS,
@@ -1900,6 +2003,22 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S,
Sema::BFRK_Rebuild);
}
+namespace {
+/// RAII object to automatically invalidate a declaration if an error occurs.
+struct InvalidateOnErrorScope {
+ InvalidateOnErrorScope(Sema &SemaRef, Decl *D, bool Enabled)
+ : Trap(SemaRef.Diags), D(D), Enabled(Enabled) {}
+ ~InvalidateOnErrorScope() {
+ if (Enabled && Trap.hasErrorOccurred())
+ D->setInvalidDecl();
+ }
+
+ DiagnosticErrorTrap Trap;
+ Decl *D;
+ bool Enabled;
+};
+}
+
/// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement.
StmtResult
Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
@@ -1915,12 +2034,17 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
DeclStmt *LoopVarDS = cast<DeclStmt>(LoopVarDecl);
VarDecl *LoopVar = cast<VarDecl>(LoopVarDS->getSingleDecl());
+ // If we hit any errors, mark the loop variable as invalid if its type
+ // contains 'auto'.
+ InvalidateOnErrorScope Invalidate(*this, LoopVar,
+ LoopVar->getType()->isUndeducedType());
+
StmtResult BeginEndDecl = BeginEnd;
ExprResult NotEqExpr = Cond, IncrExpr = Inc;
if (RangeVarType->isDependentType()) {
// The range is implicitly used as a placeholder when it is dependent.
- RangeVar->setUsed();
+ RangeVar->markUsed(Context);
// Deduce any 'auto's in the loop variable as 'DependentTy'. We'll fill
// them in properly when we instantiate the loop.
@@ -1981,8 +2105,6 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
RangeLoc));
else if (const VariableArrayType *VAT =
dyn_cast<VariableArrayType>(UnqAT))
- // FIXME: Need to build an OpaqueValueExpr for this rather than
- // recomputing it!
BoundExpr = VAT->getSizeExpr();
else {
// Can't be a DependentSizedArrayType or an IncompleteArrayType since
@@ -2009,10 +2131,25 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
BeginVar, EndVar, ColonLoc, &CandidateSet,
&BeginExpr, &EndExpr, &BEFFailure);
- // If building the range failed, try dereferencing the range expression
- // unless a diagnostic was issued or the end function is problematic.
if (Kind == BFRK_Build && RangeStatus == FRS_NoViableFunction &&
BEFFailure == BEF_begin) {
+ // If the range is being built from an array parameter, emit a
+ // a diagnostic that it is being treated as a pointer.
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Range)) {
+ if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
+ QualType ArrayTy = PVD->getOriginalType();
+ QualType PointerTy = PVD->getType();
+ if (PointerTy->isPointerType() && ArrayTy->isArrayType()) {
+ Diag(Range->getLocStart(), diag::err_range_on_array_parameter)
+ << RangeLoc << PVD << ArrayTy << PointerTy;
+ Diag(PVD->getLocation(), diag::note_declared_at);
+ return StmtError();
+ }
+ }
+ }
+
+ // If building the range failed, try dereferencing the range expression
+ // unless a diagnostic was issued or the end function is problematic.
StmtResult SR = RebuildForRangeWithDereference(*this, S, ForLoc,
LoopVarDecl, ColonLoc,
Range, RangeLoc,
@@ -2048,7 +2185,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
Decl *BeginEndDecls[] = { BeginVar, EndVar };
// Claim the type doesn't contain auto: we've already done the checking.
DeclGroupPtrTy BeginEndGroup =
- BuildDeclaratorGroup(BeginEndDecls, 2, /*TypeMayContainAuto=*/false);
+ BuildDeclaratorGroup(llvm::MutableArrayRef<Decl *>(BeginEndDecls, 2),
+ /*TypeMayContainAuto=*/ false);
BeginEndDecl = ActOnDeclStmt(BeginEndGroup, ColonLoc, ColonLoc);
const QualType BeginRefNonRefType = BeginType.getNonReferenceType();
@@ -2162,7 +2300,7 @@ StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc,
SourceLocation LabelLoc,
LabelDecl *TheDecl) {
getCurFunction()->setHasBranchIntoScope();
- TheDecl->setUsed();
+ TheDecl->markUsed(Context);
return Owned(new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc));
}
@@ -2356,28 +2494,51 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
return Res;
}
+/// \brief Determine whether the declared return type of the specified function
+/// contains 'auto'.
+static bool hasDeducedReturnType(FunctionDecl *FD) {
+ const FunctionProtoType *FPT =
+ FD->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>();
+ return FPT->getResultType()->isUndeducedType();
+}
+
/// ActOnCapScopeReturnStmt - Utility routine to type-check return statements
/// for capturing scopes.
///
StmtResult
Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// If this is the first return we've seen, infer the return type.
- // [expr.prim.lambda]p4 in C++11; block literals follow a superset of those
- // rules which allows multiple return statements.
+ // [expr.prim.lambda]p4 in C++11; block literals follow the same rules.
CapturingScopeInfo *CurCap = cast<CapturingScopeInfo>(getCurFunction());
QualType FnRetType = CurCap->ReturnType;
+ LambdaScopeInfo *CurLambda = dyn_cast<LambdaScopeInfo>(CurCap);
- // For blocks/lambdas with implicit return types, we check each return
- // statement individually, and deduce the common return type when the block
- // or lambda is completed.
- if (CurCap->HasImplicitReturnType) {
+ if (CurLambda && hasDeducedReturnType(CurLambda->CallOperator)) {
+ // In C++1y, the return type may involve 'auto'.
+ // FIXME: Blocks might have a return type of 'auto' explicitly specified.
+ FunctionDecl *FD = CurLambda->CallOperator;
+ if (CurCap->ReturnType.isNull())
+ CurCap->ReturnType = FD->getResultType();
+
+ AutoType *AT = CurCap->ReturnType->getContainedAutoType();
+ assert(AT && "lost auto type from lambda return type");
+ if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
+ FD->setInvalidDecl();
+ return StmtError();
+ }
+ CurCap->ReturnType = FnRetType = FD->getResultType();
+ } else if (CurCap->HasImplicitReturnType) {
+ // For blocks/lambdas with implicit return types, we check each return
+ // statement individually, and deduce the common return type when the block
+ // or lambda is completed.
+ // FIXME: Fold this into the 'auto' codepath above.
if (RetValExp && !isa<InitListExpr>(RetValExp)) {
ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp);
if (Result.isInvalid())
return StmtError();
RetValExp = Result.take();
- if (!RetValExp->isTypeDependent())
+ if (!CurContext->isDependentContext())
FnRetType = RetValExp->getType();
else
FnRetType = CurCap->ReturnType = Context.DependentTy;
@@ -2410,8 +2571,9 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
Diag(ReturnLoc, diag::err_return_in_captured_stmt) << CurRegion->getRegionName();
return StmtError();
} else {
- LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CurCap);
- if (LSI->CallOperator->getType()->getAs<FunctionType>()->getNoReturnAttr()){
+ assert(CurLambda && "unknown kind of captured scope");
+ if (CurLambda->CallOperator->getType()->getAs<FunctionType>()
+ ->getNoReturnAttr()) {
Diag(ReturnLoc, diag::err_noreturn_lambda_has_return_expr);
return StmtError();
}
@@ -2492,7 +2654,24 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
IgnoreParens().castAs<FunctionProtoTypeLoc>().getResultLoc();
QualType Deduced;
- if (RetExpr) {
+ if (RetExpr && isa<InitListExpr>(RetExpr)) {
+ // If the deduction is for a return statement and the initializer is
+ // a braced-init-list, the program is ill-formed.
+ Diag(RetExpr->getExprLoc(),
+ getCurLambda() ? diag::err_lambda_return_init_list
+ : diag::err_auto_fn_return_init_list)
+ << RetExpr->getSourceRange();
+ return true;
+ }
+
+ if (FD->isDependentContext()) {
+ // C++1y [dcl.spec.auto]p12:
+ // Return type deduction [...] occurs when the definition is
+ // instantiated even if the function body contains a return
+ // statement with a non-type-dependent operand.
+ assert(AT->isDeduced() && "should have deduced to dependent type");
+ return false;
+ } else if (RetExpr) {
// If the deduction is for a return statement and the initializer is
// a braced-init-list, the program is ill-formed.
if (isa<InitListExpr>(RetExpr)) {
@@ -2533,10 +2712,18 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
// the program is ill-formed.
if (AT->isDeduced() && !FD->isInvalidDecl()) {
AutoType *NewAT = Deduced->getContainedAutoType();
- if (!Context.hasSameType(AT->getDeducedType(), NewAT->getDeducedType())) {
- Diag(ReturnLoc, diag::err_auto_fn_different_deductions)
- << (AT->isDecltypeAuto() ? 1 : 0)
- << NewAT->getDeducedType() << AT->getDeducedType();
+ if (!FD->isDependentContext() &&
+ !Context.hasSameType(AT->getDeducedType(), NewAT->getDeducedType())) {
+ const LambdaScopeInfo *LambdaSI = getCurLambda();
+ if (LambdaSI && LambdaSI->HasImplicitReturnType) {
+ Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible)
+ << NewAT->getDeducedType() << AT->getDeducedType()
+ << true /*IsLambda*/;
+ } else {
+ Diag(ReturnLoc, diag::err_auto_fn_different_deductions)
+ << (AT->isDecltypeAuto() ? 1 : 0)
+ << NewAT->getDeducedType() << AT->getDeducedType();
+ }
return true;
}
} else if (!FD->isInvalidDecl()) {
@@ -2553,9 +2740,6 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp))
return StmtError();
- // FIXME: Unify this and C++1y auto function handling. In particular, we
- // should allow 'return { 1, 2, 3 };' in a lambda to deduce
- // 'std::initializer_list<int>'.
if (isa<CapturingScopeInfo>(getCurFunction()))
return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp);
@@ -2580,13 +2764,10 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// FIXME: Add a flag to the ScopeInfo to indicate whether we're performing
// deduction.
- bool HasDependentReturnType = FnRetType->isDependentType();
if (getLangOpts().CPlusPlus1y) {
if (AutoType *AT = FnRetType->getContainedAutoType()) {
FunctionDecl *FD = cast<FunctionDecl>(CurContext);
- if (CurContext->isDependentContext())
- HasDependentReturnType = true;
- else if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
+ if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
FD->setInvalidDecl();
return StmtError();
} else {
@@ -2595,6 +2776,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
}
}
+ bool HasDependentReturnType = FnRetType->isDependentType();
+
ReturnStmt *Result = 0;
if (FnRetType->isVoidType()) {
if (RetValExp) {
@@ -2699,11 +2882,10 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// If we have a related result type, we need to implicitly
// convert back to the formal result type. We can't pretend to
// initialize the result again --- we might end double-retaining
- // --- so instead we initialize a notional temporary; this can
- // lead to less-than-great diagnostics, but this stage is much
- // less likely to fail than the previous stage.
+ // --- so instead we initialize a notional temporary.
if (!RelatedRetType.isNull()) {
- Entity = InitializedEntity::InitializeTemporary(FnRetType);
+ Entity = InitializedEntity::InitializeRelatedResult(getCurMethodDecl(),
+ FnRetType);
Res = PerformCopyInitialization(Entity, ReturnLoc, RetValExp);
if (Res.isInvalid()) {
// FIXME: Clean up temporaries here anyway?
@@ -2886,18 +3068,16 @@ public:
/// ActOnCXXTryBlock - Takes a try compound-statement and a number of
/// handlers and creates a try statement from them.
-StmtResult
-Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
- MultiStmtArg RawHandlers) {
+StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
+ ArrayRef<Stmt *> Handlers) {
// Don't report an error if 'try' is used in system headers.
if (!getLangOpts().CXXExceptions &&
!getSourceManager().isInSystemHeader(TryLoc))
Diag(TryLoc, diag::err_exceptions_disabled) << "try";
- unsigned NumHandlers = RawHandlers.size();
+ const unsigned NumHandlers = Handlers.size();
assert(NumHandlers > 0 &&
"The parser shouldn't call this if there are no handlers.");
- Stmt **Handlers = RawHandlers.data();
SmallVector<TypeWithHandler, 8> TypesWithHandlers;
@@ -2945,8 +3125,7 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
// Neither of these are explicitly forbidden, but every compiler detects them
// and warns.
- return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock,
- llvm::makeArrayRef(Handlers, NumHandlers)));
+ return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers));
}
StmtResult
@@ -3051,7 +3230,7 @@ static void buildCapturedStmtCaptureList(
if (Cap->isThisCapture()) {
Captures.push_back(CapturedStmt::Capture(Cap->getLocation(),
CapturedStmt::VCK_This));
- CaptureInits.push_back(Cap->getCopyExpr());
+ CaptureInits.push_back(Cap->getInitExpr());
continue;
}
@@ -3061,7 +3240,7 @@ static void buildCapturedStmtCaptureList(
Captures.push_back(CapturedStmt::Capture(Cap->getLocation(),
CapturedStmt::VCK_ByRef,
Cap->getVariable()));
- CaptureInits.push_back(Cap->getCopyExpr());
+ CaptureInits.push_back(Cap->getInitExpr());
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
index fce95bebd1a9..9169032178fe 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
@@ -77,13 +77,12 @@ static bool isOperandMentioned(unsigned OpNo,
StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
bool IsVolatile, unsigned NumOutputs,
unsigned NumInputs, IdentifierInfo **Names,
- MultiExprArg constraints, MultiExprArg exprs,
+ MultiExprArg constraints, MultiExprArg Exprs,
Expr *asmString, MultiExprArg clobbers,
SourceLocation RParenLoc) {
unsigned NumClobbers = clobbers.size();
StringLiteral **Constraints =
reinterpret_cast<StringLiteral**>(constraints.data());
- Expr **Exprs = exprs.data();
StringLiteral *AsmString = cast<StringLiteral>(asmString);
StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data());
@@ -204,8 +203,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
GCCAsmStmt *NS =
new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
- NumInputs, Names, Constraints, Exprs, AsmString,
- NumClobbers, Clobbers, RParenLoc);
+ NumInputs, Names, Constraints, Exprs.data(),
+ AsmString, NumClobbers, Clobbers, RParenLoc);
// Validate the asm string, ensuring it makes sense given the operands we
// have.
SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces;
@@ -382,7 +381,9 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
/*trailing lparen*/ false,
- /*is & operand*/ false);
+ /*is & operand*/ false,
+ /*CorrectionCandidateCallback=*/0,
+ /*IsInlineAsmIdentifier=*/ true);
if (IsUnevaluatedContext)
PopExpressionEvaluationContext();
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
index b9695cc1e166..28603daa267c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -11,6 +11,7 @@
#include "TreeTransform.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
@@ -207,8 +208,9 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
R.suppressDiagnostics();
} else {
assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) ||
- isa<TypeAliasTemplateDecl>(TD));
- TemplateKind = TNK_Type_template;
+ isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD));
+ TemplateKind =
+ isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template;
}
}
@@ -256,7 +258,8 @@ void Sema::LookupTemplateName(LookupResult &Found,
assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
LookupCtx = computeDeclContext(ObjectType);
isDependent = ObjectType->isDependentType();
- assert((isDependent || !ObjectType->isIncompleteType()) &&
+ assert((isDependent || !ObjectType->isIncompleteType() ||
+ ObjectType->castAs<TagType>()->isBeingDefined()) &&
"Caller should have completed object type");
// Template names cannot appear inside an Objective-C class or object type.
@@ -328,20 +331,16 @@ void Sema::LookupTemplateName(LookupResult &Found,
Found.addDecl(Corrected.getCorrectionDecl());
FilterAcceptableTemplateNames(Found);
if (!Found.empty()) {
- std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
- std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
- if (LookupCtx)
- Diag(Found.getNameLoc(), diag::err_no_member_template_suggest)
- << Name << LookupCtx << CorrectedQuotedStr << SS.getRange()
- << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
- CorrectedStr);
- else
- Diag(Found.getNameLoc(), diag::err_no_template_suggest)
- << Name << CorrectedQuotedStr
- << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
- if (TemplateDecl *Template = Found.getAsSingle<TemplateDecl>())
- Diag(Template->getLocation(), diag::note_previous_decl)
- << CorrectedQuotedStr;
+ if (LookupCtx) {
+ std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
+ bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
+ Name.getAsString() == CorrectedStr;
+ diagnoseTypo(Corrected, PDiag(diag::err_no_member_template_suggest)
+ << Name << LookupCtx << DroppedSpecifier
+ << SS.getRange());
+ } else {
+ diagnoseTypo(Corrected, PDiag(diag::err_no_template_suggest) << Name);
+ }
}
} else {
Found.setLookupName(Name);
@@ -356,7 +355,7 @@ void Sema::LookupTemplateName(LookupResult &Found,
}
if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope &&
- !(getLangOpts().CPlusPlus11 && !Found.empty())) {
+ !getLangOpts().CPlusPlus11) {
// C++03 [basic.lookup.classref]p1:
// [...] If the lookup in the class of the object expression finds a
// template, the name is also looked up in the context of the entire
@@ -533,6 +532,15 @@ void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn,
TemplateArgsIn[I]));
}
+static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S,
+ SourceLocation Loc,
+ IdentifierInfo *Name) {
+ NamedDecl *PrevDecl = SemaRef.LookupSingleName(
+ S, Name, Loc, Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ if (PrevDecl && PrevDecl->isTemplateParameter())
+ SemaRef.DiagnoseTemplateParameterShadow(Loc, PrevDecl);
+}
+
/// ActOnTypeParameter - Called when a C++ template type parameter
/// (e.g., "typename T") has been parsed. Typename specifies whether
/// the keyword "typename" was used to declare the type parameter
@@ -554,16 +562,6 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
"Template type parameter not in template parameter scope!");
bool Invalid = false;
- if (ParamName) {
- NamedDecl *PrevDecl = LookupSingleName(S, ParamName, ParamNameLoc,
- LookupOrdinaryName,
- ForRedeclaration);
- if (PrevDecl && PrevDecl->isTemplateParameter()) {
- DiagnoseTemplateParameterShadow(ParamNameLoc, PrevDecl);
- PrevDecl = 0;
- }
- }
-
SourceLocation Loc = ParamNameLoc;
if (!ParamName)
Loc = KeyLoc;
@@ -577,6 +575,8 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
Param->setInvalidDecl();
if (ParamName) {
+ maybeDiagnoseTemplateParameterShadow(*this, S, ParamNameLoc, ParamName);
+
// Add the template parameter into the current scope.
S->AddDecl(Param);
IdResolver.AddDecl(Param);
@@ -682,23 +682,13 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
"Non-type template parameter not in template parameter scope!");
bool Invalid = false;
- IdentifierInfo *ParamName = D.getIdentifier();
- if (ParamName) {
- NamedDecl *PrevDecl = LookupSingleName(S, ParamName, D.getIdentifierLoc(),
- LookupOrdinaryName,
- ForRedeclaration);
- if (PrevDecl && PrevDecl->isTemplateParameter()) {
- DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
- PrevDecl = 0;
- }
- }
-
T = CheckNonTypeTemplateParameterType(T, D.getIdentifierLoc());
if (T.isNull()) {
T = Context.IntTy; // Recover with an 'int' type.
Invalid = true;
}
+ IdentifierInfo *ParamName = D.getIdentifier();
bool IsParameterPack = D.hasEllipsis();
NonTypeTemplateParmDecl *Param
= NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
@@ -707,11 +697,14 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
Depth, Position, ParamName, T,
IsParameterPack, TInfo);
Param->setAccess(AS_public);
-
+
if (Invalid)
Param->setInvalidDecl();
- if (D.getIdentifier()) {
+ if (ParamName) {
+ maybeDiagnoseTemplateParameterShadow(*this, S, D.getIdentifierLoc(),
+ ParamName);
+
// Add the template parameter into the current scope.
S->AddDecl(Param);
IdResolver.AddDecl(Param);
@@ -773,6 +766,8 @@ Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,
// If the template template parameter has a name, then link the identifier
// into the scope and lookup mechanisms.
if (Name) {
+ maybeDiagnoseTemplateParameterShadow(*this, S, NameLoc, Name);
+
S->AddDecl(Param);
IdResolver.AddDecl(Param);
}
@@ -882,10 +877,11 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// FIXME: Horrible, horrible hack! We can't currently represent this
// in the AST, and historically we have just ignored such friend
// class templates, so don't complain here.
- if (TUK != TUK_Friend)
- Diag(NameLoc, diag::err_template_qualified_declarator_no_match)
+ Diag(NameLoc, TUK == TUK_Friend
+ ? diag::warn_template_qualified_friend_ignored
+ : diag::err_template_qualified_declarator_no_match)
<< SS.getScopeRep() << SS.getRange();
- return true;
+ return TUK != TUK_Friend;
}
if (RequireCompleteDeclContext(SS, SemanticContext))
@@ -1032,13 +1028,14 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// template declaration. Skip this check for a friend in a dependent
// context, because the template parameter list might be dependent.
if (!(TUK == TUK_Friend && CurContext->isDependentContext()) &&
- CheckTemplateParameterList(TemplateParams,
- PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0,
- (SS.isSet() && SemanticContext &&
- SemanticContext->isRecord() &&
- SemanticContext->isDependentContext())
- ? TPC_ClassTemplateMember
- : TPC_ClassTemplate))
+ CheckTemplateParameterList(
+ TemplateParams,
+ PrevClassTemplate ? PrevClassTemplate->getTemplateParameters() : 0,
+ (SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
+ SemanticContext->isDependentContext())
+ ? TPC_ClassTemplateMember
+ : TUK == TUK_Friend ? TPC_FriendClassTemplate
+ : TPC_ClassTemplate))
Invalid = true;
if (SS.isSet()) {
@@ -1046,8 +1043,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// template out-of-line.
if (!SS.isInvalid() && !Invalid && !PrevClassTemplate) {
Diag(NameLoc, TUK == TUK_Friend ? diag::err_friend_decl_does_not_match
- : diag::err_member_def_does_not_match)
- << Name << SemanticContext << SS.getRange();
+ : diag::err_member_decl_does_not_match)
+ << Name << SemanticContext << /*IsDefinition*/true << SS.getRange();
Invalid = true;
}
}
@@ -1118,8 +1115,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
NewClass->setAccess(PrevClassTemplate->getAccess());
}
- NewTemplate->setObjectOfFriendDecl(/* PreviouslyDeclared = */
- PrevClassTemplate != NULL);
+ NewTemplate->setObjectOfFriendDecl();
// Friend templates are visible in fairly strange ways.
if (!CurContext->isDependentContext()) {
@@ -1158,6 +1154,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S,
SourceRange DefArgRange) {
switch (TPC) {
case Sema::TPC_ClassTemplate:
+ case Sema::TPC_VarTemplate:
case Sema::TPC_TypeAliasTemplate:
return false;
@@ -1186,6 +1183,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S,
<< DefArgRange;
return true;
+ case Sema::TPC_FriendClassTemplate:
case Sema::TPC_FriendFunctionTemplate:
// C++ [temp.param]p9:
// A default template-argument shall not be specified in a
@@ -1317,7 +1315,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
} else if (OldTypeParm && OldTypeParm->hasDefaultArgument()) {
// Merge the default argument from the old declaration to the
// new declaration.
- SawDefaultArgument = true;
NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgumentInfo(),
true);
PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc();
@@ -1354,7 +1351,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
if (!NewNonTypeParm->isPackExpansion())
SawParameterPack = true;
} else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() &&
- NewNonTypeParm->hasDefaultArgument()) {
+ NewNonTypeParm->hasDefaultArgument()) {
OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc();
NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc();
SawDefaultArgument = true;
@@ -1363,7 +1360,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
} else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument()) {
// Merge the default argument from the old declaration to the
// new declaration.
- SawDefaultArgument = true;
// FIXME: We need to create a new kind of "default argument"
// expression that points to a previous non-type template
// parameter.
@@ -1411,7 +1407,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
} else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument()) {
// Merge the default argument from the old declaration to the
// new declaration.
- SawDefaultArgument = true;
// FIXME: We need to create a new kind of "default argument" expression
// that points to a previous template template parameter.
NewTemplateParm->setDefaultArgument(
@@ -1431,7 +1426,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// If a template parameter of a primary class template or alias template
// is a template parameter pack, it shall be the last template parameter.
if (SawParameterPack && (NewParam + 1) != NewParamEnd &&
- (TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) {
+ (TPC == TPC_ClassTemplate || TPC == TPC_VarTemplate ||
+ TPC == TPC_TypeAliasTemplate)) {
Diag((*NewParam)->getLocation(),
diag::err_template_param_pack_must_be_last_template_parameter);
Invalid = true;
@@ -1584,8 +1580,6 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
/// \param ParamLists the template parameter lists, from the outermost to the
/// innermost template parameter lists.
///
-/// \param NumParamLists the number of template parameter lists in ParamLists.
-///
/// \param IsFriend Whether to apply the slightly different rules for
/// matching template parameters to scope specifiers in friend
/// declarations.
@@ -1599,15 +1593,10 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
/// template) or may have no template parameters (if we're declaring a
/// template specialization), or may be NULL (if what we're declaring isn't
/// itself a template).
-TemplateParameterList *
-Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
- SourceLocation DeclLoc,
- const CXXScopeSpec &SS,
- TemplateParameterList **ParamLists,
- unsigned NumParamLists,
- bool IsFriend,
- bool &IsExplicitSpecialization,
- bool &Invalid) {
+TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
+ SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS,
+ ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend,
+ bool &IsExplicitSpecialization, bool &Invalid) {
IsExplicitSpecialization = false;
Invalid = false;
@@ -1780,7 +1769,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
// unspecialized, except that the declaration shall not explicitly
// specialize a class member template if its en- closing class templates
// are not explicitly specialized as well.
- if (ParamIdx < NumParamLists) {
+ if (ParamIdx < ParamLists.size()) {
if (ParamLists[ParamIdx]->size() == 0) {
if (SawNonEmptyTemplateParameterList) {
Diag(DeclLoc, diag::err_specialize_member_of_template)
@@ -1798,8 +1787,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
// here, then it's an explicit specialization.
if (TypeIdx == NumTypes - 1)
IsExplicitSpecialization = true;
-
- if (ParamIdx < NumParamLists) {
+
+ if (ParamIdx < ParamLists.size()) {
if (ParamLists[ParamIdx]->size() > 0) {
// The header has template parameters when it shouldn't. Complain.
Diag(ParamLists[ParamIdx]->getTemplateLoc(),
@@ -1820,7 +1809,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
if (!IsFriend) {
// We don't have a template header, but we should.
SourceLocation ExpectedTemplateLoc;
- if (NumParamLists > 0)
+ if (!ParamLists.empty())
ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
else
ExpectedTemplateLoc = DeclStartLoc;
@@ -1839,15 +1828,15 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
// assume that empty parameter lists are supposed to match this
// template-id.
if (IsFriend && T->isDependentType()) {
- if (ParamIdx < NumParamLists &&
+ if (ParamIdx < ParamLists.size() &&
DependsOnTemplateParameters(T, ParamLists[ParamIdx]))
ExpectedTemplateParams = 0;
else
continue;
}
- if (ParamIdx < NumParamLists) {
- // Check the template parameter list, if we can.
+ if (ParamIdx < ParamLists.size()) {
+ // Check the template parameter list, if we can.
if (ExpectedTemplateParams &&
!TemplateParameterListsAreEqual(ParamLists[ParamIdx],
ExpectedTemplateParams,
@@ -1874,25 +1863,25 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
// If there were at least as many template-ids as there were template
// parameter lists, then there are no template parameter lists remaining for
// the declaration itself.
- if (ParamIdx >= NumParamLists)
+ if (ParamIdx >= ParamLists.size())
return 0;
// If there were too many template parameter lists, complain about that now.
- if (ParamIdx < NumParamLists - 1) {
+ if (ParamIdx < ParamLists.size() - 1) {
bool HasAnyExplicitSpecHeader = false;
bool AllExplicitSpecHeaders = true;
- for (unsigned I = ParamIdx; I != NumParamLists - 1; ++I) {
+ for (unsigned I = ParamIdx, E = ParamLists.size() - 1; I != E; ++I) {
if (ParamLists[I]->size() == 0)
HasAnyExplicitSpecHeader = true;
else
AllExplicitSpecHeaders = false;
}
-
+
Diag(ParamLists[ParamIdx]->getTemplateLoc(),
- AllExplicitSpecHeaders? diag::warn_template_spec_extra_headers
- : diag::err_template_spec_extra_headers)
- << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(),
- ParamLists[NumParamLists - 2]->getRAngleLoc());
+ AllExplicitSpecHeaders ? diag::warn_template_spec_extra_headers
+ : diag::err_template_spec_extra_headers)
+ << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(),
+ ParamLists[ParamLists.size() - 2]->getRAngleLoc());
// If there was a specialization somewhere, such that 'template<>' is
// not required, and there were any 'template<>' headers, note where the
@@ -1916,8 +1905,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
// unspecialized, except that the declaration shall not explicitly
// specialize a class member template if its en- closing class templates
// are not explicitly specialized as well.
- if (ParamLists[NumParamLists - 1]->size() == 0 &&
- SawNonEmptyTemplateParameterList) {
+ if (ParamLists.back()->size() == 0 && SawNonEmptyTemplateParameterList) {
Diag(DeclLoc, diag::err_specialize_member_of_template)
<< ParamLists[ParamIdx]->getSourceRange();
Invalid = true;
@@ -1927,17 +1915,20 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
// Return the last template parameter list, which corresponds to the
// entity being declared.
- return ParamLists[NumParamLists - 1];
+ return ParamLists.back();
}
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
- : isa<TypeAliasTemplateDecl>(Template)? 2
- : 3)
- << Template->getDeclName();
+ << (isa<FunctionTemplateDecl>(Template)
+ ? 0
+ : isa<ClassTemplateDecl>(Template)
+ ? 1
+ : isa<VarTemplateDecl>(Template)
+ ? 2
+ : isa<TypeAliasTemplateDecl>(Template) ? 3 : 4)
+ << Template->getDeclName();
return;
}
@@ -2007,11 +1998,11 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
TemplateArgLists.addOuterTemplateArguments(&TemplateArgs);
unsigned Depth = AliasTemplate->getTemplateParameters()->getDepth();
for (unsigned I = 0; I < Depth; ++I)
- TemplateArgLists.addOuterTemplateArguments(0, 0);
+ TemplateArgLists.addOuterTemplateArguments(None);
LocalInstantiationScope Scope(*this);
InstantiatingTemplate Inst(*this, TemplateLoc, Template);
- if (Inst)
+ if (Inst.isInvalid())
return QualType();
CanonType = SubstType(Pattern->getUnderlyingType(),
@@ -2102,6 +2093,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext());
}
+ // Diagnose uses of this specialization.
+ (void)DiagnoseUseOfDecl(Decl, TemplateLoc);
+
CanonType = Context.getTypeDeclType(Decl);
assert(isa<RecordType>(CanonType) &&
"type of non-dependent specialization is not a RecordType");
@@ -2123,7 +2117,7 @@ Sema::ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
if (SS.isInvalid())
return true;
- TemplateName Template = TemplateD.getAsVal<TemplateName>();
+ TemplateName Template = TemplateD.get();
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
@@ -2190,7 +2184,7 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation RAngleLoc) {
- TemplateName Template = TemplateD.getAsVal<TemplateName>();
+ TemplateName Template = TemplateD.get();
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
@@ -2272,6 +2266,499 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
}
+static bool CheckTemplatePartialSpecializationArgs(
+ Sema &S, TemplateParameterList *TemplateParams,
+ SmallVectorImpl<TemplateArgument> &TemplateArgs);
+
+static bool CheckTemplateSpecializationScope(Sema &S, NamedDecl *Specialized,
+ NamedDecl *PrevDecl,
+ SourceLocation Loc,
+ bool IsPartialSpecialization);
+
+static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D);
+
+static bool isTemplateArgumentTemplateParameter(
+ const TemplateArgument &Arg, unsigned Depth, unsigned Index) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::NullPtr:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Pack:
+ case TemplateArgument::TemplateExpansion:
+ return false;
+
+ case TemplateArgument::Type: {
+ QualType Type = Arg.getAsType();
+ const TemplateTypeParmType *TPT =
+ Arg.getAsType()->getAs<TemplateTypeParmType>();
+ return TPT && !Type.hasQualifiers() &&
+ TPT->getDepth() == Depth && TPT->getIndex() == Index;
+ }
+
+ case TemplateArgument::Expression: {
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg.getAsExpr());
+ if (!DRE || !DRE->getDecl())
+ return false;
+ const NonTypeTemplateParmDecl *NTTP =
+ dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
+ return NTTP && NTTP->getDepth() == Depth && NTTP->getIndex() == Index;
+ }
+
+ case TemplateArgument::Template:
+ const TemplateTemplateParmDecl *TTP =
+ dyn_cast_or_null<TemplateTemplateParmDecl>(
+ Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl());
+ return TTP && TTP->getDepth() == Depth && TTP->getIndex() == Index;
+ }
+ llvm_unreachable("unexpected kind of template argument");
+}
+
+static bool isSameAsPrimaryTemplate(TemplateParameterList *Params,
+ ArrayRef<TemplateArgument> Args) {
+ if (Params->size() != Args.size())
+ return false;
+
+ unsigned Depth = Params->getDepth();
+
+ for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+ TemplateArgument Arg = Args[I];
+
+ // If the parameter is a pack expansion, the argument must be a pack
+ // whose only element is a pack expansion.
+ if (Params->getParam(I)->isParameterPack()) {
+ if (Arg.getKind() != TemplateArgument::Pack || Arg.pack_size() != 1 ||
+ !Arg.pack_begin()->isPackExpansion())
+ return false;
+ Arg = Arg.pack_begin()->getPackExpansionPattern();
+ }
+
+ if (!isTemplateArgumentTemplateParameter(Arg, Depth, I))
+ return false;
+ }
+
+ return true;
+}
+
+DeclResult Sema::ActOnVarTemplateSpecialization(
+ Scope *S, VarTemplateDecl *VarTemplate, Declarator &D, TypeSourceInfo *DI,
+ SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
+ VarDecl::StorageClass SC, bool IsPartialSpecialization) {
+ assert(VarTemplate && "A variable template id without template?");
+
+ // D must be variable template id.
+ assert(D.getName().getKind() == UnqualifiedId::IK_TemplateId &&
+ "Variable template specialization is declared with a template it.");
+
+ TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+ SourceLocation TemplateNameLoc = D.getIdentifierLoc();
+ SourceLocation LAngleLoc = TemplateId->LAngleLoc;
+ SourceLocation RAngleLoc = TemplateId->RAngleLoc;
+ ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+ TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+ translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+ TemplateName Name(VarTemplate);
+
+ // Check for unexpanded parameter packs in any of the template arguments.
+ for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+ if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
+ UPPC_PartialSpecialization))
+ return true;
+
+ // Check that the template argument list is well-formed for this
+ // template.
+ SmallVector<TemplateArgument, 4> Converted;
+ if (CheckTemplateArgumentList(VarTemplate, TemplateNameLoc, TemplateArgs,
+ false, Converted))
+ return true;
+
+ // Check that the type of this variable template specialization
+ // matches the expected type.
+ TypeSourceInfo *ExpectedDI;
+ {
+ // Do substitution on the type of the declaration
+ TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack,
+ Converted.data(), Converted.size());
+ InstantiatingTemplate Inst(*this, TemplateKWLoc, VarTemplate);
+ if (Inst.isInvalid())
+ return true;
+ VarDecl *Templated = VarTemplate->getTemplatedDecl();
+ ExpectedDI =
+ SubstType(Templated->getTypeSourceInfo(),
+ MultiLevelTemplateArgumentList(TemplateArgList),
+ Templated->getTypeSpecStartLoc(), Templated->getDeclName());
+ }
+ if (!ExpectedDI)
+ return true;
+
+ // Find the variable template (partial) specialization declaration that
+ // corresponds to these arguments.
+ if (IsPartialSpecialization) {
+ if (CheckTemplatePartialSpecializationArgs(
+ *this, VarTemplate->getTemplateParameters(), Converted))
+ return true;
+
+ bool InstantiationDependent;
+ if (!Name.isDependent() &&
+ !TemplateSpecializationType::anyDependentTemplateArguments(
+ TemplateArgs.getArgumentArray(), TemplateArgs.size(),
+ InstantiationDependent)) {
+ Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
+ << VarTemplate->getDeclName();
+ IsPartialSpecialization = false;
+ }
+
+ if (isSameAsPrimaryTemplate(VarTemplate->getTemplateParameters(),
+ Converted)) {
+ // C++ [temp.class.spec]p9b3:
+ //
+ // -- The argument list of the specialization shall not be identical
+ // to the implicit argument list of the primary template.
+ Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
+ << /*variable template*/ 1
+ << /*is definition*/(SC != SC_Extern && !CurContext->isRecord())
+ << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
+ // FIXME: Recover from this by treating the declaration as a redeclaration
+ // of the primary template.
+ return true;
+ }
+ }
+
+ void *InsertPos = 0;
+ VarTemplateSpecializationDecl *PrevDecl = 0;
+
+ if (IsPartialSpecialization)
+ // FIXME: Template parameter list matters too
+ PrevDecl = VarTemplate->findPartialSpecialization(
+ Converted.data(), Converted.size(), InsertPos);
+ else
+ PrevDecl = VarTemplate->findSpecialization(Converted.data(),
+ Converted.size(), InsertPos);
+
+ VarTemplateSpecializationDecl *Specialization = 0;
+
+ // Check whether we can declare a variable template specialization in
+ // the current scope.
+ if (CheckTemplateSpecializationScope(*this, VarTemplate, PrevDecl,
+ TemplateNameLoc,
+ IsPartialSpecialization))
+ return true;
+
+ if (PrevDecl && PrevDecl->getSpecializationKind() == TSK_Undeclared) {
+ // Since the only prior variable template specialization with these
+ // arguments was referenced but not declared, reuse that
+ // 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);
+ PrevDecl = 0;
+ } else if (IsPartialSpecialization) {
+ // Create a new class template partial specialization declaration node.
+ VarTemplatePartialSpecializationDecl *PrevPartial =
+ cast_or_null<VarTemplatePartialSpecializationDecl>(PrevDecl);
+ VarTemplatePartialSpecializationDecl *Partial =
+ VarTemplatePartialSpecializationDecl::Create(
+ Context, VarTemplate->getDeclContext(), TemplateKWLoc,
+ TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC,
+ Converted.data(), Converted.size(), TemplateArgs);
+
+ if (!PrevPartial)
+ VarTemplate->AddPartialSpecialization(Partial, InsertPos);
+ Specialization = Partial;
+
+ // If we are providing an explicit specialization of a member variable
+ // template specialization, make a note of that.
+ if (PrevPartial && PrevPartial->getInstantiatedFromMember())
+ PrevPartial->setMemberSpecialization();
+
+ // Check that all of the template parameters of the variable template
+ // partial specialization are deducible from the template
+ // arguments. If not, this variable template partial specialization
+ // will never be used.
+ llvm::SmallBitVector DeducibleParams(TemplateParams->size());
+ MarkUsedTemplateParameters(Partial->getTemplateArgs(), true,
+ TemplateParams->getDepth(), DeducibleParams);
+
+ if (!DeducibleParams.all()) {
+ unsigned NumNonDeducible =
+ DeducibleParams.size() - DeducibleParams.count();
+ Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible)
+ << /*variable template*/ 1 << (NumNonDeducible > 1)
+ << SourceRange(TemplateNameLoc, RAngleLoc);
+ for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
+ if (!DeducibleParams[I]) {
+ NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
+ if (Param->getDeclName())
+ Diag(Param->getLocation(), diag::note_partial_spec_unused_parameter)
+ << Param->getDeclName();
+ else
+ Diag(Param->getLocation(), diag::note_partial_spec_unused_parameter)
+ << "<anonymous>";
+ }
+ }
+ }
+ } else {
+ // Create a new class template specialization declaration node for
+ // this explicit specialization or friend declaration.
+ Specialization = VarTemplateSpecializationDecl::Create(
+ Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc,
+ VarTemplate, DI->getType(), DI, SC, Converted.data(), Converted.size());
+ Specialization->setTemplateArgsInfo(TemplateArgs);
+
+ if (!PrevDecl)
+ VarTemplate->AddSpecialization(Specialization, InsertPos);
+ }
+
+ // C++ [temp.expl.spec]p6:
+ // If a template, a member template or the member of a class template is
+ // explicitly specialized then that specialization shall be declared
+ // 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.
+ if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) {
+ bool Okay = false;
+ for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
+ // Is there any previous explicit specialization declaration?
+ if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
+ Okay = true;
+ break;
+ }
+ }
+
+ if (!Okay) {
+ SourceRange Range(TemplateNameLoc, RAngleLoc);
+ Diag(TemplateNameLoc, diag::err_specialization_after_instantiation)
+ << Name << Range;
+
+ Diag(PrevDecl->getPointOfInstantiation(),
+ diag::note_instantiation_required_here)
+ << (PrevDecl->getTemplateSpecializationKind() !=
+ TSK_ImplicitInstantiation);
+ return true;
+ }
+ }
+
+ Specialization->setTemplateKeywordLoc(TemplateKWLoc);
+ Specialization->setLexicalDeclContext(CurContext);
+
+ // Add the specialization into its lexical context, so that it can
+ // be seen when iterating through the list of declarations in that
+ // context. However, specializations are not found by name lookup.
+ CurContext->addDecl(Specialization);
+
+ // Note that this is an explicit specialization.
+ Specialization->setSpecializationKind(TSK_ExplicitSpecialization);
+
+ if (PrevDecl) {
+ // Check that this isn't a redefinition of this specialization,
+ // merging with previous declarations.
+ LookupResult PrevSpec(*this, GetNameForDeclarator(D), LookupOrdinaryName,
+ ForRedeclaration);
+ PrevSpec.addDecl(PrevDecl);
+ D.setRedeclaration(CheckVariableDeclaration(Specialization, PrevSpec));
+ } else if (Specialization->isStaticDataMember() &&
+ Specialization->isOutOfLine()) {
+ Specialization->setAccess(VarTemplate->getAccess());
+ }
+
+ // Link instantiations of static data members back to the template from
+ // which they were instantiated.
+ if (Specialization->isStaticDataMember())
+ Specialization->setInstantiationOfStaticDataMember(
+ VarTemplate->getTemplatedDecl(),
+ Specialization->getSpecializationKind());
+
+ return Specialization;
+}
+
+namespace {
+/// \brief A partial specialization whose template arguments have matched
+/// a given template-id.
+struct PartialSpecMatchResult {
+ VarTemplatePartialSpecializationDecl *Partial;
+ TemplateArgumentList *Args;
+};
+}
+
+DeclResult
+Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
+ SourceLocation TemplateNameLoc,
+ const TemplateArgumentListInfo &TemplateArgs) {
+ assert(Template && "A variable template id without template?");
+
+ // Check that the template argument list is well-formed for this template.
+ SmallVector<TemplateArgument, 4> Converted;
+ bool ExpansionIntoFixedList = false;
+ if (CheckTemplateArgumentList(
+ Template, TemplateNameLoc,
+ const_cast<TemplateArgumentListInfo &>(TemplateArgs), false,
+ Converted, &ExpansionIntoFixedList))
+ return true;
+
+ // Find the variable template specialization declaration that
+ // corresponds to these arguments.
+ void *InsertPos = 0;
+ if (VarTemplateSpecializationDecl *Spec = Template->findSpecialization(
+ Converted.data(), Converted.size(), InsertPos))
+ // If we already have a variable template specialization, return it.
+ return Spec;
+
+ // This is the first time we have referenced this variable template
+ // specialization. Create the canonical declaration and add it to
+ // the set of specializations, based on the closest partial specialization
+ // that it represents. That is,
+ VarDecl *InstantiationPattern = Template->getTemplatedDecl();
+ TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack,
+ Converted.data(), Converted.size());
+ TemplateArgumentList *InstantiationArgs = &TemplateArgList;
+ bool AmbiguousPartialSpec = false;
+ typedef PartialSpecMatchResult MatchResult;
+ SmallVector<MatchResult, 4> Matched;
+ SourceLocation PointOfInstantiation = TemplateNameLoc;
+ TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
+
+ // 1. Attempt to find the closest partial specialization that this
+ // specializes, if any.
+ // If any of the template arguments is dependent, then this is probably
+ // a placeholder for an incomplete declarative context; which must be
+ // complete by instantiation time. Thus, do not search through the partial
+ // specializations yet.
+ // TODO: Unify with InstantiateClassTemplateSpecialization()?
+ // Perhaps better after unification of DeduceTemplateArguments() and
+ // getMoreSpecializedPartialSpecialization().
+ bool InstantiationDependent = false;
+ if (!TemplateSpecializationType::anyDependentTemplateArguments(
+ TemplateArgs, InstantiationDependent)) {
+
+ SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+ Template->getPartialSpecializations(PartialSpecs);
+
+ for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
+ VarTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
+ TemplateDeductionInfo Info(FailedCandidates.getLocation());
+
+ if (TemplateDeductionResult Result =
+ DeduceTemplateArguments(Partial, TemplateArgList, Info)) {
+ // Store the failed-deduction information for use in diagnostics, later.
+ // TODO: Actually use the failed-deduction info?
+ FailedCandidates.addCandidate()
+ .set(Partial, MakeDeductionFailureInfo(Context, Result, Info));
+ (void)Result;
+ } else {
+ Matched.push_back(PartialSpecMatchResult());
+ Matched.back().Partial = Partial;
+ Matched.back().Args = Info.take();
+ }
+ }
+
+ // If we're dealing with a member template where the template parameters
+ // have been instantiated, this provides the original template parameters
+ // from which the member template's parameters were instantiated.
+ SmallVector<const NamedDecl *, 4> InstantiatedTemplateParameters;
+
+ if (Matched.size() >= 1) {
+ SmallVector<MatchResult, 4>::iterator Best = Matched.begin();
+ if (Matched.size() == 1) {
+ // -- If exactly one matching specialization is found, the
+ // instantiation is generated from that specialization.
+ // We don't need to do anything for this.
+ } else {
+ // -- If more than one matching specialization is found, the
+ // partial order rules (14.5.4.2) are used to determine
+ // whether one of the specializations is more specialized
+ // than the others. If none of the specializations is more
+ // specialized than all of the other matching
+ // specializations, then the use of the variable template is
+ // ambiguous and the program is ill-formed.
+ for (SmallVector<MatchResult, 4>::iterator P = Best + 1,
+ PEnd = Matched.end();
+ P != PEnd; ++P) {
+ if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
+ PointOfInstantiation) ==
+ P->Partial)
+ Best = P;
+ }
+
+ // Determine if the best partial specialization is more specialized than
+ // the others.
+ for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
+ PEnd = Matched.end();
+ P != PEnd; ++P) {
+ if (P != Best && getMoreSpecializedPartialSpecialization(
+ P->Partial, Best->Partial,
+ PointOfInstantiation) != Best->Partial) {
+ AmbiguousPartialSpec = true;
+ break;
+ }
+ }
+ }
+
+ // Instantiate using the best variable template partial specialization.
+ InstantiationPattern = Best->Partial;
+ InstantiationArgs = Best->Args;
+ } else {
+ // -- If no match is found, the instantiation is generated
+ // from the primary template.
+ // InstantiationPattern = Template->getTemplatedDecl();
+ }
+ }
+
+ // 2. Create the canonical declaration.
+ // Note that we do not instantiate the variable just yet, since
+ // instantiation is handled in DoMarkVarDeclReferenced().
+ // FIXME: LateAttrs et al.?
+ VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation(
+ Template, InstantiationPattern, *InstantiationArgs, TemplateArgs,
+ Converted, TemplateNameLoc, InsertPos /*, LateAttrs, StartingScope*/);
+ if (!Decl)
+ return true;
+
+ if (AmbiguousPartialSpec) {
+ // Partial ordering did not produce a clear winner. Complain.
+ Decl->setInvalidDecl();
+ Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous)
+ << Decl;
+
+ // Print the matching partial specializations.
+ for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
+ PEnd = Matched.end();
+ P != PEnd; ++P)
+ Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
+ << getTemplateArgumentBindingsText(
+ P->Partial->getTemplateParameters(), *P->Args);
+ return true;
+ }
+
+ if (VarTemplatePartialSpecializationDecl *D =
+ dyn_cast<VarTemplatePartialSpecializationDecl>(InstantiationPattern))
+ Decl->setInstantiationOf(D, InstantiationArgs);
+
+ assert(Decl && "No variable template specialization?");
+ return Decl;
+}
+
+ExprResult
+Sema::CheckVarTemplateId(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ VarTemplateDecl *Template, SourceLocation TemplateLoc,
+ const TemplateArgumentListInfo *TemplateArgs) {
+
+ DeclResult Decl = CheckVarTemplateId(Template, TemplateLoc, NameInfo.getLoc(),
+ *TemplateArgs);
+ if (Decl.isInvalid())
+ return ExprError();
+
+ VarDecl *Var = cast<VarDecl>(Decl.get());
+ if (!Var->getTemplateSpecializationKind())
+ Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation,
+ NameInfo.getLoc());
+
+ // Build an ordinary singleton decl ref.
+ return BuildDeclarationNameExpr(SS, NameInfo, Var,
+ /*FoundD=*/0, TemplateArgs);
+}
+
ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
@@ -2291,6 +2778,13 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
assert(!R.empty() && "empty lookup results when building templateid");
assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");
+ // In C++1y, check variable template ids.
+ if (R.getAsSingle<VarTemplateDecl>()) {
+ return Owned(CheckVarTemplateId(SS, R.getLookupNameInfo(),
+ R.getAsSingle<VarTemplateDecl>(),
+ TemplateKWLoc, TemplateArgs));
+ }
+
// We don't want lookup warnings at this point.
R.suppressDiagnostics();
@@ -2311,6 +2805,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
+
assert(TemplateArgs || TemplateKWLoc.isValid());
DeclContext *DC;
if (!(DC = computeDeclContext(SS, false)) ||
@@ -2564,22 +3059,25 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
// If the argument type is dependent, instantiate it now based
// on the previously-computed template arguments.
if (ArgType->getType()->isDependentType()) {
- TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
- Converted.data(), Converted.size());
-
- MultiLevelTemplateArgumentList AllTemplateArgs
- = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
-
Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
Template, Converted,
SourceRange(TemplateLoc, RAngleLoc));
- if (Inst)
+ if (Inst.isInvalid())
return 0;
+ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+ Converted.data(), Converted.size());
+
+ // Only substitute for the innermost template argument list.
+ MultiLevelTemplateArgumentList TemplateArgLists;
+ TemplateArgLists.addOuterTemplateArguments(&TemplateArgs);
+ for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
+ TemplateArgLists.addOuterTemplateArguments(None);
+
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
- ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs,
- Param->getDefaultArgumentLoc(),
- Param->getDeclName());
+ ArgType =
+ SemaRef.SubstType(ArgType, TemplateArgLists,
+ Param->getDefaultArgumentLoc(), Param->getDeclName());
}
return ArgType;
@@ -2614,21 +3112,24 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
SourceLocation RAngleLoc,
NonTypeTemplateParmDecl *Param,
SmallVectorImpl<TemplateArgument> &Converted) {
- TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
- Converted.data(), Converted.size());
-
- MultiLevelTemplateArgumentList AllTemplateArgs
- = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
-
Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
Template, Converted,
SourceRange(TemplateLoc, RAngleLoc));
- if (Inst)
+ if (Inst.isInvalid())
return ExprError();
+ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+ Converted.data(), Converted.size());
+
+ // Only substitute for the innermost template argument list.
+ MultiLevelTemplateArgumentList TemplateArgLists;
+ TemplateArgLists.addOuterTemplateArguments(&TemplateArgs);
+ for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
+ TemplateArgLists.addOuterTemplateArguments(None);
+
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
- return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs);
+ return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists);
}
/// \brief Substitute template arguments into the default template argument for
@@ -2664,32 +3165,35 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
TemplateTemplateParmDecl *Param,
SmallVectorImpl<TemplateArgument> &Converted,
NestedNameSpecifierLoc &QualifierLoc) {
+ Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Template, Converted,
+ SourceRange(TemplateLoc, RAngleLoc));
+ if (Inst.isInvalid())
+ return TemplateName();
+
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
Converted.data(), Converted.size());
- MultiLevelTemplateArgumentList AllTemplateArgs
- = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
-
- Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
- Template, Converted,
- SourceRange(TemplateLoc, RAngleLoc));
- if (Inst)
- return TemplateName();
+ // Only substitute for the innermost template argument list.
+ MultiLevelTemplateArgumentList TemplateArgLists;
+ TemplateArgLists.addOuterTemplateArguments(&TemplateArgs);
+ for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
+ TemplateArgLists.addOuterTemplateArguments(None);
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
- // Substitute into the nested-name-specifier first,
+ // Substitute into the nested-name-specifier first,
QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc();
if (QualifierLoc) {
- QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
- AllTemplateArgs);
+ QualifierLoc =
+ SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgLists);
if (!QualifierLoc)
return TemplateName();
}
-
- return SemaRef.SubstTemplateName(QualifierLoc,
- Param->getDefaultArgument().getArgument().getAsTemplate(),
- Param->getDefaultArgument().getTemplateNameLoc(),
- AllTemplateArgs);
+
+ return SemaRef.SubstTemplateName(
+ QualifierLoc,
+ Param->getDefaultArgument().getArgument().getAsTemplate(),
+ Param->getDefaultArgument().getTemplateNameLoc(),
+ TemplateArgLists);
}
/// \brief If the given template parameter has a default template
@@ -2700,11 +3204,16 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
Decl *Param,
- SmallVectorImpl<TemplateArgument> &Converted) {
- if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) {
+ SmallVectorImpl<TemplateArgument>
+ &Converted,
+ bool &HasDefaultArg) {
+ HasDefaultArg = false;
+
+ if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) {
if (!TypeParm->hasDefaultArgument())
return TemplateArgumentLoc();
+ HasDefaultArg = true;
TypeSourceInfo *DI = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
RAngleLoc,
@@ -2721,6 +3230,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
if (!NonTypeParm->hasDefaultArgument())
return TemplateArgumentLoc();
+ HasDefaultArg = true;
ExprResult Arg = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
RAngleLoc,
@@ -2738,7 +3248,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
if (!TempTempParm->hasDefaultArgument())
return TemplateArgumentLoc();
-
+ HasDefaultArg = true;
NestedNameSpecifierLoc QualifierLoc;
TemplateName TName = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
@@ -2808,7 +3318,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
InstantiatingTemplate Inst(*this, TemplateLoc, Template,
NTTP, Converted,
SourceRange(TemplateLoc, RAngleLoc));
- if (Inst)
+ if (Inst.isInvalid())
return true;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
@@ -2943,7 +3453,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
InstantiatingTemplate Inst(*this, TemplateLoc, Template,
TempParm, Converted,
SourceRange(TemplateLoc, RAngleLoc));
- if (Inst)
+ if (Inst.isInvalid())
return true;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
@@ -3110,8 +3620,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// deduced argument and place it on the argument pack. Note that we
// stay on the same template parameter so that we can deduce more
// arguments.
- ArgumentPack.push_back(Converted.back());
- Converted.pop_back();
+ ArgumentPack.push_back(Converted.pop_back_val());
} else {
// Move to the next template parameter.
++Param;
@@ -3255,10 +3764,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// Introduce an instantiation record that describes where we are using
// the default template argument.
- InstantiatingTemplate Instantiating(*this, RAngleLoc, Template,
- *Param, Converted,
- SourceRange(TemplateLoc, RAngleLoc));
- if (Instantiating)
+ InstantiatingTemplate Inst(*this, RAngleLoc, Template, *Param, Converted,
+ SourceRange(TemplateLoc, RAngleLoc));
+ if (Inst.isInvalid())
return true;
// Check the default template argument.
@@ -3655,6 +4163,63 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
return NPV_NotNullPointer;
}
+/// \brief Checks whether the given template argument is compatible with its
+/// template parameter.
+static bool CheckTemplateArgumentIsCompatibleWithParameter(
+ Sema &S, NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *ArgIn,
+ Expr *Arg, QualType ArgType) {
+ bool ObjCLifetimeConversion;
+ if (ParamType->isPointerType() &&
+ !ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType() &&
+ S.IsQualificationConversion(ArgType, ParamType, false,
+ ObjCLifetimeConversion)) {
+ // For pointer-to-object types, qualification conversions are
+ // permitted.
+ } else {
+ if (const ReferenceType *ParamRef = ParamType->getAs<ReferenceType>()) {
+ if (!ParamRef->getPointeeType()->isFunctionType()) {
+ // C++ [temp.arg.nontype]p5b3:
+ // For a non-type template-parameter of type reference to
+ // object, no conversions apply. The type referred to by the
+ // reference may be more cv-qualified than the (otherwise
+ // identical) type of the template- argument. The
+ // template-parameter is bound directly to the
+ // template-argument, which shall be an lvalue.
+
+ // FIXME: Other qualifiers?
+ unsigned ParamQuals = ParamRef->getPointeeType().getCVRQualifiers();
+ unsigned ArgQuals = ArgType.getCVRQualifiers();
+
+ if ((ParamQuals | ArgQuals) != ParamQuals) {
+ S.Diag(Arg->getLocStart(),
+ diag::err_template_arg_ref_bind_ignores_quals)
+ << ParamType << Arg->getType() << Arg->getSourceRange();
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+ }
+ }
+
+ // At this point, the template argument refers to an object or
+ // function with external linkage. We now need to check whether the
+ // argument and parameter types are compatible.
+ if (!S.Context.hasSameUnqualifiedType(ArgType,
+ ParamType.getNonReferenceType())) {
+ // We can't perform this conversion or binding.
+ if (ParamType->isReferenceType())
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_no_ref_bind)
+ << ParamType << ArgIn->getType() << Arg->getSourceRange();
+ else
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible)
+ << ArgIn->getType() << ParamType << Arg->getSourceRange();
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+ }
+
+ return false;
+}
+
/// \brief Checks whether the given template argument is the address
/// of an object or function according to C++ [temp.arg.nontype]p1.
static bool
@@ -3682,68 +4247,110 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
break;
}
}
-
- // See through any implicit casts we added to fix the type.
- Arg = Arg->IgnoreImpCasts();
- // C++ [temp.arg.nontype]p1:
- //
- // A template-argument for a non-type, non-template
- // template-parameter shall be one of: [...]
- //
- // -- the address of an object or function with external
- // linkage, including function templates and function
- // template-ids but excluding non-static class members,
- // expressed as & id-expression where the & is optional if
- // the name refers to a function or array, or if the
- // corresponding template-parameter is a reference; or
-
- // In C++98/03 mode, give an extension warning on any extra parentheses.
- // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
- bool ExtraParens = false;
- while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
- if (!Invalid && !ExtraParens) {
- S.Diag(Arg->getLocStart(),
- S.getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_template_arg_extra_parens :
- diag::ext_template_arg_extra_parens)
- << Arg->getSourceRange();
- ExtraParens = true;
+ bool AddressTaken = false;
+ SourceLocation AddrOpLoc;
+ if (S.getLangOpts().MicrosoftExt) {
+ // Microsoft Visual C++ strips all casts, allows an arbitrary number of
+ // dereference and address-of operators.
+ Arg = Arg->IgnoreParenCasts();
+
+ bool ExtWarnMSTemplateArg = false;
+ UnaryOperatorKind FirstOpKind;
+ SourceLocation FirstOpLoc;
+ while (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
+ UnaryOperatorKind UnOpKind = UnOp->getOpcode();
+ if (UnOpKind == UO_Deref)
+ ExtWarnMSTemplateArg = true;
+ if (UnOpKind == UO_AddrOf || UnOpKind == UO_Deref) {
+ Arg = UnOp->getSubExpr()->IgnoreParenCasts();
+ if (!AddrOpLoc.isValid()) {
+ FirstOpKind = UnOpKind;
+ FirstOpLoc = UnOp->getOperatorLoc();
+ }
+ } else
+ break;
+ }
+ if (FirstOpLoc.isValid()) {
+ if (ExtWarnMSTemplateArg)
+ S.Diag(ArgIn->getLocStart(), diag::ext_ms_deref_template_argument)
+ << ArgIn->getSourceRange();
+
+ if (FirstOpKind == UO_AddrOf)
+ AddressTaken = true;
+ else if (Arg->getType()->isPointerType()) {
+ // We cannot let pointers get dereferenced here, that is obviously not a
+ // constant expression.
+ assert(FirstOpKind == UO_Deref);
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
+ << Arg->getSourceRange();
+ }
}
+ } else {
+ // See through any implicit casts we added to fix the type.
+ Arg = Arg->IgnoreImpCasts();
- Arg = Parens->getSubExpr();
- }
+ // C++ [temp.arg.nontype]p1:
+ //
+ // A template-argument for a non-type, non-template
+ // template-parameter shall be one of: [...]
+ //
+ // -- the address of an object or function with external
+ // linkage, including function templates and function
+ // template-ids but excluding non-static class members,
+ // expressed as & id-expression where the & is optional if
+ // the name refers to a function or array, or if the
+ // corresponding template-parameter is a reference; or
+
+ // In C++98/03 mode, give an extension warning on any extra parentheses.
+ // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
+ bool ExtraParens = false;
+ while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
+ if (!Invalid && !ExtraParens) {
+ S.Diag(Arg->getLocStart(),
+ S.getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_template_arg_extra_parens
+ : diag::ext_template_arg_extra_parens)
+ << Arg->getSourceRange();
+ ExtraParens = true;
+ }
- while (SubstNonTypeTemplateParmExpr *subst =
- dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
- Arg = subst->getReplacement()->IgnoreImpCasts();
+ Arg = Parens->getSubExpr();
+ }
- bool AddressTaken = false;
- SourceLocation AddrOpLoc;
- if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
- if (UnOp->getOpcode() == UO_AddrOf) {
- Arg = UnOp->getSubExpr();
- AddressTaken = true;
- AddrOpLoc = UnOp->getOperatorLoc();
+ while (SubstNonTypeTemplateParmExpr *subst =
+ dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
+ Arg = subst->getReplacement()->IgnoreImpCasts();
+
+ if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
+ if (UnOp->getOpcode() == UO_AddrOf) {
+ Arg = UnOp->getSubExpr();
+ AddressTaken = true;
+ AddrOpLoc = UnOp->getOperatorLoc();
+ }
}
+
+ while (SubstNonTypeTemplateParmExpr *subst =
+ dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
+ Arg = subst->getReplacement()->IgnoreImpCasts();
}
- if (S.getLangOpts().MicrosoftExt && isa<CXXUuidofExpr>(Arg)) {
+ // Stop checking the precise nature of the argument if it is value dependent,
+ // it should be checked when instantiated.
+ if (Arg->isValueDependent()) {
Converted = TemplateArgument(ArgIn);
return false;
}
- while (SubstNonTypeTemplateParmExpr *subst =
- dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
- Arg = subst->getReplacement()->IgnoreImpCasts();
+ if (isa<CXXUuidofExpr>(Arg)) {
+ if (CheckTemplateArgumentIsCompatibleWithParameter(S, Param, ParamType,
+ ArgIn, Arg, ArgType))
+ return true;
- // Stop checking the precise nature of the argument if it is value dependent,
- // it should be checked when instantiated.
- if (Arg->isValueDependent()) {
Converted = TemplateArgument(ArgIn);
return false;
}
-
+
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg);
if (!DRE) {
S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
@@ -3752,20 +4359,12 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
return true;
}
- if (!isa<ValueDecl>(DRE->getDecl())) {
- S.Diag(Arg->getLocStart(),
- diag::err_template_arg_not_object_or_func_form)
- << Arg->getSourceRange();
- S.Diag(Param->getLocation(), diag::note_template_param_here);
- return true;
- }
-
ValueDecl *Entity = DRE->getDecl();
// Cannot refer to non-static data members
- if (FieldDecl *Field = dyn_cast<FieldDecl>(Entity)) {
+ if (isa<FieldDecl>(Entity) || isa<IndirectFieldDecl>(Entity)) {
S.Diag(Arg->getLocStart(), diag::err_template_arg_field)
- << Field << Arg->getSourceRange();
+ << Entity << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
@@ -3793,14 +4392,14 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
}
// Address / reference template args must have external linkage in C++98.
- if (Entity->getLinkage() == InternalLinkage) {
+ if (Entity->getFormalLinkage() == InternalLinkage) {
S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_arg_object_internal :
diag::ext_template_arg_object_internal)
<< !Func << Entity << Arg->getSourceRange();
S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
<< !Func;
- } else if (Entity->getLinkage() == NoLinkage) {
+ } else if (!Entity->hasLinkage()) {
S.Diag(Arg->getLocStart(), diag::err_template_arg_object_no_linkage)
<< !Func << Entity << Arg->getSourceRange();
S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
@@ -3896,55 +4495,9 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
}
}
- bool ObjCLifetimeConversion;
- if (ParamType->isPointerType() &&
- !ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType() &&
- S.IsQualificationConversion(ArgType, ParamType, false,
- ObjCLifetimeConversion)) {
- // For pointer-to-object types, qualification conversions are
- // permitted.
- } else {
- if (const ReferenceType *ParamRef = ParamType->getAs<ReferenceType>()) {
- if (!ParamRef->getPointeeType()->isFunctionType()) {
- // C++ [temp.arg.nontype]p5b3:
- // For a non-type template-parameter of type reference to
- // object, no conversions apply. The type referred to by the
- // reference may be more cv-qualified than the (otherwise
- // identical) type of the template- argument. The
- // template-parameter is bound directly to the
- // template-argument, which shall be an lvalue.
-
- // FIXME: Other qualifiers?
- unsigned ParamQuals = ParamRef->getPointeeType().getCVRQualifiers();
- unsigned ArgQuals = ArgType.getCVRQualifiers();
-
- if ((ParamQuals | ArgQuals) != ParamQuals) {
- S.Diag(Arg->getLocStart(),
- diag::err_template_arg_ref_bind_ignores_quals)
- << ParamType << Arg->getType()
- << Arg->getSourceRange();
- S.Diag(Param->getLocation(), diag::note_template_param_here);
- return true;
- }
- }
- }
-
- // At this point, the template argument refers to an object or
- // function with external linkage. We now need to check whether the
- // argument and parameter types are compatible.
- if (!S.Context.hasSameUnqualifiedType(ArgType,
- ParamType.getNonReferenceType())) {
- // We can't perform this conversion or binding.
- if (ParamType->isReferenceType())
- S.Diag(Arg->getLocStart(), diag::err_template_arg_no_ref_bind)
- << ParamType << ArgIn->getType() << Arg->getSourceRange();
- else
- S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible)
- << ArgIn->getType() << ParamType << Arg->getSourceRange();
- S.Diag(Param->getLocation(), diag::note_template_param_here);
- return true;
- }
- }
+ if (CheckTemplateArgumentIsCompatibleWithParameter(S, Param, ParamType, ArgIn,
+ Arg, ArgType))
+ return true;
// Create the template argument.
Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
@@ -4035,9 +4588,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) {
if (ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) {
if (VD->getType()->isMemberPointerType()) {
- if (isa<NonTypeTemplateParmDecl>(VD) ||
- (isa<VarDecl>(VD) &&
- S.Context.getCanonicalType(VD->getType()).isConstQualified())) {
+ if (isa<NonTypeTemplateParmDecl>(VD)) {
if (Arg->isTypeDependent() || Arg->isValueDependent()) {
Converted = TemplateArgument(Arg);
} else {
@@ -4057,8 +4608,11 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
diag::err_template_arg_not_pointer_to_member_form)
<< Arg->getSourceRange();
- if (isa<FieldDecl>(DRE->getDecl()) || isa<CXXMethodDecl>(DRE->getDecl())) {
+ if (isa<FieldDecl>(DRE->getDecl()) ||
+ isa<IndirectFieldDecl>(DRE->getDecl()) ||
+ isa<CXXMethodDecl>(DRE->getDecl())) {
assert((isa<FieldDecl>(DRE->getDecl()) ||
+ isa<IndirectFieldDecl>(DRE->getDecl()) ||
!cast<CXXMethodDecl>(DRE->getDecl())->isStatic()) &&
"Only non-static member pointers can make it here");
@@ -4520,7 +5074,8 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
if (VD->getDeclContext()->isRecord() &&
- (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD))) {
+ (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD) ||
+ isa<IndirectFieldDecl>(VD))) {
// If the value is a class member, we might have a pointer-to-member.
// Determine whether the non-type template template parameter is of
// pointer-to-member type. If so, we need to build an appropriate
@@ -4898,7 +5453,7 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
// C++ [temp]p2:
// A template-declaration can appear only as a namespace scope or
// class scope declaration.
- DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
+ DeclContext *Ctx = S->getEntity();
if (Ctx && isa<LinkageSpecDecl>(Ctx) &&
cast<LinkageSpecDecl>(Ctx)->getLanguage() != LinkageSpecDecl::lang_cxx)
return Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage)
@@ -4907,8 +5462,20 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
while (Ctx && isa<LinkageSpecDecl>(Ctx))
Ctx = Ctx->getParent();
- if (Ctx && (Ctx->isFileContext() || Ctx->isRecord()))
- return false;
+ if (Ctx) {
+ if (Ctx->isFileContext())
+ return false;
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Ctx)) {
+ // C++ [temp.mem]p2:
+ // A local class shall not have member templates.
+ if (RD->isLocalClass())
+ return Diag(TemplateParams->getTemplateLoc(),
+ diag::err_template_inside_local_class)
+ << TemplateParams->getSourceRange();
+ else
+ return false;
+ }
+ }
return Diag(TemplateParams->getTemplateLoc(),
diag::err_template_outside_namespace_or_class_scope)
@@ -4965,16 +5532,18 @@ static bool CheckTemplateSpecializationScope(Sema &S,
int EntityKind = 0;
if (isa<ClassTemplateDecl>(Specialized))
EntityKind = IsPartialSpecialization? 1 : 0;
+ else if (isa<VarTemplateDecl>(Specialized))
+ EntityKind = IsPartialSpecialization ? 3 : 2;
else if (isa<FunctionTemplateDecl>(Specialized))
- EntityKind = 2;
+ EntityKind = 4;
else if (isa<CXXMethodDecl>(Specialized))
- EntityKind = 3;
+ EntityKind = 5;
else if (isa<VarDecl>(Specialized))
- EntityKind = 4;
+ EntityKind = 6;
else if (isa<RecordDecl>(Specialized))
- EntityKind = 5;
+ EntityKind = 7;
else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus11)
- EntityKind = 6;
+ EntityKind = 8;
else {
S.Diag(Loc, diag::err_template_spec_unknown_kind)
<< S.getLangOpts().CPlusPlus11;
@@ -5098,17 +5667,15 @@ static bool CheckTemplateSpecializationScope(Sema &S,
return false;
}
-/// \brief Subroutine of Sema::CheckClassTemplatePartialSpecializationArgs
+/// \brief Subroutine of Sema::CheckTemplatePartialSpecializationArgs
/// that checks non-type template partial specialization arguments.
-static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S,
- NonTypeTemplateParmDecl *Param,
- const TemplateArgument *Args,
- unsigned NumArgs) {
+static bool CheckNonTypeTemplatePartialSpecializationArgs(
+ Sema &S, NonTypeTemplateParmDecl *Param, const TemplateArgument *Args,
+ unsigned NumArgs) {
for (unsigned I = 0; I != NumArgs; ++I) {
if (Args[I].getKind() == TemplateArgument::Pack) {
- if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param,
- Args[I].pack_begin(),
- Args[I].pack_size()))
+ if (CheckNonTypeTemplatePartialSpecializationArgs(
+ S, Param, Args[I].pack_begin(), Args[I].pack_size()))
return true;
continue;
@@ -5179,9 +5746,9 @@ static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S,
/// partial specialization.
///
/// \returns true if there was an error, false otherwise.
-static bool CheckClassTemplatePartialSpecializationArgs(Sema &S,
- TemplateParameterList *TemplateParams,
- SmallVectorImpl<TemplateArgument> &TemplateArgs) {
+static bool CheckTemplatePartialSpecializationArgs(
+ Sema &S, TemplateParameterList *TemplateParams,
+ SmallVectorImpl<TemplateArgument> &TemplateArgs) {
const TemplateArgument *ArgList = TemplateArgs.data();
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
@@ -5190,8 +5757,7 @@ static bool CheckClassTemplatePartialSpecializationArgs(Sema &S,
if (!Param)
continue;
- if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param,
- &ArgList[I], 1))
+ if (CheckNonTypeTemplatePartialSpecializationArgs(S, Param, &ArgList[I], 1))
return true;
}
@@ -5219,7 +5785,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
? TemplateParameterLists[0]->getTemplateLoc() : SourceLocation();
// Find the class template we're specializing
- TemplateName Name = TemplateD.getAsVal<TemplateName>();
+ TemplateName Name = TemplateD.get();
ClassTemplateDecl *ClassTemplate
= dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl());
@@ -5238,15 +5804,10 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// FIXME: We probably shouldn't complain about these headers for
// friend declarations.
bool Invalid = false;
- TemplateParameterList *TemplateParams
- = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc,
- TemplateNameLoc,
- SS,
- TemplateParameterLists.data(),
- TemplateParameterLists.size(),
- TUK == TUK_Friend,
- isExplicitSpecialization,
- Invalid);
+ TemplateParameterList *TemplateParams =
+ MatchTemplateParametersToScopeSpecifier(
+ TemplateNameLoc, TemplateNameLoc, SS, TemplateParameterLists,
+ TUK == TUK_Friend, isExplicitSpecialization, Invalid);
if (Invalid)
return true;
@@ -5300,6 +5861,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
} else if (TUK != TUK_Friend) {
Diag(KWLoc, diag::err_template_spec_needs_header)
<< FixItHint::CreateInsertion(KWLoc, "template<> ");
+ TemplateKWLoc = KWLoc;
isExplicitSpecialization = true;
}
@@ -5341,9 +5903,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Find the class template (partial) specialization declaration that
// corresponds to these arguments.
if (isPartialSpecialization) {
- if (CheckClassTemplatePartialSpecializationArgs(*this,
- ClassTemplate->getTemplateParameters(),
- Converted))
+ if (CheckTemplatePartialSpecializationArgs(
+ *this, ClassTemplate->getTemplateParameters(), Converted))
return true;
bool InstantiationDependent;
@@ -5416,7 +5977,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// -- The argument list of the specialization shall not be identical
// to the implicit argument list of the primary template.
Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
- << (TUK == TUK_Definition)
+ << /*class template*/0 << (TUK == TUK_Definition)
<< FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS,
ClassTemplate->getIdentifier(),
@@ -5431,8 +5992,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Create a new class template partial specialization declaration node.
ClassTemplatePartialSpecializationDecl *PrevPartial
= cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
- unsigned SequenceNumber = PrevPartial? PrevPartial->getSequenceNumber()
- : ClassTemplate->getNextPartialSpecSequenceNumber();
ClassTemplatePartialSpecializationDecl *Partial
= ClassTemplatePartialSpecializationDecl::Create(Context, Kind,
ClassTemplate->getDeclContext(),
@@ -5443,8 +6002,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Converted.size(),
TemplateArgs,
CanonType,
- PrevPartial,
- SequenceNumber);
+ PrevPartial);
SetNestedNameSpecifier(Partial, SS);
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
Partial->setTemplateParameterListsInfo(Context,
@@ -5473,7 +6031,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
if (!DeducibleParams.all()) {
unsigned NumNonDeducible = DeducibleParams.size()-DeducibleParams.count();
Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible)
- << (NumNonDeducible > 1)
+ << /*class template*/0 << (NumNonDeducible > 1)
<< SourceRange(TemplateNameLoc, RAngleLoc);
for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
if (!DeducibleParams[I]) {
@@ -5710,7 +6268,10 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
switch (NewTSK) {
case TSK_Undeclared:
case TSK_ImplicitInstantiation:
- llvm_unreachable("Don't check implicit instantiations here");
+ assert(
+ (PrevTSK == TSK_Undeclared || PrevTSK == TSK_ImplicitInstantiation) &&
+ "previous declaration must be implicit!");
+ return false;
case TSK_ExplicitSpecialization:
switch (PrevTSK) {
@@ -5916,13 +6477,13 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
///
/// \param Previous the set of declarations that may be specialized by
/// this function specialization.
-bool
-Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- LookupResult &Previous) {
+bool Sema::CheckFunctionTemplateSpecialization(
+ FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
+ LookupResult &Previous) {
// The set of function template specializations that could match this
// explicit function template specialization.
UnresolvedSet<8> Candidates;
+ TemplateSpecCandidateSet FailedCandidates(FD->getLocation());
DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
@@ -5948,9 +6509,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals |= Qualifiers::Const;
- FT = Context.getFunctionType(FPT->getResultType(),
- ArrayRef<QualType>(FPT->arg_type_begin(),
- FPT->getNumArgs()),
+ FT = Context.getFunctionType(FPT->getResultType(), FPT->getArgTypes(),
EPI);
}
}
@@ -5962,13 +6521,16 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
// Perform template argument deduction to determine whether we may be
// specializing this template.
// FIXME: It is somewhat wasteful to build
- TemplateDeductionInfo Info(FD->getLocation());
+ TemplateDeductionInfo Info(FailedCandidates.getLocation());
FunctionDecl *Specialization = 0;
- if (TemplateDeductionResult TDK
- = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, FT,
- Specialization, Info)) {
- // FIXME: Template argument deduction failed; record why it failed, so
+ if (TemplateDeductionResult TDK = DeduceTemplateArguments(
+ cast<FunctionTemplateDecl>(FunTmpl->getFirstDecl()),
+ ExplicitTemplateArgs, FT, Specialization, Info)) {
+ // Template argument deduction failed; record why it failed, so
// that we can provide nifty diagnostics.
+ FailedCandidates.addCandidate()
+ .set(FunTmpl->getTemplatedDecl(),
+ MakeDeductionFailureInfo(Context, TDK, Info));
(void)TDK;
continue;
}
@@ -5979,14 +6541,14 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
}
// Find the most specialized function template.
- UnresolvedSetIterator Result
- = getMostSpecialized(Candidates.begin(), Candidates.end(),
- TPOC_Other, 0, FD->getLocation(),
- PDiag(diag::err_function_template_spec_no_match)
- << FD->getDeclName(),
- PDiag(diag::err_function_template_spec_ambiguous)
- << FD->getDeclName() << (ExplicitTemplateArgs != 0),
- PDiag(diag::note_function_template_spec_matched));
+ UnresolvedSetIterator Result = getMostSpecialized(
+ Candidates.begin(), Candidates.end(), FailedCandidates,
+ FD->getLocation(),
+ PDiag(diag::err_function_template_spec_no_match) << FD->getDeclName(),
+ PDiag(diag::err_function_template_spec_ambiguous)
+ << FD->getDeclName() << (ExplicitTemplateArgs != 0),
+ PDiag(diag::note_function_template_spec_matched));
+
if (Result == Candidates.end())
return true;
@@ -6213,9 +6775,8 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
InstantiationVar->setLocation(Member->getLocation());
}
- Context.setInstantiatedFromStaticDataMember(cast<VarDecl>(Member),
- cast<VarDecl>(InstantiatedFrom),
- TSK_ExplicitSpecialization);
+ cast<VarDecl>(Member)->setInstantiationOfStaticDataMember(
+ cast<VarDecl>(InstantiatedFrom), TSK_ExplicitSpecialization);
MarkUnusedFileScopedDecl(InstantiationVar);
} else if (isa<CXXRecordDecl>(Member)) {
CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation);
@@ -6340,15 +6901,23 @@ Sema::ActOnExplicitInstantiation(Scope *S,
SourceLocation RAngleLoc,
AttributeList *Attr) {
// Find the class template we're specializing
- TemplateName Name = TemplateD.getAsVal<TemplateName>();
- ClassTemplateDecl *ClassTemplate
- = cast<ClassTemplateDecl>(Name.getAsTemplateDecl());
-
+ TemplateName Name = TemplateD.get();
+ TemplateDecl *TD = Name.getAsTemplateDecl();
// Check that the specialization uses the same tag kind as the
// original template.
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
assert(Kind != TTK_Enum &&
"Invalid enum tag in class template explicit instantiation!");
+
+ if (isa<TypeAliasTemplateDecl>(TD)) {
+ Diag(KWLoc, diag::err_tag_reference_non_tag) << Kind;
+ Diag(TD->getTemplatedDecl()->getLocation(),
+ diag::note_previous_use);
+ return true;
+ }
+
+ ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(TD);
+
if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
Kind, /*isDefinition*/false, KWLoc,
*ClassTemplate->getIdentifier())) {
@@ -6695,7 +7264,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
diag::err_explicit_instantiation_inline :
diag::warn_explicit_instantiation_inline_0x)
<< FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
- if (D.getDeclSpec().isConstexprSpecified())
+ if (D.getDeclSpec().isConstexprSpecified() && R->isFunctionType())
// FIXME: Add a fix-it to remove the 'constexpr' and add a 'const' if one is
// not already specified.
Diag(D.getDeclSpec().getConstexprSpecLoc(),
@@ -6717,28 +7286,78 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// A [...] static data member of a class template can be explicitly
// instantiated from the member definition associated with its class
// template.
+ // C++1y [temp.explicit]p1:
+ // A [...] variable [...] template specialization can be explicitly
+ // instantiated from its template.
if (Previous.isAmbiguous())
return true;
VarDecl *Prev = Previous.getAsSingle<VarDecl>();
- if (!Prev || !Prev->isStaticDataMember()) {
- // We expect to see a data data member here.
- Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known)
- << Name;
- for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
- P != PEnd; ++P)
- Diag((*P)->getLocation(), diag::note_explicit_instantiation_here);
- return true;
- }
+ VarTemplateDecl *PrevTemplate = Previous.getAsSingle<VarTemplateDecl>();
+
+ if (!PrevTemplate) {
+ if (!Prev || !Prev->isStaticDataMember()) {
+ // We expect to see a data data member here.
+ Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known)
+ << Name;
+ for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
+ P != PEnd; ++P)
+ Diag((*P)->getLocation(), diag::note_explicit_instantiation_here);
+ return true;
+ }
- if (!Prev->getInstantiatedFromStaticDataMember()) {
- // FIXME: Check for explicit specialization?
- Diag(D.getIdentifierLoc(),
- diag::err_explicit_instantiation_data_member_not_instantiated)
- << Prev;
- Diag(Prev->getLocation(), diag::note_explicit_instantiation_here);
- // FIXME: Can we provide a note showing where this was declared?
- return true;
+ if (!Prev->getInstantiatedFromStaticDataMember()) {
+ // FIXME: Check for explicit specialization?
+ Diag(D.getIdentifierLoc(),
+ diag::err_explicit_instantiation_data_member_not_instantiated)
+ << Prev;
+ Diag(Prev->getLocation(), diag::note_explicit_instantiation_here);
+ // FIXME: Can we provide a note showing where this was declared?
+ return true;
+ }
+ } else {
+ // Explicitly instantiate a variable template.
+
+ // C++1y [dcl.spec.auto]p6:
+ // ... A program that uses auto or decltype(auto) in a context not
+ // explicitly allowed in this section is ill-formed.
+ //
+ // This includes auto-typed variable template instantiations.
+ if (R->isUndeducedType()) {
+ Diag(T->getTypeLoc().getLocStart(),
+ diag::err_auto_not_allowed_var_inst);
+ return true;
+ }
+
+ if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ // C++1y [temp.explicit]p3:
+ // If the explicit instantiation is for a variable, the unqualified-id
+ // in the declaration shall be a template-id.
+ Diag(D.getIdentifierLoc(),
+ diag::err_explicit_instantiation_without_template_id)
+ << PrevTemplate;
+ Diag(PrevTemplate->getLocation(),
+ diag::note_explicit_instantiation_here);
+ return true;
+ }
+
+ // Translate the parser's template argument list into our AST format.
+ TemplateArgumentListInfo TemplateArgs;
+ TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+ TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
+ TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
+ ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+ translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+
+ DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,
+ D.getIdentifierLoc(), TemplateArgs);
+ if (Res.isInvalid())
+ return true;
+
+ // Ignore access control bits, we don't need them for redeclaration
+ // checking.
+ Prev = cast<VarDecl>(Res.get());
}
// C++0x [temp.explicit]p2:
@@ -6748,7 +7367,10 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// name shall be a simple-template-id.
//
// C++98 has the same restriction, just worded differently.
- if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
+ //
+ // This does not apply to variable template specializations, where the
+ // template-id is in the unqualified-id instead.
+ if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()) && !PrevTemplate)
Diag(D.getIdentifierLoc(),
diag::ext_explicit_instantiation_without_qualified_id)
<< Prev << D.getCXXScopeSpec().getRange();
@@ -6757,21 +7379,35 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true);
// Verify that it is okay to explicitly instantiate here.
- MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo();
- assert(MSInfo && "Missing static data member specialization info?");
+ TemplateSpecializationKind PrevTSK = Prev->getTemplateSpecializationKind();
+ SourceLocation POI = Prev->getPointOfInstantiation();
bool HasNoEffect = false;
if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev,
- MSInfo->getTemplateSpecializationKind(),
- MSInfo->getPointOfInstantiation(),
- HasNoEffect))
+ PrevTSK, POI, HasNoEffect))
return true;
- if (HasNoEffect)
- return (Decl*) 0;
- // Instantiate static data member.
- Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
- if (TSK == TSK_ExplicitInstantiationDefinition)
- InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev);
+ if (!HasNoEffect) {
+ // Instantiate static data member or variable template.
+
+ Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+ if (PrevTemplate) {
+ // Merge attributes.
+ if (AttributeList *Attr = D.getDeclSpec().getAttributes().getList())
+ ProcessDeclAttributeList(S, Prev, Attr);
+ }
+ if (TSK == TSK_ExplicitInstantiationDefinition)
+ InstantiateVariableDefinition(D.getIdentifierLoc(), Prev);
+ }
+
+ // Check the new variable specialization against the parsed input.
+ if (PrevTemplate && Prev && !Context.hasSameType(Prev->getType(), R)) {
+ Diag(T->getTypeLoc().getLocStart(),
+ diag::err_invalid_var_template_spec_type)
+ << 0 << PrevTemplate << R << Prev->getType();
+ Diag(PrevTemplate->getLocation(), diag::note_template_declared_here)
+ << 2 << PrevTemplate->getDeclName();
+ return true;
+ }
// FIXME: Create an ExplicitInstantiation node?
return (Decl*) 0;
@@ -6797,12 +7433,14 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// instantiated from the member definition associated with its class
// template.
UnresolvedSet<8> Matches;
+ TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc());
for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
P != PEnd; ++P) {
NamedDecl *Prev = *P;
if (!HasExplicitTemplateArgs) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
- if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
+ QualType Adjusted = adjustCCAndNoReturn(R, Method->getType());
+ if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) {
Matches.clear();
Matches.addDecl(Method, P.getAccess());
@@ -6816,13 +7454,16 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
if (!FunTmpl)
continue;
- TemplateDeductionInfo Info(D.getIdentifierLoc());
+ TemplateDeductionInfo Info(FailedCandidates.getLocation());
FunctionDecl *Specialization = 0;
if (TemplateDeductionResult TDK
= DeduceTemplateArguments(FunTmpl,
(HasExplicitTemplateArgs ? &TemplateArgs : 0),
R, Specialization, Info)) {
- // FIXME: Keep track of almost-matches?
+ // Keep track of almost-matches.
+ FailedCandidates.addCandidate()
+ .set(FunTmpl->getTemplatedDecl(),
+ MakeDeductionFailureInfo(Context, TDK, Info));
(void)TDK;
continue;
}
@@ -6831,12 +7472,12 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
}
// Find the most specialized function template specialization.
- UnresolvedSetIterator Result
- = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, 0,
- D.getIdentifierLoc(),
- PDiag(diag::err_explicit_instantiation_not_known) << Name,
- PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
- PDiag(diag::note_explicit_instantiation_candidate));
+ UnresolvedSetIterator Result = getMostSpecialized(
+ Matches.begin(), Matches.end(), FailedCandidates,
+ D.getIdentifierLoc(),
+ PDiag(diag::err_explicit_instantiation_not_known) << Name,
+ PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
+ PDiag(diag::note_explicit_instantiation_candidate));
if (Result == Matches.end())
return true;
@@ -7373,11 +8014,26 @@ Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
return Out.str();
}
-void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag) {
+void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD,
+ CachedTokens &Toks) {
if (!FD)
return;
- FD->setLateTemplateParsed(Flag);
-}
+
+ LateParsedTemplate *LPT = new LateParsedTemplate;
+
+ // Take tokens to avoid allocations
+ LPT->Toks.swap(Toks);
+ LPT->D = FnD;
+ LateParsedTemplateMap[FD] = LPT;
+
+ FD->setLateTemplateParsed(true);
+}
+
+void Sema::UnmarkAsLateParsedTemplate(FunctionDecl *FD) {
+ if (!FD)
+ return;
+ FD->setLateTemplateParsed(false);
+}
bool Sema::IsInsideALocalClassWithinATemplateFunction() {
DeclContext *DC = CurContext;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
index 8efc7a026347..8d66ff68efa6 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -13,6 +13,7 @@
#include "clang/Sema/TemplateDeduction.h"
#include "TreeTransform.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
@@ -26,7 +27,6 @@
namespace clang {
using namespace sema;
-
/// \brief Various flags that control template argument deduction.
///
/// These flags can be bitwise-OR'd together.
@@ -89,7 +89,7 @@ DeduceTemplateArguments(Sema &S,
const TemplateArgument &Param,
TemplateArgument Arg,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced);
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced);
/// \brief Whether template argument deduction for two reference parameters
/// resulted in the argument type, parameter type, or neither type being more
@@ -375,10 +375,10 @@ DeduceNonTypeTemplateArgument(Sema &S,
/// \returns true if deduction succeeded, false otherwise.
static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(Sema &S,
- NonTypeTemplateParmDecl *NTTP,
- ValueDecl *D,
- TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ NonTypeTemplateParmDecl *NTTP,
+ ValueDecl *D,
+ TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
@@ -405,7 +405,7 @@ DeduceTemplateArguments(Sema &S,
TemplateName Param,
TemplateName Arg,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
TemplateDecl *ParamDecl = Param.getAsTemplateDecl();
if (!ParamDecl) {
// The parameter type is dependent and is not a template template parameter,
@@ -464,7 +464,7 @@ DeduceTemplateArguments(Sema &S,
const TemplateSpecializationType *Param,
QualType Arg,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(Arg.isCanonical() && "Argument type must be canonical");
// Check whether the template argument is a dependent template-id.
@@ -575,20 +575,23 @@ getDepthAndIndex(UnexpandedParameterPack UPP) {
static TemplateParameter makeTemplateParameter(Decl *D) {
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(D))
return TemplateParameter(TTP);
- else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
return TemplateParameter(NTTP);
return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
}
+typedef SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
+ NewlyDeducedPacksType;
+
/// \brief Prepare to perform template argument deduction for all of the
/// arguments in a set of argument packs.
-static void PrepareArgumentPackDeduction(Sema &S,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- ArrayRef<unsigned> PackIndices,
- SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
- SmallVectorImpl<
- SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks) {
+static void
+PrepareArgumentPackDeduction(Sema &S,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ ArrayRef<unsigned> PackIndices,
+ SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
+ NewlyDeducedPacksType &NewlyDeducedPacks) {
// Save the deduced template arguments for each parameter pack expanded
// by this pack expansion, then clear out the deduction.
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
@@ -620,14 +623,13 @@ static void PrepareArgumentPackDeduction(Sema &S,
/// deductions.
static Sema::TemplateDeductionResult
FinishArgumentPackDeduction(Sema &S,
- TemplateParameterList *TemplateParams,
- bool HasAnyArguments,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- ArrayRef<unsigned> PackIndices,
- SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
- SmallVectorImpl<
- SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks,
- TemplateDeductionInfo &Info) {
+ TemplateParameterList *TemplateParams,
+ bool HasAnyArguments,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ ArrayRef<unsigned> PackIndices,
+ SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
+ NewlyDeducedPacksType &NewlyDeducedPacks,
+ TemplateDeductionInfo &Info) {
// Build argument packs for each of the parameter packs expanded by this
// pack expansion.
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
@@ -709,7 +711,7 @@ DeduceTemplateArguments(Sema &S,
const QualType *Params, unsigned NumParams,
const QualType *Args, unsigned NumArgs,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
bool PartialOrdering = false,
SmallVectorImpl<RefParamPartialOrderingComparison> *
@@ -793,8 +795,7 @@ DeduceTemplateArguments(Sema &S,
// Keep track of the deduced template arguments for each parameter pack
// expanded by this pack expansion (the outer index) and for each
// template argument (the inner SmallVectors).
- SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
- NewlyDeducedPacks(PackIndices.size());
+ NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size());
SmallVector<DeducedTemplateArgument, 2>
SavedPacks(PackIndices.size());
PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
@@ -1430,8 +1431,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
Deduced.end());
while (!ToVisit.empty()) {
// Retrieve the next class in the inheritance hierarchy.
- const RecordType *NextT = ToVisit.back();
- ToVisit.pop_back();
+ const RecordType *NextT = ToVisit.pop_back_val();
// If we have already seen this type, skip it.
if (!Visited.insert(NextT))
@@ -1635,7 +1635,7 @@ DeduceTemplateArguments(Sema &S,
const TemplateArgument &Param,
TemplateArgument Arg,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
// If the template argument is a pack expansion, perform template argument
// deduction against the pattern of that expansion. This only occurs during
// partial ordering.
@@ -1871,8 +1871,7 @@ DeduceTemplateArguments(Sema &S,
// by this pack expansion, then clear out the deduction.
SmallVector<DeducedTemplateArgument, 2>
SavedPacks(PackIndices.size());
- SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
- NewlyDeducedPacks(PackIndices.size());
+ NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size());
PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
NewlyDeducedPacks);
@@ -1921,7 +1920,7 @@ DeduceTemplateArguments(Sema &S,
const TemplateArgumentList &ParamList,
const TemplateArgumentList &ArgList,
TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
return DeduceTemplateArguments(S, TemplateParams,
ParamList.data(), ParamList.size(),
ArgList.data(), ArgList.size(),
@@ -2064,14 +2063,15 @@ getTrivialTemplateArgumentLoc(Sema &S,
/// \brief Convert the given deduced template argument and add it to the set of
/// fully-converted template arguments.
-static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
- DeducedTemplateArgument Arg,
- NamedDecl *Template,
- QualType NTTPType,
- unsigned ArgumentPackIndex,
- TemplateDeductionInfo &Info,
- bool InFunctionTemplate,
- SmallVectorImpl<TemplateArgument> &Output) {
+static bool
+ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
+ DeducedTemplateArgument Arg,
+ NamedDecl *Template,
+ QualType NTTPType,
+ unsigned ArgumentPackIndex,
+ TemplateDeductionInfo &Info,
+ bool InFunctionTemplate,
+ SmallVectorImpl<TemplateArgument> &Output) {
if (Arg.getKind() == TemplateArgument::Pack) {
// This is a template argument pack, so check each of its arguments against
// the template parameter.
@@ -2090,8 +2090,7 @@ static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
return true;
// Move the converted template argument into our argument pack.
- PackedArgsBuilder.push_back(Output.back());
- Output.pop_back();
+ PackedArgsBuilder.push_back(Output.pop_back_val());
}
// Create the resulting argument pack.
@@ -2200,14 +2199,15 @@ FinishTemplateArgumentDeduction(Sema &S,
// to the class template.
LocalInstantiationScope InstScope(S);
ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
- const TemplateArgumentLoc *PartialTemplateArgs
+ const ASTTemplateArgumentListInfo *PartialTemplArgInfo
= Partial->getTemplateArgsAsWritten();
+ const TemplateArgumentLoc *PartialTemplateArgs
+ = PartialTemplArgInfo->getTemplateArgs();
- // Note that we don't provide the langle and rangle locations.
- TemplateArgumentListInfo InstArgs;
+ TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc,
+ PartialTemplArgInfo->RAngleLoc);
- if (S.Subst(PartialTemplateArgs,
- Partial->getNumTemplateArgsAsWritten(),
+ if (S.Subst(PartialTemplateArgs, PartialTemplArgInfo->NumTemplateArgs,
InstArgs, MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx;
if (ParamIdx >= Partial->getTemplateParameters()->size())
@@ -2276,7 +2276,171 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
DeducedArgs, Info);
- if (Inst)
+ if (Inst.isInvalid())
+ return TDK_InstantiationDepth;
+
+ if (Trap.hasErrorOccurred())
+ return Sema::TDK_SubstitutionFailure;
+
+ return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs,
+ Deduced, Info);
+}
+
+/// Complete template argument deduction for a variable template partial
+/// specialization.
+/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
+/// May require unifying ClassTemplate(Partial)SpecializationDecl and
+/// VarTemplate(Partial)SpecializationDecl with a new data
+/// structure Template(Partial)SpecializationDecl, and
+/// using Template(Partial)SpecializationDecl as input type.
+static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
+ Sema &S, VarTemplatePartialSpecializationDecl *Partial,
+ const TemplateArgumentList &TemplateArgs,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ TemplateDeductionInfo &Info) {
+ // Unevaluated SFINAE context.
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
+ Sema::SFINAETrap Trap(S);
+
+ // C++ [temp.deduct.type]p2:
+ // [...] or if any template argument remains neither deduced nor
+ // explicitly specified, template argument deduction fails.
+ SmallVector<TemplateArgument, 4> Builder;
+ TemplateParameterList *PartialParams = Partial->getTemplateParameters();
+ for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) {
+ NamedDecl *Param = PartialParams->getParam(I);
+ if (Deduced[I].isNull()) {
+ Info.Param = makeTemplateParameter(Param);
+ return Sema::TDK_Incomplete;
+ }
+
+ // We have deduced this argument, so it still needs to be
+ // checked and converted.
+
+ // First, for a non-type template parameter type that is
+ // initialized by a declaration, we need the type of the
+ // corresponding non-type template parameter.
+ QualType NTTPType;
+ if (NonTypeTemplateParmDecl *NTTP =
+ dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ NTTPType = NTTP->getType();
+ if (NTTPType->isDependentType()) {
+ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+ Builder.data(), Builder.size());
+ NTTPType =
+ S.SubstType(NTTPType, MultiLevelTemplateArgumentList(TemplateArgs),
+ NTTP->getLocation(), NTTP->getDeclName());
+ if (NTTPType.isNull()) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
+ Builder.size()));
+ return Sema::TDK_SubstitutionFailure;
+ }
+ }
+ }
+
+ if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Partial, NTTPType,
+ 0, Info, false, Builder)) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
+ Builder.size()));
+ return Sema::TDK_SubstitutionFailure;
+ }
+ }
+
+ // Form the template argument list from the deduced template arguments.
+ TemplateArgumentList *DeducedArgumentList = TemplateArgumentList::CreateCopy(
+ S.Context, Builder.data(), Builder.size());
+
+ Info.reset(DeducedArgumentList);
+
+ // Substitute the deduced template arguments into the template
+ // arguments of the class template partial specialization, and
+ // verify that the instantiated template arguments are both valid
+ // and are equivalent to the template arguments originally provided
+ // to the class template.
+ LocalInstantiationScope InstScope(S);
+ VarTemplateDecl *VarTemplate = Partial->getSpecializedTemplate();
+ const ASTTemplateArgumentListInfo *PartialTemplArgInfo
+ = Partial->getTemplateArgsAsWritten();
+ const TemplateArgumentLoc *PartialTemplateArgs
+ = PartialTemplArgInfo->getTemplateArgs();
+
+ TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc,
+ PartialTemplArgInfo->RAngleLoc);
+
+ if (S.Subst(PartialTemplateArgs, PartialTemplArgInfo->NumTemplateArgs,
+ InstArgs, MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
+ unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx;
+ if (ParamIdx >= Partial->getTemplateParameters()->size())
+ ParamIdx = Partial->getTemplateParameters()->size() - 1;
+
+ Decl *Param = const_cast<NamedDecl *>(
+ Partial->getTemplateParameters()->getParam(ParamIdx));
+ Info.Param = makeTemplateParameter(Param);
+ Info.FirstArg = PartialTemplateArgs[ArgIdx].getArgument();
+ return Sema::TDK_SubstitutionFailure;
+ }
+ SmallVector<TemplateArgument, 4> ConvertedInstArgs;
+ if (S.CheckTemplateArgumentList(VarTemplate, Partial->getLocation(), InstArgs,
+ false, ConvertedInstArgs))
+ return Sema::TDK_SubstitutionFailure;
+
+ TemplateParameterList *TemplateParams = VarTemplate->getTemplateParameters();
+ for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
+ TemplateArgument InstArg = ConvertedInstArgs.data()[I];
+ if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg)) {
+ Info.Param = makeTemplateParameter(TemplateParams->getParam(I));
+ Info.FirstArg = TemplateArgs[I];
+ Info.SecondArg = InstArg;
+ return Sema::TDK_NonDeducedMismatch;
+ }
+ }
+
+ if (Trap.hasErrorOccurred())
+ return Sema::TDK_SubstitutionFailure;
+
+ return Sema::TDK_Success;
+}
+
+/// \brief Perform template argument deduction to determine whether
+/// the given template arguments match the given variable template
+/// partial specialization per C++ [temp.class.spec.match].
+/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
+/// May require unifying ClassTemplate(Partial)SpecializationDecl and
+/// VarTemplate(Partial)SpecializationDecl with a new data
+/// structure Template(Partial)SpecializationDecl, and
+/// using Template(Partial)SpecializationDecl as input type.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
+ const TemplateArgumentList &TemplateArgs,
+ TemplateDeductionInfo &Info) {
+ if (Partial->isInvalidDecl())
+ return TDK_Invalid;
+
+ // C++ [temp.class.spec.match]p2:
+ // A partial specialization matches a given actual template
+ // argument list if the template arguments of the partial
+ // specialization can be deduced from the actual template argument
+ // list (14.8.2).
+
+ // Unevaluated SFINAE context.
+ EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+ SFINAETrap Trap(*this);
+
+ SmallVector<DeducedTemplateArgument, 4> Deduced;
+ Deduced.resize(Partial->getTemplateParameters()->size());
+ if (TemplateDeductionResult Result = ::DeduceTemplateArguments(
+ *this, Partial->getTemplateParameters(), Partial->getTemplateArgs(),
+ TemplateArgs, Info, Deduced))
+ return Result;
+
+ SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
+ InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
+ DeducedArgs, Info);
+ if (Inst.isInvalid())
return TDK_InstantiationDepth;
if (Trap.hasErrorOccurred())
@@ -2364,7 +2528,7 @@ Sema::SubstituteExplicitTemplateArguments(
FunctionTemplate, DeducedArgs,
ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution,
Info);
- if (Inst)
+ if (Inst.isInvalid())
return TDK_InstantiationDepth;
if (CheckTemplateArgumentList(FunctionTemplate,
@@ -2423,7 +2587,6 @@ Sema::SubstituteExplicitTemplateArguments(
}
// Instantiate the return type.
- // FIXME: exception-specifications?
QualType ResultType;
{
// C++11 [expr.prim.general]p3:
@@ -2524,13 +2687,16 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
Qualifiers AQuals = A.getQualifiers();
Qualifiers DeducedAQuals = DeducedA.getQualifiers();
- // Under Objective-C++ ARC, the deduced type may have implicitly been
- // given strong lifetime. If so, update the original qualifiers to
- // include this strong lifetime.
+ // Under Objective-C++ ARC, the deduced type may have implicitly
+ // been given strong or (when dealing with a const reference)
+ // unsafe_unretained lifetime. If so, update the original
+ // qualifiers to include this lifetime.
if (S.getLangOpts().ObjCAutoRefCount &&
- DeducedAQuals.getObjCLifetime() == Qualifiers::OCL_Strong &&
- AQuals.getObjCLifetime() == Qualifiers::OCL_None) {
- AQuals.setObjCLifetime(Qualifiers::OCL_Strong);
+ ((DeducedAQuals.getObjCLifetime() == Qualifiers::OCL_Strong &&
+ AQuals.getObjCLifetime() == Qualifiers::OCL_None) ||
+ (DeducedAQuals.hasConst() &&
+ DeducedAQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone))) {
+ AQuals.setObjCLifetime(DeducedAQuals.getObjCLifetime());
}
if (AQuals == DeducedAQuals) {
@@ -2551,7 +2717,7 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
//
// Also allow conversions which merely strip [[noreturn]] from function types
// (recursively) as an extension.
- // FIXME: Currently, this doesn't place nicely with qualfication conversions.
+ // FIXME: Currently, this doesn't play nicely with qualification conversions.
bool ObjCLifetimeConversion = false;
QualType ResultTy;
if ((A->isAnyPointerType() || A->isMemberPointerType()) &&
@@ -2616,7 +2782,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
FunctionTemplate, DeducedArgs,
ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
Info);
- if (Inst)
+ if (Inst.isInvalid())
return TDK_InstantiationDepth;
ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
@@ -2704,18 +2870,21 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
}
// Substitute into the default template argument, if available.
+ bool HasDefaultArg = false;
TemplateArgumentLoc DefArg
= SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate,
FunctionTemplate->getLocation(),
FunctionTemplate->getSourceRange().getEnd(),
Param,
- Builder);
+ Builder, HasDefaultArg);
// If there was no default argument, deduction is incomplete.
if (DefArg.getArgument().isNull()) {
Info.Param = makeTemplateParameter(
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
- return TDK_Incomplete;
+ Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(),
+ Builder.size()));
+ return HasDefaultArg ? TDK_SubstitutionFailure : TDK_Incomplete;
}
// Check whether we can actually use the default argument.
@@ -2792,7 +2961,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// keep track of these diagnostics. They'll be emitted if this specialization
// is actually used.
if (Info.diag_begin() != Info.diag_end()) {
- llvm::DenseMap<Decl *, SmallVector<PartialDiagnosticAt, 1> >::iterator
+ SuppressedDiagnosticsMap::iterator
Pos = SuppressedDiagnostics.find(Specialization->getCanonicalDecl());
if (Pos == SuppressedDiagnostics.end())
SuppressedDiagnostics[Specialization->getCanonicalDecl()]
@@ -3099,12 +3268,10 @@ DeduceTemplateArgumentByListElement(Sema &S,
/// about template argument deduction.
///
/// \returns the result of template argument deduction.
-Sema::TemplateDeductionResult
-Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- llvm::ArrayRef<Expr *> Args,
- FunctionDecl *&Specialization,
- TemplateDeductionInfo &Info) {
+Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
+ FunctionDecl *&Specialization, TemplateDeductionInfo &Info) {
if (FunctionTemplate->isInvalidDecl())
return TDK_Invalid;
@@ -3251,8 +3418,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// Keep track of the deduced template arguments for each parameter pack
// expanded by this pack expansion (the outer index) and for each
// template argument (the inner SmallVectors).
- SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
- NewlyDeducedPacks(PackIndices.size());
+ NewlyDeducedPacksType NewlyDeducedPacks(PackIndices.size());
SmallVector<DeducedTemplateArgument, 2>
SavedPacks(PackIndices.size());
PrepareArgumentPackDeduction(*this, Deduced, PackIndices, SavedPacks,
@@ -3335,6 +3501,28 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
Specialization, Info, &OriginalCallArgs);
}
+QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
+ QualType FunctionType) {
+ if (ArgFunctionType.isNull())
+ return ArgFunctionType;
+
+ const FunctionProtoType *FunctionTypeP =
+ FunctionType->castAs<FunctionProtoType>();
+ CallingConv CC = FunctionTypeP->getCallConv();
+ bool NoReturn = FunctionTypeP->getNoReturnAttr();
+ const FunctionProtoType *ArgFunctionTypeP =
+ ArgFunctionType->getAs<FunctionProtoType>();
+ if (ArgFunctionTypeP->getCallConv() == CC &&
+ ArgFunctionTypeP->getNoReturnAttr() == NoReturn)
+ return ArgFunctionType;
+
+ FunctionType::ExtInfo EI = ArgFunctionTypeP->getExtInfo().withCallingConv(CC);
+ EI = EI.withNoReturn(NoReturn);
+ ArgFunctionTypeP =
+ cast<FunctionProtoType>(Context.adjustFunctionType(ArgFunctionTypeP, EI));
+ return QualType(ArgFunctionTypeP, 0);
+}
+
/// \brief Deduce template arguments when taking the address of a function
/// template (C++ [temp.deduct.funcaddr]) or matching a specialization to
/// a template.
@@ -3372,6 +3560,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
QualType FunctionType = Function->getType();
+ if (!InOverloadResolution)
+ ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType);
// Substitute any explicit template arguments.
LocalInstantiationScope InstScope(*this);
@@ -3397,11 +3587,11 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// If the function has a deduced return type, substitute it for a dependent
// type so that we treat it as a non-deduced context in what follows.
- bool HasUndeducedReturnType = false;
+ bool HasDeducedReturnType = false;
if (getLangOpts().CPlusPlus1y && InOverloadResolution &&
- Function->getResultType()->isUndeducedType()) {
+ Function->getResultType()->getContainedAutoType()) {
FunctionType = SubstAutoType(FunctionType, Context.DependentTy);
- HasUndeducedReturnType = true;
+ HasDeducedReturnType = true;
}
if (!ArgFunctionType.isNull()) {
@@ -3423,7 +3613,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// If the function has a deduced return type, deduce it now, so we can check
// that the deduced function type matches the requested type.
- if (HasUndeducedReturnType &&
+ if (HasDeducedReturnType &&
Specialization->getResultType()->isUndeducedType() &&
DeduceReturnType(Specialization, Info.getLocation(), false))
return TDK_MiscellaneousDeductionFailure;
@@ -3444,20 +3634,130 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
return TDK_Success;
}
+/// \brief Given a function declaration (e.g. a generic lambda conversion
+/// function) that contains an 'auto' in its result type, substitute it
+/// with TypeToReplaceAutoWith. Be careful to pass in the type you want
+/// to replace 'auto' with and not the actual result type you want
+/// to set the function to.
+static inline void
+SubstAutoWithinFunctionReturnType(FunctionDecl *F,
+ QualType TypeToReplaceAutoWith, Sema &S) {
+ assert(!TypeToReplaceAutoWith->getContainedAutoType());
+ QualType AutoResultType = F->getResultType();
+ assert(AutoResultType->getContainedAutoType());
+ QualType DeducedResultType = S.SubstAutoType(AutoResultType,
+ TypeToReplaceAutoWith);
+ S.Context.adjustDeducedFunctionResultType(F, DeducedResultType);
+}
+
+/// \brief Given a specialized conversion operator of a generic lambda
+/// create the corresponding specializations of the call operator and
+/// the static-invoker. If the return type of the call operator is auto,
+/// deduce its return type and check if that matches the
+/// return type of the destination function ptr.
+
+static inline Sema::TemplateDeductionResult
+SpecializeCorrespondingLambdaCallOperatorAndInvoker(
+ CXXConversionDecl *ConversionSpecialized,
+ SmallVectorImpl<DeducedTemplateArgument> &DeducedArguments,
+ QualType ReturnTypeOfDestFunctionPtr,
+ TemplateDeductionInfo &TDInfo,
+ Sema &S) {
+
+ CXXRecordDecl *LambdaClass = ConversionSpecialized->getParent();
+ assert(LambdaClass && LambdaClass->isGenericLambda());
+
+ CXXMethodDecl *CallOpGeneric = LambdaClass->getLambdaCallOperator();
+ QualType CallOpResultType = CallOpGeneric->getResultType();
+ const bool GenericLambdaCallOperatorHasDeducedReturnType =
+ CallOpResultType->getContainedAutoType();
+
+ FunctionTemplateDecl *CallOpTemplate =
+ CallOpGeneric->getDescribedFunctionTemplate();
+
+ FunctionDecl *CallOpSpecialized = 0;
+ // Use the deduced arguments of the conversion function, to specialize our
+ // generic lambda's call operator.
+ if (Sema::TemplateDeductionResult Result
+ = S.FinishTemplateArgumentDeduction(CallOpTemplate,
+ DeducedArguments,
+ 0, CallOpSpecialized, TDInfo))
+ return Result;
+
+ // If we need to deduce the return type, do so (instantiates the callop).
+ if (GenericLambdaCallOperatorHasDeducedReturnType &&
+ CallOpSpecialized->getResultType()->isUndeducedType())
+ S.DeduceReturnType(CallOpSpecialized,
+ CallOpSpecialized->getPointOfInstantiation(),
+ /*Diagnose*/ true);
+
+ // Check to see if the return type of the destination ptr-to-function
+ // matches the return type of the call operator.
+ if (!S.Context.hasSameType(CallOpSpecialized->getResultType(),
+ ReturnTypeOfDestFunctionPtr))
+ return Sema::TDK_NonDeducedMismatch;
+ // Since we have succeeded in matching the source and destination
+ // ptr-to-functions (now including return type), and have successfully
+ // specialized our corresponding call operator, we are ready to
+ // specialize the static invoker with the deduced arguments of our
+ // ptr-to-function.
+ FunctionDecl *InvokerSpecialized = 0;
+ FunctionTemplateDecl *InvokerTemplate = LambdaClass->
+ getLambdaStaticInvoker()->getDescribedFunctionTemplate();
+
+ Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result
+ = S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0,
+ InvokerSpecialized, TDInfo);
+ assert(Result == Sema::TDK_Success &&
+ "If the call operator succeeded so should the invoker!");
+ // Set the result type to match the corresponding call operator
+ // specialization's result type.
+ if (GenericLambdaCallOperatorHasDeducedReturnType &&
+ InvokerSpecialized->getResultType()->isUndeducedType()) {
+ // Be sure to get the type to replace 'auto' with and not
+ // the full result type of the call op specialization
+ // to substitute into the 'auto' of the invoker and conversion
+ // function.
+ // For e.g.
+ // int* (*fp)(int*) = [](auto* a) -> auto* { return a; };
+ // We don't want to subst 'int*' into 'auto' to get int**.
+
+ QualType TypeToReplaceAutoWith =
+ CallOpSpecialized->getResultType()->
+ getContainedAutoType()->getDeducedType();
+ SubstAutoWithinFunctionReturnType(InvokerSpecialized,
+ TypeToReplaceAutoWith, S);
+ SubstAutoWithinFunctionReturnType(ConversionSpecialized,
+ TypeToReplaceAutoWith, S);
+ }
+
+ // Ensure that static invoker doesn't have a const qualifier.
+ // FIXME: When creating the InvokerTemplate in SemaLambda.cpp
+ // do not use the CallOperator's TypeSourceInfo which allows
+ // the const qualifier to leak through.
+ const FunctionProtoType *InvokerFPT = InvokerSpecialized->
+ getType().getTypePtr()->castAs<FunctionProtoType>();
+ FunctionProtoType::ExtProtoInfo EPI = InvokerFPT->getExtProtoInfo();
+ EPI.TypeQuals = 0;
+ InvokerSpecialized->setType(S.Context.getFunctionType(
+ InvokerFPT->getResultType(), InvokerFPT->getArgTypes(),EPI));
+ return Sema::TDK_Success;
+}
/// \brief Deduce template arguments for a templated conversion
/// function (C++ [temp.deduct.conv]) and, if successful, produce a
/// conversion function template specialization.
Sema::TemplateDeductionResult
-Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
QualType ToType,
CXXConversionDecl *&Specialization,
TemplateDeductionInfo &Info) {
- if (FunctionTemplate->isInvalidDecl())
+ if (ConversionTemplate->isInvalidDecl())
return TDK_Invalid;
- CXXConversionDecl *Conv
- = cast<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl());
- QualType FromType = Conv->getConversionType();
+ CXXConversionDecl *ConversionGeneric
+ = cast<CXXConversionDecl>(ConversionTemplate->getTemplatedDecl());
+
+ QualType FromType = ConversionGeneric->getConversionType();
// Canonicalize the types for deduction.
QualType P = Context.getCanonicalType(FromType);
@@ -3512,7 +3812,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// type that is required as the result of the conversion (call it
// A) as described in 14.8.2.4.
TemplateParameterList *TemplateParams
- = FunctionTemplate->getTemplateParameters();
+ = ConversionTemplate->getTemplateParameters();
SmallVector<DeducedTemplateArgument, 4> Deduced;
Deduced.resize(TemplateParams->size());
@@ -3541,13 +3841,43 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
P, A, Info, Deduced, TDF))
return Result;
- // Finish template argument deduction.
+ // Create an Instantiation Scope for finalizing the operator.
LocalInstantiationScope InstScope(*this);
- FunctionDecl *Spec = 0;
+ // Finish template argument deduction.
+ FunctionDecl *ConversionSpecialized = 0;
TemplateDeductionResult Result
- = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, 0, Spec,
- Info);
- Specialization = cast_or_null<CXXConversionDecl>(Spec);
+ = FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
+ ConversionSpecialized, Info);
+ Specialization = cast_or_null<CXXConversionDecl>(ConversionSpecialized);
+
+ // If the conversion operator is being invoked on a lambda closure to convert
+ // to a ptr-to-function, use the deduced arguments from the conversion function
+ // to specialize the corresponding call operator.
+ // e.g., int (*fp)(int) = [](auto a) { return a; };
+ if (Result == TDK_Success && isLambdaConversionOperator(ConversionGeneric)) {
+
+ // Get the return type of the destination ptr-to-function we are converting
+ // to. This is necessary for matching the lambda call operator's return
+ // type to that of the destination ptr-to-function's return type.
+ assert(A->isPointerType() &&
+ "Can only convert from lambda to ptr-to-function");
+ const FunctionType *ToFunType =
+ A->getPointeeType().getTypePtr()->getAs<FunctionType>();
+ const QualType DestFunctionPtrReturnType = ToFunType->getResultType();
+
+ // Create the corresponding specializations of the call operator and
+ // the static-invoker; and if the return type is auto,
+ // deduce the return type and check if it matches the
+ // DestFunctionPtrReturnType.
+ // For instance:
+ // auto L = [](auto a) { return f(a); };
+ // int (*fp)(int) = L;
+ // char (*fp2)(int) = L; <-- Not OK.
+
+ Result = SpecializeCorrespondingLambdaCallOperatorAndInvoker(
+ Specialization, Deduced, DestFunctionPtrReturnType,
+ Info, *this);
+ }
return Result;
}
@@ -3750,17 +4080,29 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
return DAR_Succeeded;
}
-QualType Sema::SubstAutoType(QualType Type, QualType Deduced) {
- return SubstituteAutoTransform(*this, Deduced).TransformType(Type);
+QualType Sema::SubstAutoType(QualType TypeWithAuto,
+ QualType TypeToReplaceAuto) {
+ return SubstituteAutoTransform(*this, TypeToReplaceAuto).
+ TransformType(TypeWithAuto);
+}
+
+TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
+ QualType TypeToReplaceAuto) {
+ return SubstituteAutoTransform(*this, TypeToReplaceAuto).
+ TransformType(TypeWithAuto);
}
void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
if (isa<InitListExpr>(Init))
Diag(VDecl->getLocation(),
- diag::err_auto_var_deduction_failure_from_init_list)
+ VDecl->isInitCapture()
+ ? diag::err_init_capture_deduction_failure_from_init_list
+ : diag::err_auto_var_deduction_failure_from_init_list)
<< VDecl->getDeclName() << VDecl->getType() << Init->getSourceRange();
else
- Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
+ Diag(VDecl->getLocation(),
+ VDecl->isInitCapture() ? diag::err_init_capture_deduction_failure
+ : diag::err_auto_var_deduction_failure)
<< VDecl->getDeclName() << VDecl->getType() << Init->getType()
<< Init->getSourceRange();
}
@@ -3788,9 +4130,10 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
llvm::SmallBitVector &Deduced);
/// \brief If this is a non-static member function,
-static void AddImplicitObjectParameterType(ASTContext &Context,
- CXXMethodDecl *Method,
- SmallVectorImpl<QualType> &ArgTypes) {
+static void
+AddImplicitObjectParameterType(ASTContext &Context,
+ CXXMethodDecl *Method,
+ SmallVectorImpl<QualType> &ArgTypes) {
// C++11 [temp.func.order]p3:
// [...] The new parameter is of type "reference to cv A," where cv are
// the cv-qualifiers of the function template (if any) and A is
@@ -3815,7 +4158,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
TemplatePartialOrderingContext TPOC,
- unsigned NumCallArguments,
+ unsigned NumCallArguments1,
SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) {
FunctionDecl *FD1 = FT1->getTemplatedDecl();
FunctionDecl *FD2 = FT2->getTemplatedDecl();
@@ -3831,19 +4174,13 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
// The types used to determine the ordering depend on the context in which
// the partial ordering is done:
TemplateDeductionInfo Info(Loc);
- CXXMethodDecl *Method1 = 0;
- CXXMethodDecl *Method2 = 0;
- bool IsNonStatic2 = false;
- bool IsNonStatic1 = false;
- unsigned Skip2 = 0;
+ SmallVector<QualType, 4> Args2;
switch (TPOC) {
case TPOC_Call: {
// - In the context of a function call, the function parameter types are
// used.
- Method1 = dyn_cast<CXXMethodDecl>(FD1);
- Method2 = dyn_cast<CXXMethodDecl>(FD2);
- IsNonStatic1 = Method1 && !Method1->isStatic();
- IsNonStatic2 = Method2 && !Method2->isStatic();
+ CXXMethodDecl *Method1 = dyn_cast<CXXMethodDecl>(FD1);
+ CXXMethodDecl *Method2 = dyn_cast<CXXMethodDecl>(FD2);
// C++11 [temp.func.order]p3:
// [...] If only one of the function templates is a non-static
@@ -3862,26 +4199,39 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
// first argument of the free function, which seems to match
// existing practice.
SmallVector<QualType, 4> Args1;
- unsigned Skip1 = !S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !Method1;
- if (S.getLangOpts().CPlusPlus11 && IsNonStatic1 && !Method2)
- AddImplicitObjectParameterType(S.Context, Method1, Args1);
+
+ unsigned Skip1 = 0, Skip2 = 0;
+ unsigned NumComparedArguments = NumCallArguments1;
+
+ if (!Method2 && Method1 && !Method1->isStatic()) {
+ if (S.getLangOpts().CPlusPlus11) {
+ // Compare 'this' from Method1 against first parameter from Method2.
+ AddImplicitObjectParameterType(S.Context, Method1, Args1);
+ ++NumComparedArguments;
+ } else
+ // Ignore first parameter from Method2.
+ ++Skip2;
+ } else if (!Method1 && Method2 && !Method2->isStatic()) {
+ if (S.getLangOpts().CPlusPlus11)
+ // Compare 'this' from Method2 against first parameter from Method1.
+ AddImplicitObjectParameterType(S.Context, Method2, Args2);
+ else
+ // Ignore first parameter from Method1.
+ ++Skip1;
+ }
+
Args1.insert(Args1.end(),
Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end());
-
- SmallVector<QualType, 4> Args2;
- Skip2 = !S.getLangOpts().CPlusPlus11 && IsNonStatic1 && !Method2;
- if (S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !Method1)
- AddImplicitObjectParameterType(S.Context, Method2, Args2);
Args2.insert(Args2.end(),
Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end());
// C++ [temp.func.order]p5:
// The presence of unused ellipsis and default arguments has no effect on
// the partial ordering of function templates.
- if (Args1.size() > NumCallArguments)
- Args1.resize(NumCallArguments);
- if (Args2.size() > NumCallArguments)
- Args2.resize(NumCallArguments);
+ if (Args1.size() > NumComparedArguments)
+ Args1.resize(NumComparedArguments);
+ if (Args2.size() > NumComparedArguments)
+ Args2.resize(NumComparedArguments);
if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(),
Args1.data(), Args1.size(), Info, Deduced,
TDF_None, /*PartialOrdering=*/true,
@@ -3935,20 +4285,12 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
// Figure out which template parameters were used.
llvm::SmallBitVector UsedParameters(TemplateParams->size());
switch (TPOC) {
- case TPOC_Call: {
- unsigned NumParams = std::min(NumCallArguments,
- std::min(Proto1->getNumArgs(),
- Proto2->getNumArgs()));
- if (S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !IsNonStatic1)
- ::MarkUsedTemplateParameters(S.Context, Method2->getThisType(S.Context),
- false,
- TemplateParams->getDepth(), UsedParameters);
- for (unsigned I = Skip2; I < NumParams; ++I)
- ::MarkUsedTemplateParameters(S.Context, Proto2->getArgType(I), false,
+ case TPOC_Call:
+ for (unsigned I = 0, N = Args2.size(); I != N; ++I)
+ ::MarkUsedTemplateParameters(S.Context, Args2[I], false,
TemplateParams->getDepth(),
UsedParameters);
break;
- }
case TPOC_Conversion:
::MarkUsedTemplateParameters(S.Context, Proto2->getResultType(), false,
@@ -4003,8 +4345,11 @@ static bool isVariadicFunctionTemplate(FunctionTemplateDecl *FunTmpl) {
/// \param TPOC the context in which we are performing partial ordering of
/// function templates.
///
-/// \param NumCallArguments The number of arguments in a call, used only
-/// when \c TPOC is \c TPOC_Call.
+/// \param NumCallArguments1 The number of arguments in the call to FT1, used
+/// only when \c TPOC is \c TPOC_Call.
+///
+/// \param NumCallArguments2 The number of arguments in the call to FT2, used
+/// only when \c TPOC is \c TPOC_Call.
///
/// \returns the more specialized function template. If neither
/// template is more specialized, returns NULL.
@@ -4013,12 +4358,13 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
SourceLocation Loc,
TemplatePartialOrderingContext TPOC,
- unsigned NumCallArguments) {
+ unsigned NumCallArguments1,
+ unsigned NumCallArguments2) {
SmallVector<RefParamPartialOrderingComparison, 4> RefParamComparisons;
bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC,
- NumCallArguments, 0);
+ NumCallArguments1, 0);
bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
- NumCallArguments,
+ NumCallArguments2,
&RefParamComparisons);
if (Better1 != Better2) // We have a clear winner
@@ -4122,12 +4468,6 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
/// \param SpecEnd the end iterator of the function template
/// specializations, paired with \p SpecBegin.
///
-/// \param TPOC the partial ordering context to use to compare the function
-/// template specializations.
-///
-/// \param NumCallArguments The number of arguments in a call, used only
-/// when \c TPOC is \c TPOC_Call.
-///
/// \param Loc the location where the ambiguity or no-specializations
/// diagnostic should occur.
///
@@ -4144,23 +4484,17 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
///
/// \returns the most specialized function template specialization, if
/// found. Otherwise, returns SpecEnd.
-///
-/// \todo FIXME: Consider passing in the "also-ran" candidates that failed
-/// template argument deduction.
-UnresolvedSetIterator
-Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
- UnresolvedSetIterator SpecEnd,
- TemplatePartialOrderingContext TPOC,
- unsigned NumCallArguments,
- SourceLocation Loc,
- const PartialDiagnostic &NoneDiag,
- const PartialDiagnostic &AmbigDiag,
- const PartialDiagnostic &CandidateDiag,
- bool Complain,
- QualType TargetType) {
+UnresolvedSetIterator Sema::getMostSpecialized(
+ UnresolvedSetIterator SpecBegin, UnresolvedSetIterator SpecEnd,
+ TemplateSpecCandidateSet &FailedCandidates,
+ SourceLocation Loc, const PartialDiagnostic &NoneDiag,
+ const PartialDiagnostic &AmbigDiag, const PartialDiagnostic &CandidateDiag,
+ bool Complain, QualType TargetType) {
if (SpecBegin == SpecEnd) {
- if (Complain)
+ if (Complain) {
Diag(Loc, NoneDiag);
+ FailedCandidates.NoteCandidates(*this, Loc);
+ }
return SpecEnd;
}
@@ -4178,7 +4512,7 @@ Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
= cast<FunctionDecl>(*I)->getPrimaryTemplate();
assert(Challenger && "Not a function template specialization?");
if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
- Loc, TPOC, NumCallArguments),
+ Loc, TPOC_Other, 0, 0),
Challenger)) {
Best = I;
BestTemplate = Challenger;
@@ -4193,7 +4527,7 @@ Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
= cast<FunctionDecl>(*I)->getPrimaryTemplate();
if (I != Best &&
!isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
- Loc, TPOC, NumCallArguments),
+ Loc, TPOC_Other, 0, 0),
BestTemplate)) {
Ambiguous = true;
break;
@@ -4279,6 +4613,67 @@ Sema::getMoreSpecializedPartialSpecialization(
/*RefParamComparisons=*/0);
if (Better1) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
+ InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2, DeducedArgs,
+ Info);
+ Better1 = !::FinishTemplateArgumentDeduction(
+ *this, PS2, PS1->getTemplateArgs(), Deduced, Info);
+ }
+
+ // Determine whether PS2 is at least as specialized as PS1
+ Deduced.clear();
+ Deduced.resize(PS1->getTemplateParameters()->size());
+ bool Better2 = !DeduceTemplateArgumentsByTypeMatch(
+ *this, PS1->getTemplateParameters(), PT1, PT2, Info, Deduced, TDF_None,
+ /*PartialOrdering=*/true,
+ /*RefParamComparisons=*/0);
+ if (Better2) {
+ SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
+ Deduced.end());
+ InstantiatingTemplate Inst(*this, PS1->getLocation(), PS1, DeducedArgs,
+ Info);
+ Better2 = !::FinishTemplateArgumentDeduction(
+ *this, PS1, PS2->getTemplateArgs(), Deduced, Info);
+ }
+
+ if (Better1 == Better2)
+ return 0;
+
+ return Better1 ? PS1 : PS2;
+}
+
+/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
+/// May require unifying ClassTemplate(Partial)SpecializationDecl and
+/// VarTemplate(Partial)SpecializationDecl with a new data
+/// structure Template(Partial)SpecializationDecl, and
+/// using Template(Partial)SpecializationDecl as input type.
+VarTemplatePartialSpecializationDecl *
+Sema::getMoreSpecializedPartialSpecialization(
+ VarTemplatePartialSpecializationDecl *PS1,
+ VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc) {
+ SmallVector<DeducedTemplateArgument, 4> Deduced;
+ TemplateDeductionInfo Info(Loc);
+
+ assert(PS1->getSpecializedTemplate() == PS1->getSpecializedTemplate() &&
+ "the partial specializations being compared should specialize"
+ " the same template.");
+ TemplateName Name(PS1->getSpecializedTemplate());
+ TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
+ QualType PT1 = Context.getTemplateSpecializationType(
+ CanonTemplate, PS1->getTemplateArgs().data(),
+ PS1->getTemplateArgs().size());
+ QualType PT2 = Context.getTemplateSpecializationType(
+ CanonTemplate, PS2->getTemplateArgs().data(),
+ PS2->getTemplateArgs().size());
+
+ // Determine whether PS1 is at least as specialized as PS2
+ Deduced.resize(PS2->getTemplateParameters()->size());
+ bool Better1 = !DeduceTemplateArgumentsByTypeMatch(
+ *this, PS2->getTemplateParameters(), PT2, PT1, Info, Deduced, TDF_None,
+ /*PartialOrdering=*/true,
+ /*RefParamComparisons=*/0);
+ if (Better1) {
+ SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
+ Deduced.end());
InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2,
DeducedArgs, Info);
Better1 = !::FinishTemplateArgumentDeduction(*this, PS2,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 7ef04e964dc6..8904f3794955 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -14,6 +14,7 @@
#include "TreeTransform.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/LangOptions.h"
@@ -61,7 +62,24 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
DeclContext *Ctx = dyn_cast<DeclContext>(D);
if (!Ctx) {
Ctx = D->getDeclContext();
-
+
+ // Add template arguments from a variable template instantiation.
+ if (VarTemplateSpecializationDecl *Spec =
+ dyn_cast<VarTemplateSpecializationDecl>(D)) {
+ // We're done when we hit an explicit specialization.
+ if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
+ !isa<VarTemplatePartialSpecializationDecl>(Spec))
+ return Result;
+
+ Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
+
+ // If this variable template specialization was instantiated from a
+ // specialized member that is a variable template, we're done.
+ assert(Spec->getSpecializedTemplate() && "No variable template?");
+ if (Spec->getSpecializedTemplate()->isMemberSpecialization())
+ return Result;
+ }
+
// If we have a template template parameter with translation unit context,
// then we're performing substitution into a default template argument of
// this template template parameter before we've constructed the template
@@ -72,7 +90,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(D)) {
for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I)
- Result.addOuterTemplateArguments(0, 0);
+ Result.addOuterTemplateArguments(None);
return Result;
}
}
@@ -113,12 +131,15 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
assert(Function->getPrimaryTemplate() && "No function template?");
if (Function->getPrimaryTemplate()->isMemberSpecialization())
break;
+
+ // If this function is a generic lambda specialization, we are done.
+ if (isGenericLambdaCallOperatorSpecialization(Function))
+ 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);
+ Result.addOuterTemplateArguments(FunTmpl->getInjectedTemplateArgs());
}
// If this is a friend declaration and it declares an entity at
@@ -135,9 +156,10 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
} else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Ctx)) {
if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) {
QualType T = ClassTemplate->getInjectedClassNameSpecialization();
- const TemplateSpecializationType *TST
- = cast<TemplateSpecializationType>(Context.getCanonicalType(T));
- Result.addOuterTemplateArguments(TST->getArgs(), TST->getNumArgs());
+ const TemplateSpecializationType *TST =
+ cast<TemplateSpecializationType>(Context.getCanonicalType(T));
+ Result.addOuterTemplateArguments(
+ llvm::makeArrayRef(TST->getArgs(), TST->getNumArgs()));
if (ClassTemplate->isMemberSpecialization())
break;
}
@@ -293,6 +315,29 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
}
}
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, SourceLocation PointOfInstantiation,
+ VarTemplatePartialSpecializationDecl *PartialSpec,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
+ : SemaRef(SemaRef), SavedInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext) {
+ Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
+ if (!Invalid) {
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind =
+ ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = PartialSpec;
+ Inst.TemplateArgs = TemplateArgs.data();
+ Inst.NumTemplateArgs = TemplateArgs.size();
+ Inst.DeductionInfo = &DeductionInfo;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.InNonInstantiationSFINAEContext = false;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+ }
+}
+
Sema::InstantiatingTemplate::
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ParmVarDecl *Param,
@@ -399,6 +444,18 @@ void Sema::InstantiatingTemplate::Clear() {
}
SemaRef.InNonInstantiationSFINAEContext
= SavedInNonInstantiationSFINAEContext;
+
+ // Name lookup no longer looks in this template's defining module.
+ assert(SemaRef.ActiveTemplateInstantiations.size() >=
+ SemaRef.ActiveTemplateInstantiationLookupModules.size() &&
+ "forgot to remove a lookup module for a template instantiation");
+ if (SemaRef.ActiveTemplateInstantiations.size() ==
+ SemaRef.ActiveTemplateInstantiationLookupModules.size()) {
+ if (Module *M = SemaRef.ActiveTemplateInstantiationLookupModules.back())
+ SemaRef.LookupModulesCache.erase(M);
+ SemaRef.ActiveTemplateInstantiationLookupModules.pop_back();
+ }
+
SemaRef.ActiveTemplateInstantiations.pop_back();
Invalid = true;
}
@@ -436,7 +493,7 @@ void Sema::PrintInstantiationStack() {
// FIXME: In all of these cases, we need to show the template arguments
unsigned InstantiationIdx = 0;
- for (SmallVector<ActiveTemplateInstantiation, 16>::reverse_iterator
+ for (SmallVectorImpl<ActiveTemplateInstantiation>::reverse_iterator
Active = ActiveTemplateInstantiations.rbegin(),
ActiveEnd = ActiveTemplateInstantiations.rend();
Active != ActiveEnd;
@@ -473,7 +530,9 @@ void Sema::PrintInstantiationStack() {
<< Active->InstantiationRange;
} else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
Diags.Report(Active->PointOfInstantiation,
- diag::note_template_static_data_member_def_here)
+ VD->isStaticDataMember()?
+ diag::note_template_static_data_member_def_here
+ : diag::note_template_variable_def_here)
<< VD
<< Active->InstantiationRange;
} else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
@@ -616,7 +675,7 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
if (InNonInstantiationSFINAEContext)
return Optional<TemplateDeductionInfo *>(0);
- for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator
+ for (SmallVectorImpl<ActiveTemplateInstantiation>::const_reverse_iterator
Active = ActiveTemplateInstantiations.rbegin(),
ActiveEnd = ActiveTemplateInstantiations.rend();
Active != ActiveEnd;
@@ -708,9 +767,8 @@ namespace {
bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
SourceRange PatternRange,
- llvm::ArrayRef<UnexpandedParameterPack> Unexpanded,
- bool &ShouldExpand,
- bool &RetainExpansion,
+ ArrayRef<UnexpandedParameterPack> Unexpanded,
+ bool &ShouldExpand, bool &RetainExpansion,
Optional<unsigned> &NumExpansions) {
return getSema().CheckParameterPacksForExpansion(EllipsisLoc,
PatternRange, Unexpanded,
@@ -859,13 +917,38 @@ namespace {
}
ExprResult TransformLambdaScope(LambdaExpr *E,
- CXXMethodDecl *CallOperator) {
- CallOperator->setInstantiationOfMemberFunction(E->getCallOperator(),
- TSK_ImplicitInstantiation);
- return TreeTransform<TemplateInstantiator>::
- TransformLambdaScope(E, CallOperator);
+ CXXMethodDecl *NewCallOperator,
+ ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes) {
+ CXXMethodDecl *const OldCallOperator = E->getCallOperator();
+ // In the generic lambda case, we set the NewTemplate to be considered
+ // an "instantiation" of the OldTemplate.
+ if (FunctionTemplateDecl *const NewCallOperatorTemplate =
+ NewCallOperator->getDescribedFunctionTemplate()) {
+
+ FunctionTemplateDecl *const OldCallOperatorTemplate =
+ OldCallOperator->getDescribedFunctionTemplate();
+ NewCallOperatorTemplate->setInstantiatedFromMemberTemplate(
+ OldCallOperatorTemplate);
+ // Mark the NewCallOperatorTemplate a specialization.
+ NewCallOperatorTemplate->setMemberSpecialization();
+ } else
+ // For a non-generic lambda we set the NewCallOperator to
+ // be an instantiation of the OldCallOperator.
+ NewCallOperator->setInstantiationOfMemberFunction(OldCallOperator,
+ TSK_ImplicitInstantiation);
+
+ return inherited::TransformLambdaScope(E, NewCallOperator,
+ InitCaptureExprsAndTypes);
+ }
+ TemplateParameterList *TransformTemplateParameterList(
+ TemplateParameterList *OrigTPL) {
+ if (!OrigTPL || !OrigTPL->size()) return OrigTPL;
+
+ DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext();
+ TemplateDeclInstantiator DeclInstantiator(getSema(),
+ /* DeclContext *Owner */ Owner, TemplateArgs);
+ return DeclInstantiator.SubstTemplateParams(OrigTPL);
}
-
private:
ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm,
SourceLocation loc,
@@ -884,6 +967,16 @@ bool TemplateInstantiator::AlreadyTransformed(QualType T) {
return true;
}
+static TemplateArgument
+getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) {
+ assert(S.ArgumentPackSubstitutionIndex >= 0);
+ assert(S.ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
+ Arg = Arg.pack_begin()[S.ArgumentPackSubstitutionIndex];
+ if (Arg.isPackExpansion())
+ Arg = Arg.getPackExpansionPattern();
+ return Arg;
+}
+
Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
if (!D)
return 0;
@@ -903,10 +996,7 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
if (TTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
-
- assert(getSema().ArgumentPackSubstitutionIndex >= 0);
- assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
- Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+ Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
TemplateName Template = Arg.getAsTemplate();
@@ -951,8 +1041,7 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
if (getSema().ArgumentPackSubstitutionIndex == -1)
return 0;
- assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
- Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+ Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
QualType T = Arg.getAsType();
@@ -1054,9 +1143,8 @@ TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS,
// keep the entire argument pack.
return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg);
}
-
- assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
- Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+
+ Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
TemplateName Template = Arg.getAsTemplate();
@@ -1078,11 +1166,9 @@ TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS,
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();
+ TemplateArgument Arg = SubstPack->getArgumentPack();
+ Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ return Arg.getAsTemplate();
}
return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
@@ -1094,25 +1180,7 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
if (!E->isTypeDependent())
return SemaRef.Owned(E);
- FunctionDecl *currentDecl = getSema().getCurFunctionDecl();
- assert(currentDecl && "Must have current function declaration when "
- "instantiating.");
-
- PredefinedExpr::IdentType IT = E->getIdentType();
-
- unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
-
- llvm::APInt LengthI(32, Length + 1);
- QualType ResTy;
- if (IT == PredefinedExpr::LFunction)
- ResTy = getSema().Context.WCharTy.withConst();
- else
- ResTy = getSema().Context.CharTy.withConst();
- ResTy = getSema().Context.getConstantArrayType(ResTy, LengthI,
- ArrayType::Normal, 0);
- PredefinedExpr *PE =
- new (getSema().Context) PredefinedExpr(E->getLocation(), ResTy, IT);
- return getSema().Owned(PE);
+ return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentType());
}
ExprResult
@@ -1147,8 +1215,7 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
Arg);
}
- assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
- Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+ Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
return transformNonTypeTemplateParmRef(NTTP, E->getLocation(), Arg);
@@ -1161,14 +1228,6 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
ExprResult result;
QualType type;
- // If the argument is a pack expansion, the parameter must actually be a
- // parameter pack, and we should substitute the pattern itself, producing
- // an expression which contains an unexpanded parameter pack.
- if (arg.isPackExpansion()) {
- assert(parm->isParameterPack() && "pack expansion for non-pack");
- arg = arg.getPackExpansionPattern();
- }
-
// The template argument itself might be an expression, in which
// case we just return that expression.
if (arg.getKind() == TemplateArgument::Expression) {
@@ -1234,12 +1293,9 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
// We aren't expanding the parameter pack, so just return ourselves.
return getSema().Owned(E);
}
-
- const TemplateArgument &ArgPack = E->getArgumentPack();
- unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex;
- assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
-
- const TemplateArgument &Arg = ArgPack.pack_begin()[Index];
+
+ TemplateArgument Arg = E->getArgumentPack();
+ Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
return transformNonTypeTemplateParmRef(E->getParameterPack(),
E->getParameterPackLocation(),
Arg);
@@ -1410,8 +1466,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
return Result;
}
- assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
- Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+ Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
assert(Arg.getKind() == TemplateArgument::Type &&
@@ -1459,12 +1514,11 @@ TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
NewTL.setNameLoc(TL.getNameLoc());
return TL.getType();
}
-
- const TemplateArgument &ArgPack = TL.getTypePtr()->getArgumentPack();
- unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex;
- assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
-
- QualType Result = ArgPack.pack_begin()[Index].getAsType();
+
+ TemplateArgument Arg = TL.getTypePtr()->getArgumentPack();
+ Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ QualType Result = Arg.getAsType();
+
Result = getSema().Context.getSubstTemplateTypeParmType(
TL.getTypePtr()->getReplacedParameter(),
Result);
@@ -1577,6 +1631,9 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
for (unsigned I = 0, E = FP.getNumArgs(); I != E; ++I) {
ParmVarDecl *P = FP.getArg(I);
+ // This must be synthesized from a typedef.
+ if (!P) continue;
+
// The parameter's type as written might be dependent even if the
// decayed type was not dependent.
if (TypeSourceInfo *TSInfo = P->getTypeSourceInfo())
@@ -1755,6 +1812,10 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end();
Base != BaseEnd; ++Base) {
if (!Base->getType()->isDependentType()) {
+ if (const CXXRecordDecl *RD = Base->getType()->getAsCXXRecordDecl()) {
+ if (RD->isInvalidDecl())
+ Instantiation->setInvalidDecl();
+ }
InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base));
continue;
}
@@ -1949,7 +2010,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
}
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
- if (Inst)
+ if (Inst.isInvalid())
return true;
// Enter the scope of this instantiation. We don't use
@@ -2081,6 +2142,14 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
E = LateAttrs.end(); I != E; ++I) {
assert(CurrentInstantiationScope == Instantiator.getStartingScope());
CurrentInstantiationScope = I->Scope;
+
+ // Allow 'this' within late-parsed attributes.
+ NamedDecl *ND = dyn_cast<NamedDecl>(I->NewDecl);
+ CXXRecordDecl *ThisContext =
+ dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
+ CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0,
+ ND && ND->isCXXInstanceMember());
+
Attr *NewAttr =
instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs);
I->NewDecl->addAttr(NewAttr);
@@ -2104,13 +2173,25 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// Instantiate any out-of-line class template partial
// specializations now.
- for (TemplateDeclInstantiator::delayed_partial_spec_iterator
+ for (TemplateDeclInstantiator::delayed_partial_spec_iterator
P = Instantiator.delayed_partial_spec_begin(),
PEnd = Instantiator.delayed_partial_spec_end();
P != PEnd; ++P) {
if (!Instantiator.InstantiateClassTemplatePartialSpecialization(
- P->first,
- P->second)) {
+ P->first, P->second)) {
+ Instantiation->setInvalidDecl();
+ break;
+ }
+ }
+
+ // Instantiate any out-of-line variable template partial
+ // specializations now.
+ for (TemplateDeclInstantiator::delayed_var_partial_spec_iterator
+ P = Instantiator.delayed_var_partial_spec_begin(),
+ PEnd = Instantiator.delayed_var_partial_spec_end();
+ P != PEnd; ++P) {
+ if (!Instantiator.InstantiateVarTemplatePartialSpecialization(
+ P->first, P->second)) {
Instantiation->setInvalidDecl();
break;
}
@@ -2166,7 +2247,7 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
}
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
- if (Inst)
+ if (Inst.isInvalid())
return true;
// Enter the scope of this instantiation. We don't use
@@ -2198,12 +2279,10 @@ namespace {
};
}
-bool
-Sema::InstantiateClassTemplateSpecialization(
- SourceLocation PointOfInstantiation,
- ClassTemplateSpecializationDecl *ClassTemplateSpec,
- TemplateSpecializationKind TSK,
- bool Complain) {
+bool Sema::InstantiateClassTemplateSpecialization(
+ SourceLocation PointOfInstantiation,
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ TemplateSpecializationKind TSK, bool Complain) {
// Perform the actual instantiation on the canonical declaration.
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
ClassTemplateSpec->getCanonicalDecl());
@@ -2252,15 +2331,18 @@ Sema::InstantiateClassTemplateSpecialization(
SmallVector<MatchResult, 4> Matched;
SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
Template->getPartialSpecializations(PartialSpecs);
+ TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
- TemplateDeductionInfo Info(PointOfInstantiation);
+ TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (TemplateDeductionResult Result
= DeduceTemplateArguments(Partial,
ClassTemplateSpec->getTemplateArgs(),
Info)) {
- // FIXME: Store the failed-deduction information for use in
- // diagnostics, later.
+ // Store the failed-deduction information for use in diagnostics, later.
+ // TODO: Actually use the failed-deduction info?
+ FailedCandidates.addCandidate()
+ .set(Partial, MakeDeductionFailureInfo(Context, Result, Info));
(void)Result;
} else {
Matched.push_back(PartialSpecMatchResult());
@@ -2275,7 +2357,7 @@ Sema::InstantiateClassTemplateSpecialization(
SmallVector<const NamedDecl *, 4> InstantiatedTemplateParameters;
if (Matched.size() >= 1) {
- SmallVector<MatchResult, 4>::iterator Best = Matched.begin();
+ SmallVectorImpl<MatchResult>::iterator Best = Matched.begin();
if (Matched.size() == 1) {
// -- If exactly one matching specialization is found, the
// instantiation is generated from that specialization.
@@ -2288,8 +2370,8 @@ Sema::InstantiateClassTemplateSpecialization(
// specialized than all of the other matching
// specializations, then the use of the class template is
// ambiguous and the program is ill-formed.
- for (SmallVector<MatchResult, 4>::iterator P = Best + 1,
- PEnd = Matched.end();
+ for (SmallVectorImpl<MatchResult>::iterator P = Best + 1,
+ PEnd = Matched.end();
P != PEnd; ++P) {
if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
PointOfInstantiation)
@@ -2300,8 +2382,8 @@ Sema::InstantiateClassTemplateSpecialization(
// Determine if the best partial specialization is more specialized than
// the others.
bool Ambiguous = false;
- for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
- PEnd = Matched.end();
+ for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
+ PEnd = Matched.end();
P != PEnd; ++P) {
if (P != Best &&
getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
@@ -2319,8 +2401,8 @@ Sema::InstantiateClassTemplateSpecialization(
<< ClassTemplateSpec;
// Print the matching partial specializations.
- for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
- PEnd = Matched.end();
+ for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
+ PEnd = Matched.end();
P != PEnd; ++P)
Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
<< getTemplateArgumentBindingsText(
@@ -2377,6 +2459,11 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation,
const MultiLevelTemplateArgumentList &TemplateArgs,
TemplateSpecializationKind TSK) {
+ assert(
+ (TSK == TSK_ExplicitInstantiationDefinition ||
+ TSK == TSK_ExplicitInstantiationDeclaration ||
+ (TSK == TSK_ImplicitInstantiation && Instantiation->isLocalClass())) &&
+ "Unexpected template specialization kind!");
for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
DEnd = Instantiation->decls_end();
D != DEnd; ++D) {
@@ -2417,9 +2504,15 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
InstantiateFunctionDefinition(PointOfInstantiation, Function);
} else {
Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ if (TSK == TSK_ImplicitInstantiation)
+ PendingLocalImplicitInstantiations.push_back(
+ std::make_pair(Function, PointOfInstantiation));
}
}
} else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
+ if (isa<VarTemplateSpecializationDecl>(Var))
+ continue;
+
if (Var->isStaticDataMember()) {
MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
assert(MSInfo && "No member specialization information?");
@@ -2689,6 +2782,12 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
break;
}
+ // If we're performing a partial substitution during template argument
+ // deduction, we may not have values for template parameters yet.
+ if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
+ isa<TemplateTemplateParmDecl>(D))
+ return 0;
+
// If we didn't find the decl, then we either have a sema bug, or we have a
// forward reference to a label declaration. Return null to indicate that
// we have an uninstantiated label.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index d1428c51a4f9..5c28e3b7a828 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -25,6 +25,17 @@
using namespace clang;
+static bool isDeclWithinFunction(const Decl *D) {
+ const DeclContext *DC = D->getDeclContext();
+ if (DC->isFunctionOrMethod())
+ return true;
+
+ if (DC->isRecord())
+ return cast<CXXRecordDecl>(DC)->isLocalClass();
+
+ return false;
+}
+
bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl,
DeclaratorDecl *NewDecl) {
if (!OldDecl->getQualifierLoc())
@@ -142,6 +153,13 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope);
LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New));
} else {
+ // Allow 'this' within late-parsed attributes.
+ NamedDecl *ND = dyn_cast<NamedDecl>(New);
+ CXXRecordDecl *ThisContext =
+ dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
+ CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0,
+ ND && ND->isCXXInstanceMember());
+
Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,
*this, TemplateArgs);
if (NewAttr)
@@ -247,7 +265,7 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
// If the typedef types are not identical, reject them.
SemaRef.isIncompatibleTypedef(InstPrevTypedef, Typedef);
- Typedef->setPreviousDeclaration(InstPrevTypedef);
+ Typedef->setPreviousDecl(InstPrevTypedef);
}
SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef);
@@ -299,7 +317,7 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
= TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(),
D->getDeclName(), InstParams, AliasInst);
if (PrevAliasTemplate)
- Inst->setPreviousDeclaration(PrevAliasTemplate);
+ Inst->setPreviousDecl(PrevAliasTemplate);
Inst->setAccess(D->getAccess());
@@ -312,6 +330,12 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
}
Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
+ return VisitVarDecl(D, /*InstantiatingVarTemplate=*/false);
+}
+
+Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
+ bool InstantiatingVarTemplate) {
+
// If this is the variable for an anonymous struct or union,
// instantiate the anonymous struct/union type first.
if (const RecordType *RecordTy = D->getType()->getAs<RecordType>())
@@ -333,105 +357,26 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
return 0;
}
- // Build the instantiated declaration
- VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner,
- D->getInnerLocStart(),
- D->getLocation(), D->getIdentifier(),
- DI->getType(), DI,
- D->getStorageClass());
- Var->setTSCSpec(D->getTSCSpec());
- Var->setInitStyle(D->getInitStyle());
- Var->setCXXForRangeDecl(D->isCXXForRangeDecl());
- Var->setConstexpr(D->isConstexpr());
-
- // Substitute the nested name specifier, if any.
- if (SubstQualifier(D, Var))
- return 0;
-
- // If we are instantiating a static data member defined
- // out-of-line, the instantiation will have the same lexical
- // context (which will be a namespace scope) as the template.
- if (D->isOutOfLine())
- Var->setLexicalDeclContext(D->getLexicalDeclContext());
-
- Var->setAccess(D->getAccess());
-
- if (!D->isStaticDataMember()) {
- Var->setUsed(D->isUsed(false));
- Var->setReferenced(D->isReferenced());
- }
-
- SemaRef.InstantiateAttrs(TemplateArgs, D, Var, LateAttrs, StartingScope);
+ DeclContext *DC = Owner;
+ if (D->isLocalExternDecl())
+ SemaRef.adjustContextForLocalExternDecl(DC);
- if (Var->hasAttrs())
- SemaRef.CheckAlignasUnderalignment(Var);
+ // Build the instantiated declaration.
+ VarDecl *Var = VarDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
+ D->getLocation(), D->getIdentifier(),
+ DI->getType(), DI, D->getStorageClass());
- // FIXME: In theory, we could have a previous declaration for variables that
- // are not static data members.
- // FIXME: having to fake up a LookupResult is dumb.
- LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(),
- Sema::LookupOrdinaryName, Sema::ForRedeclaration);
- if (D->isStaticDataMember())
- SemaRef.LookupQualifiedName(Previous, Owner, false);
-
// In ARC, infer 'retaining' for variables of retainable type.
if (SemaRef.getLangOpts().ObjCAutoRefCount &&
SemaRef.inferObjCARCLifetime(Var))
Var->setInvalidDecl();
- SemaRef.CheckVariableDeclaration(Var, Previous);
-
- if (D->isOutOfLine()) {
- D->getLexicalDeclContext()->addDecl(Var);
- Owner->makeDeclVisibleInContext(Var);
- } else {
- Owner->addDecl(Var);
- if (Owner->isFunctionOrMethod())
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var);
- }
-
- // Link instantiations of static data members back to the template from
- // which they were instantiated.
- if (Var->isStaticDataMember())
- SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D,
- TSK_ImplicitInstantiation);
-
- if (Var->getAnyInitializer()) {
- // We already have an initializer in the class.
- } else if (D->getInit()) {
- if (Var->isStaticDataMember() && !D->isOutOfLine())
- SemaRef.PushExpressionEvaluationContext(Sema::ConstantEvaluated, D);
- else
- SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated, D);
-
- // Instantiate the initializer.
- ExprResult Init = SemaRef.SubstInitializer(D->getInit(), TemplateArgs,
- D->getInitStyle() == VarDecl::CallInit);
- if (!Init.isInvalid()) {
- bool TypeMayContainAuto = true;
- if (Init.get()) {
- bool DirectInit = D->isDirectInit();
- SemaRef.AddInitializerToDecl(Var, Init.take(), DirectInit,
- TypeMayContainAuto);
- } else
- SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto);
- } else {
- // FIXME: Not too happy about invalidating the declaration
- // because of a bogus initializer.
- Var->setInvalidDecl();
- }
-
- SemaRef.PopExpressionEvaluationContext();
- } else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) &&
- !Var->isCXXForRangeDecl())
- SemaRef.ActOnUninitializedDecl(Var, false);
-
- // Diagnose unused local variables with dependent types, where the diagnostic
- // will have been deferred.
- if (!Var->isInvalidDecl() && Owner->isFunctionOrMethod() && !Var->isUsed() &&
- D->getType()->isDependentType())
- SemaRef.DiagnoseUnusedDecl(Var);
+ // Substitute the nested name specifier, if any.
+ if (SubstQualifier(D, Var))
+ return 0;
+ SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner,
+ StartingScope, InstantiatingVarTemplate);
return Var;
}
@@ -723,19 +668,17 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
}
}
- if (D->getDeclContext()->isFunctionOrMethod())
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum);
-
// C++11 [temp.inst]p1: The implicit instantiation of a class template
// specialization causes the implicit instantiation of the declarations, but
// not the definitions of scoped member enumerations.
- // FIXME: There appears to be no wording for what happens for an enum defined
- // within a block scope, but we treat that much like a member template. Only
- // instantiate the definition when visiting the definition in that case, since
- // we will visit all redeclarations.
- if (!Enum->isScoped() && Def &&
- (!D->getDeclContext()->isFunctionOrMethod() || D->isCompleteDefinition()))
+ //
+ // DR1484 clarifies that enumeration definitions inside of a template
+ // declaration aren't considered entities that can be separately instantiated
+ // from the rest of the entity they are declared inside of.
+ if (isDeclWithinFunction(D) ? D == Def : Def && !Enum->isScoped()) {
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum);
InstantiateEnumDefinition(Enum, Def);
+ }
return Enum;
}
@@ -953,7 +896,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
else
Inst->setAccess(D->getAccess());
- Inst->setObjectOfFriendDecl(PrevClassTemplate != 0);
+ Inst->setObjectOfFriendDecl();
// TODO: do we want to track the instantiation progeny of this
// friend target decl?
} else {
@@ -988,7 +931,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
D->getPartialSpecializations(PartialSpecs);
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
- if (PartialSpecs[I]->isOutOfLine())
+ if (PartialSpecs[I]->getFirstDecl()->isOutOfLine())
OutOfLinePartialSpecs.push_back(std::make_pair(Inst, PartialSpecs[I]));
}
@@ -1019,6 +962,85 @@ TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl(
return InstantiateClassTemplatePartialSpecialization(InstClassTemplate, D);
}
+Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) {
+ assert(D->getTemplatedDecl()->isStaticDataMember() &&
+ "Only static data member templates are allowed.");
+
+ // Create a local instantiation scope for this variable template, which
+ // will contain the instantiations of the template parameters.
+ LocalInstantiationScope Scope(SemaRef);
+ TemplateParameterList *TempParams = D->getTemplateParameters();
+ TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+ if (!InstParams)
+ return NULL;
+
+ VarDecl *Pattern = D->getTemplatedDecl();
+ VarTemplateDecl *PrevVarTemplate = 0;
+
+ if (Pattern->getPreviousDecl()) {
+ DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
+ if (!Found.empty())
+ PrevVarTemplate = dyn_cast<VarTemplateDecl>(Found.front());
+ }
+
+ VarDecl *VarInst =
+ cast_or_null<VarDecl>(VisitVarDecl(Pattern,
+ /*InstantiatingVarTemplate=*/true));
+
+ DeclContext *DC = Owner;
+
+ VarTemplateDecl *Inst = VarTemplateDecl::Create(
+ SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams,
+ VarInst, PrevVarTemplate);
+ VarInst->setDescribedVarTemplate(Inst);
+
+ Inst->setAccess(D->getAccess());
+ if (!PrevVarTemplate)
+ Inst->setInstantiatedFromMemberTemplate(D);
+
+ if (D->isOutOfLine()) {
+ Inst->setLexicalDeclContext(D->getLexicalDeclContext());
+ VarInst->setLexicalDeclContext(D->getLexicalDeclContext());
+ }
+
+ Owner->addDecl(Inst);
+
+ if (!PrevVarTemplate) {
+ // Queue up any out-of-line partial specializations of this member
+ // variable template; the client will force their instantiation once
+ // the enclosing class has been instantiated.
+ SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+ D->getPartialSpecializations(PartialSpecs);
+ for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
+ if (PartialSpecs[I]->getFirstDecl()->isOutOfLine())
+ OutOfLineVarPartialSpecs.push_back(
+ std::make_pair(Inst, PartialSpecs[I]));
+ }
+
+ return Inst;
+}
+
+Decl *TemplateDeclInstantiator::VisitVarTemplatePartialSpecializationDecl(
+ VarTemplatePartialSpecializationDecl *D) {
+ assert(D->isStaticDataMember() &&
+ "Only static data member templates are allowed.");
+
+ VarTemplateDecl *VarTemplate = D->getSpecializedTemplate();
+
+ // Lookup the already-instantiated declaration and return that.
+ DeclContext::lookup_result Found = Owner->lookup(VarTemplate->getDeclName());
+ assert(!Found.empty() && "Instantiation found nothing?");
+
+ VarTemplateDecl *InstVarTemplate = dyn_cast<VarTemplateDecl>(Found.front());
+ assert(InstVarTemplate && "Instantiation did not find a variable template?");
+
+ if (VarTemplatePartialSpecializationDecl *Result =
+ InstVarTemplate->findPartialSpecInstantiatedFromMember(D))
+ return Result;
+
+ return InstantiateVarTemplatePartialSpecialization(InstVarTemplate, D);
+}
+
Decl *
TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
// Create a local instantiation scope for this function template, which
@@ -1103,17 +1125,30 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
// If the original function was part of a friend declaration,
// inherit its namespace state.
- if (Decl::FriendObjectKind FOK = D->getFriendObjectKind())
- Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared);
+ if (D->getFriendObjectKind())
+ Record->setObjectOfFriendDecl();
// Make sure that anonymous structs and unions are recorded.
- if (D->isAnonymousStructOrUnion()) {
+ if (D->isAnonymousStructOrUnion())
Record->setAnonymousStructOrUnion(true);
- if (Record->getDeclContext()->getRedeclContext()->isFunctionOrMethod())
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record);
- }
+
+ if (D->isLocalClass())
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record);
Owner->addDecl(Record);
+
+ // DR1484 clarifies that the members of a local class are instantiated as part
+ // of the instantiation of their enclosing entity.
+ if (D->isCompleteDefinition() && D->isLocalClass()) {
+ if (SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs,
+ TSK_ImplicitInstantiation,
+ /*Complain=*/true)) {
+ llvm_unreachable("InstantiateClass shouldn't fail here!");
+ } else {
+ SemaRef.InstantiateClassMembers(D->getLocation(), Record, TemplateArgs,
+ TSK_ImplicitInstantiation);
+ }
+ }
return Record;
}
@@ -1136,9 +1171,7 @@ static QualType adjustFunctionTypeForInstantiation(ASTContext &Context,
FunctionProtoType::ExtProtoInfo NewEPI = NewFunc->getExtProtoInfo();
NewEPI.ExtInfo = OrigFunc->getExtInfo();
return Context.getFunctionType(NewFunc->getResultType(),
- ArrayRef<QualType>(NewFunc->arg_type_begin(),
- NewFunc->getNumArgs()),
- NewEPI);
+ NewFunc->getArgTypes(), NewEPI);
}
/// Normal class members are of more specific types and therefore
@@ -1191,11 +1224,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
}
// If we're instantiating a local function declaration, put the result
- // in the owner; otherwise we need to find the instantiated context.
+ // in the enclosing namespace; otherwise we need to find the instantiated
+ // context.
DeclContext *DC;
- if (D->getDeclContext()->isFunctionOrMethod())
+ if (D->isLocalExternDecl()) {
DC = Owner;
- else if (isFriend && QualifierLoc) {
+ SemaRef.adjustContextForLocalExternDecl(DC);
+ } else if (isFriend && QualifierLoc) {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
DC = SemaRef.computeDeclContext(SS);
@@ -1211,6 +1246,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
D->getCanonicalDecl()->getStorageClass(),
D->isInlineSpecified(), D->hasWrittenPrototype(),
D->isConstexpr());
+ Function->setRangeEnd(D->getSourceRange().getEnd());
if (D->isInlined())
Function->setImplicitlyInline();
@@ -1218,8 +1254,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
if (QualifierLoc)
Function->setQualifierInfo(QualifierLoc);
+ if (D->isLocalExternDecl())
+ Function->setLocalExternDecl();
+
DeclContext *LexicalDC = Owner;
- if (!isFriend && D->isOutOfLine()) {
+ if (!isFriend && D->isOutOfLine() && !D->isLocalExternDecl()) {
assert(D->getDeclContext()->isFileContext());
LexicalDC = D->getDeclContext();
}
@@ -1227,26 +1266,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
Function->setLexicalDeclContext(LexicalDC);
// Attach the parameters
- if (isa<FunctionProtoType>(Function->getType().IgnoreParens())) {
- // Adopt the already-instantiated parameters into our own context.
- for (unsigned P = 0; P < Params.size(); ++P)
- if (Params[P])
- Params[P]->setOwningFunction(Function);
- } else {
- // Since we were instantiated via a typedef of a function type, create
- // new parameters.
- const FunctionProtoType *Proto
- = Function->getType()->getAs<FunctionProtoType>();
- assert(Proto && "No function prototype in template instantiation?");
- for (FunctionProtoType::arg_type_iterator AI = Proto->arg_type_begin(),
- AE = Proto->arg_type_end(); AI != AE; ++AI) {
- ParmVarDecl *Param
- = SemaRef.BuildParmVarDeclForTypedef(Function, Function->getLocation(),
- *AI);
- Param->setScopeInfo(0, Params.size());
- Params.push_back(Param);
- }
- }
+ for (unsigned P = 0; P < Params.size(); ++P)
+ if (Params[P])
+ Params[P]->setOwningFunction(Function);
Function->setParams(Params);
SourceLocation InstantiateAtPOI;
@@ -1302,15 +1324,18 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
bool isExplicitSpecialization = false;
- LookupResult Previous(SemaRef, Function->getDeclName(), SourceLocation(),
- Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ LookupResult Previous(
+ SemaRef, Function->getDeclName(), SourceLocation(),
+ D->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage
+ : Sema::LookupOrdinaryName,
+ Sema::ForRedeclaration);
if (DependentFunctionTemplateSpecializationInfo *Info
= D->getDependentSpecializationInfo()) {
assert(isFriend && "non-friend has dependent specialization info?");
// This needs to be set now for future sanity.
- Function->setObjectOfFriendDecl(/*HasPrevious*/ true);
+ Function->setObjectOfFriendDecl();
// Instantiate the explicit template arguments.
TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
@@ -1360,13 +1385,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
// If the original function was part of a friend declaration,
// inherit its namespace state and add it to the owner.
if (isFriend) {
- NamedDecl *PrevDecl;
- if (TemplateParams)
- PrevDecl = FunctionTemplate->getPreviousDecl();
- else
- PrevDecl = Function->getPreviousDecl();
-
- PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0);
+ PrincipalDecl->setObjectOfFriendDecl();
DC->makeDeclVisibleInContext(PrincipalDecl);
bool queuedInstantiation = false;
@@ -1441,6 +1460,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
}
}
+ if (Function->isLocalExternDecl() && !Function->getPreviousDecl())
+ DC->makeDeclVisibleInContext(PrincipalDecl);
+
if (Function->isOverloadedOperator() && !DC->isRecord() &&
PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
PrincipalDecl->setNonMemberOperator();
@@ -1502,24 +1524,6 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
return 0;
QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo);
- // \brief If the type of this function, after ignoring parentheses,
- // is not *directly* a function type, then we're instantiating a function
- // that was declared via a typedef, e.g.,
- //
- // typedef int functype(int, int);
- // functype func;
- //
- // In this case, we'll just go instantiate the ParmVarDecls that we
- // synthesized in the method declaration.
- if (!isa<FunctionProtoType>(T.IgnoreParens())) {
- assert(!Params.size() && "Instantiating type could not yield parameters");
- SmallVector<QualType, 4> ParamTypes;
- if (SemaRef.SubstParmTypes(D->getLocation(), D->param_begin(),
- D->getNumParams(), TemplateArgs, ParamTypes,
- &Params))
- return 0;
- }
-
NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
if (QualifierLoc) {
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
@@ -1572,7 +1576,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
"inheriting constructor template in dependent context?");
Sema::InstantiatingTemplate Inst(SemaRef, Constructor->getLocation(),
Inh);
- if (Inst)
+ if (Inst.isInvalid())
return 0;
Sema::ContextRAII SavedContext(SemaRef, Inh->getDeclContext());
LocalInstantiationScope LocalScope(SemaRef);
@@ -1634,7 +1638,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
TemplateParams, Method);
if (isFriend) {
FunctionTemplate->setLexicalDeclContext(Owner);
- FunctionTemplate->setObjectOfFriendDecl(true);
+ FunctionTemplate->setObjectOfFriendDecl();
} else if (D->isOutOfLine())
FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
Method->setDescribedFunctionTemplate(FunctionTemplate);
@@ -1661,7 +1665,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
TempParamLists.data());
Method->setLexicalDeclContext(Owner);
- Method->setObjectOfFriendDecl(true);
+ Method->setObjectOfFriendDecl();
} else if (D->isOutOfLine())
Method->setLexicalDeclContext(D->getLexicalDeclContext());
@@ -1750,7 +1754,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
return VisitCXXMethodDecl(D);
}
-ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
+Decl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, None,
/*ExpectParameterPack=*/ false);
}
@@ -1769,8 +1773,13 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
D->isParameterPack());
Inst->setAccess(AS_public);
- if (D->hasDefaultArgument())
- Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false);
+ if (D->hasDefaultArgument()) {
+ TypeSourceInfo *InstantiatedDefaultArg =
+ SemaRef.SubstType(D->getDefaultArgumentInfo(), TemplateArgs,
+ D->getDefaultArgumentLoc(), D->getDeclName());
+ if (InstantiatedDefaultArg)
+ Inst->setDefaultArgument(InstantiatedDefaultArg, false);
+ }
// Introduce this template parameter's instantiation into the instantiation
// scope.
@@ -1920,7 +1929,11 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
if (Invalid)
Param->setInvalidDecl();
- Param->setDefaultArgument(D->getDefaultArgument(), false);
+ if (D->hasDefaultArgument()) {
+ ExprResult Value = SemaRef.SubstExpr(D->getDefaultArgument(), TemplateArgs);
+ if (!Value.isInvalid())
+ Param->setDefaultArgument(Value.get(), false);
+ }
// Introduce this template parameter's instantiation into the instantiation
// scope.
@@ -2043,7 +2056,21 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
D->getPosition(),
D->isParameterPack(),
D->getIdentifier(), InstParams);
- Param->setDefaultArgument(D->getDefaultArgument(), false);
+ if (D->hasDefaultArgument()) {
+ NestedNameSpecifierLoc QualifierLoc =
+ D->getDefaultArgument().getTemplateQualifierLoc();
+ QualifierLoc =
+ SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs);
+ TemplateName TName = SemaRef.SubstTemplateName(
+ QualifierLoc, D->getDefaultArgument().getArgument().getAsTemplate(),
+ D->getDefaultArgument().getTemplateNameLoc(), TemplateArgs);
+ if (!TName.isNull())
+ Param->setDefaultArgument(
+ TemplateArgumentLoc(TemplateArgument(TName),
+ D->getDefaultArgument().getTemplateQualifierLoc(),
+ D->getDefaultArgument().getTemplateNameLoc()),
+ false);
+ }
Param->setAccess(AS_public);
// Introduce this template parameter's instantiation into the instantiation
@@ -2102,10 +2129,10 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
Sema::ForRedeclaration);
UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
- D->getUsingLocation(),
+ D->getUsingLoc(),
QualifierLoc,
NameInfo,
- D->isTypeName());
+ D->hasTypename());
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
@@ -2114,15 +2141,15 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
SemaRef.LookupQualifiedName(Prev, Owner);
// Check for invalid redeclarations.
- if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLocation(),
- D->isTypeName(), SS,
+ if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLoc(),
+ D->hasTypename(), SS,
D->getLocation(), Prev))
NewUD->setInvalidDecl();
}
if (!NewUD->isInvalidDecl() &&
- SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
+ SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), SS,
D->getLocation()))
NewUD->setInvalidDecl();
@@ -2147,19 +2174,22 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
I != E; ++I) {
UsingShadowDecl *Shadow = *I;
NamedDecl *InstTarget =
- cast_or_null<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))
- continue;
+ UsingShadowDecl *PrevDecl = 0;
+ if (CheckRedeclaration) {
+ if (SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev, PrevDecl))
+ continue;
+ } else if (UsingShadowDecl *OldPrev = Shadow->getPreviousDecl()) {
+ PrevDecl = cast_or_null<UsingShadowDecl>(SemaRef.FindInstantiatedDecl(
+ Shadow->getLocation(), OldPrev, TemplateArgs));
+ }
- UsingShadowDecl *InstShadow
- = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget);
+ UsingShadowDecl *InstShadow =
+ SemaRef.BuildUsingShadowDecl(/*Scope*/0, NewUD, InstTarget, PrevDecl);
SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
if (isFunctionScope)
@@ -2257,13 +2287,13 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
OMPThreadPrivateDecl *D) {
- SmallVector<DeclRefExpr *, 5> Vars;
- for (ArrayRef<DeclRefExpr *>::iterator I = D->varlist_begin(),
- E = D->varlist_end();
+ SmallVector<Expr *, 5> Vars;
+ for (ArrayRef<Expr *>::iterator I = D->varlist_begin(),
+ E = D->varlist_end();
I != E; ++I) {
Expr *Var = SemaRef.SubstExpr(*I, TemplateArgs).take();
assert(isa<DeclRefExpr>(Var) && "threadprivate arg is not a DeclRefExpr");
- Vars.push_back(cast<DeclRefExpr>(Var));
+ Vars.push_back(Var);
}
OMPThreadPrivateDecl *TD =
@@ -2272,6 +2302,262 @@ Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
return TD;
}
+Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
+ return VisitFunctionDecl(D, 0);
+}
+
+Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
+ return VisitCXXMethodDecl(D, 0);
+}
+
+Decl *TemplateDeclInstantiator::VisitRecordDecl(RecordDecl *D) {
+ llvm_unreachable("There are only CXXRecordDecls in C++");
+}
+
+Decl *
+TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D) {
+ // As a MS extension, we permit class-scope explicit specialization
+ // of member class templates.
+ ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate();
+ assert(ClassTemplate->getDeclContext()->isRecord() &&
+ D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization &&
+ "can only instantiate an explicit specialization "
+ "for a member class template");
+
+ // Lookup the already-instantiated declaration in the instantiation
+ // of the class template. FIXME: Diagnose or assert if this fails?
+ DeclContext::lookup_result Found
+ = Owner->lookup(ClassTemplate->getDeclName());
+ if (Found.empty())
+ return 0;
+ ClassTemplateDecl *InstClassTemplate
+ = dyn_cast<ClassTemplateDecl>(Found.front());
+ if (!InstClassTemplate)
+ return 0;
+
+ // Substitute into the template arguments of the class template explicit
+ // specialization.
+ TemplateSpecializationTypeLoc Loc = D->getTypeAsWritten()->getTypeLoc().
+ castAs<TemplateSpecializationTypeLoc>();
+ TemplateArgumentListInfo InstTemplateArgs(Loc.getLAngleLoc(),
+ Loc.getRAngleLoc());
+ SmallVector<TemplateArgumentLoc, 4> ArgLocs;
+ for (unsigned I = 0; I != Loc.getNumArgs(); ++I)
+ ArgLocs.push_back(Loc.getArgLoc(I));
+ if (SemaRef.Subst(ArgLocs.data(), ArgLocs.size(),
+ InstTemplateArgs, TemplateArgs))
+ return 0;
+
+ // Check that the template argument list is well-formed for this
+ // class template.
+ SmallVector<TemplateArgument, 4> Converted;
+ if (SemaRef.CheckTemplateArgumentList(InstClassTemplate,
+ D->getLocation(),
+ InstTemplateArgs,
+ false,
+ Converted))
+ return 0;
+
+ // Figure out where to insert this class template explicit specialization
+ // in the member template's set of class template explicit specializations.
+ void *InsertPos = 0;
+ ClassTemplateSpecializationDecl *PrevDecl =
+ InstClassTemplate->findSpecialization(Converted.data(), Converted.size(),
+ InsertPos);
+
+ // Check whether we've already seen a conflicting instantiation of this
+ // declaration (for instance, if there was a prior implicit instantiation).
+ bool Ignored;
+ if (PrevDecl &&
+ SemaRef.CheckSpecializationInstantiationRedecl(D->getLocation(),
+ D->getSpecializationKind(),
+ PrevDecl,
+ PrevDecl->getSpecializationKind(),
+ PrevDecl->getPointOfInstantiation(),
+ Ignored))
+ return 0;
+
+ // If PrevDecl was a definition and D is also a definition, diagnose.
+ // This happens in cases like:
+ //
+ // template<typename T, typename U>
+ // struct Outer {
+ // template<typename X> struct Inner;
+ // template<> struct Inner<T> {};
+ // template<> struct Inner<U> {};
+ // };
+ //
+ // Outer<int, int> outer; // error: the explicit specializations of Inner
+ // // have the same signature.
+ if (PrevDecl && PrevDecl->getDefinition() &&
+ D->isThisDeclarationADefinition()) {
+ SemaRef.Diag(D->getLocation(), diag::err_redefinition) << PrevDecl;
+ SemaRef.Diag(PrevDecl->getDefinition()->getLocation(),
+ diag::note_previous_definition);
+ return 0;
+ }
+
+ // Create the class template partial specialization declaration.
+ ClassTemplateSpecializationDecl *InstD
+ = ClassTemplateSpecializationDecl::Create(SemaRef.Context,
+ D->getTagKind(),
+ Owner,
+ D->getLocStart(),
+ D->getLocation(),
+ InstClassTemplate,
+ Converted.data(),
+ Converted.size(),
+ PrevDecl);
+
+ // Add this partial specialization to the set of class template partial
+ // specializations.
+ if (!PrevDecl)
+ InstClassTemplate->AddSpecialization(InstD, InsertPos);
+
+ // Substitute the nested name specifier, if any.
+ if (SubstQualifier(D, InstD))
+ return 0;
+
+ // Build the canonical type that describes the converted template
+ // arguments of the class template explicit specialization.
+ QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
+ TemplateName(InstClassTemplate), Converted.data(), Converted.size(),
+ SemaRef.Context.getRecordType(InstD));
+
+ // Build the fully-sugared type for this class template
+ // specialization as the user wrote in the specialization
+ // itself. This means that we'll pretty-print the type retrieved
+ // from the specialization's declaration the way that the user
+ // actually wrote the specialization, rather than formatting the
+ // name based on the "canonical" representation used to store the
+ // template arguments in the specialization.
+ TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo(
+ TemplateName(InstClassTemplate), D->getLocation(), InstTemplateArgs,
+ CanonType);
+
+ InstD->setAccess(D->getAccess());
+ InstD->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation);
+ InstD->setSpecializationKind(D->getSpecializationKind());
+ InstD->setTypeAsWritten(WrittenTy);
+ InstD->setExternLoc(D->getExternLoc());
+ InstD->setTemplateKeywordLoc(D->getTemplateKeywordLoc());
+
+ Owner->addDecl(InstD);
+
+ // Instantiate the members of the class-scope explicit specialization eagerly.
+ // We don't have support for lazy instantiation of an explicit specialization
+ // yet, and MSVC eagerly instantiates in this case.
+ if (D->isThisDeclarationADefinition() &&
+ SemaRef.InstantiateClass(D->getLocation(), InstD, D, TemplateArgs,
+ TSK_ImplicitInstantiation,
+ /*Complain=*/true))
+ return 0;
+
+ return InstD;
+}
+
+Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
+ VarTemplateSpecializationDecl *D) {
+
+ TemplateArgumentListInfo VarTemplateArgsInfo;
+ VarTemplateDecl *VarTemplate = D->getSpecializedTemplate();
+ assert(VarTemplate &&
+ "A template specialization without specialized template?");
+
+ // Substitute the current template arguments.
+ const TemplateArgumentListInfo &TemplateArgsInfo = D->getTemplateArgsInfo();
+ VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo.getLAngleLoc());
+ VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo.getRAngleLoc());
+
+ if (SemaRef.Subst(TemplateArgsInfo.getArgumentArray(),
+ TemplateArgsInfo.size(), VarTemplateArgsInfo, TemplateArgs))
+ return 0;
+
+ // Check that the template argument list is well-formed for this template.
+ SmallVector<TemplateArgument, 4> Converted;
+ bool ExpansionIntoFixedList = false;
+ if (SemaRef.CheckTemplateArgumentList(
+ VarTemplate, VarTemplate->getLocStart(),
+ const_cast<TemplateArgumentListInfo &>(VarTemplateArgsInfo), false,
+ Converted, &ExpansionIntoFixedList))
+ return 0;
+
+ // Find the variable template specialization declaration that
+ // corresponds to these arguments.
+ void *InsertPos = 0;
+ if (VarTemplateSpecializationDecl *VarSpec = VarTemplate->findSpecialization(
+ Converted.data(), Converted.size(), InsertPos))
+ // If we already have a variable template specialization, return it.
+ return VarSpec;
+
+ return VisitVarTemplateSpecializationDecl(VarTemplate, D, InsertPos,
+ VarTemplateArgsInfo, Converted);
+}
+
+Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
+ VarTemplateDecl *VarTemplate, VarDecl *D, void *InsertPos,
+ const TemplateArgumentListInfo &TemplateArgsInfo,
+ llvm::ArrayRef<TemplateArgument> Converted) {
+
+ // If this is the variable for an anonymous struct or union,
+ // instantiate the anonymous struct/union type first.
+ if (const RecordType *RecordTy = D->getType()->getAs<RecordType>())
+ if (RecordTy->getDecl()->isAnonymousStructOrUnion())
+ if (!VisitCXXRecordDecl(cast<CXXRecordDecl>(RecordTy->getDecl())))
+ return 0;
+
+ // Do substitution on the type of the declaration
+ TypeSourceInfo *DI =
+ SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs,
+ D->getTypeSpecStartLoc(), D->getDeclName());
+ if (!DI)
+ return 0;
+
+ if (DI->getType()->isFunctionType()) {
+ SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function)
+ << D->isStaticDataMember() << DI->getType();
+ return 0;
+ }
+
+ // Build the instantiated declaration
+ VarTemplateSpecializationDecl *Var = VarTemplateSpecializationDecl::Create(
+ SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(),
+ VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted.data(),
+ Converted.size());
+ Var->setTemplateArgsInfo(TemplateArgsInfo);
+ if (InsertPos)
+ VarTemplate->AddSpecialization(Var, InsertPos);
+
+ // Substitute the nested name specifier, if any.
+ if (SubstQualifier(D, Var))
+ return 0;
+
+ SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs,
+ Owner, StartingScope);
+
+ return Var;
+}
+
+Decl *TemplateDeclInstantiator::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) {
+ llvm_unreachable("@defs is not supported in Objective-C++");
+}
+
+Decl *TemplateDeclInstantiator::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
+ // FIXME: We need to be able to instantiate FriendTemplateDecls.
+ unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "cannot instantiate %0 yet");
+ SemaRef.Diag(D->getLocation(), DiagID)
+ << D->getDeclKindName();
+
+ return 0;
+}
+
+Decl *TemplateDeclInstantiator::VisitDecl(Decl *D) {
+ llvm_unreachable("Unexpected decl");
+}
+
Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
@@ -2343,9 +2629,12 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
// Substitute into the template arguments of the class template partial
// specialization.
- TemplateArgumentListInfo InstTemplateArgs; // no angle locations
- if (SemaRef.Subst(PartialSpec->getTemplateArgsAsWritten(),
- PartialSpec->getNumTemplateArgsAsWritten(),
+ const ASTTemplateArgumentListInfo *TemplArgInfo
+ = PartialSpec->getTemplateArgsAsWritten();
+ TemplateArgumentListInfo InstTemplateArgs(TemplArgInfo->LAngleLoc,
+ TemplArgInfo->RAngleLoc);
+ if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(),
+ TemplArgInfo->NumTemplateArgs,
InstTemplateArgs, TemplateArgs))
return 0;
@@ -2424,8 +2713,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
Converted.size(),
InstTemplateArgs,
CanonType,
- 0,
- ClassTemplate->getNextPartialSpecSequenceNumber());
+ 0);
// Substitute the nested name specifier, if any.
if (SubstQualifier(PartialSpec, InstPartialSpec))
return 0;
@@ -2439,6 +2727,137 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
return InstPartialSpec;
}
+/// \brief Instantiate the declaration of a variable template partial
+/// specialization.
+///
+/// \param VarTemplate the (instantiated) variable template that is partially
+/// specialized by the instantiation of \p PartialSpec.
+///
+/// \param PartialSpec the (uninstantiated) variable template partial
+/// specialization that we are instantiating.
+///
+/// \returns The instantiated partial specialization, if successful; otherwise,
+/// NULL to indicate an error.
+VarTemplatePartialSpecializationDecl *
+TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
+ VarTemplateDecl *VarTemplate,
+ VarTemplatePartialSpecializationDecl *PartialSpec) {
+ // Create a local instantiation scope for this variable template partial
+ // specialization, which will contain the instantiations of the template
+ // parameters.
+ LocalInstantiationScope Scope(SemaRef);
+
+ // Substitute into the template parameters of the variable template partial
+ // specialization.
+ TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
+ TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+ if (!InstParams)
+ return 0;
+
+ // Substitute into the template arguments of the variable template partial
+ // specialization.
+ const ASTTemplateArgumentListInfo *TemplArgInfo
+ = PartialSpec->getTemplateArgsAsWritten();
+ TemplateArgumentListInfo InstTemplateArgs(TemplArgInfo->LAngleLoc,
+ TemplArgInfo->RAngleLoc);
+ if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(),
+ TemplArgInfo->NumTemplateArgs,
+ InstTemplateArgs, TemplateArgs))
+ return 0;
+
+ // Check that the template argument list is well-formed for this
+ // class template.
+ SmallVector<TemplateArgument, 4> Converted;
+ if (SemaRef.CheckTemplateArgumentList(VarTemplate, PartialSpec->getLocation(),
+ InstTemplateArgs, false, Converted))
+ return 0;
+
+ // Figure out where to insert this variable template partial specialization
+ // in the member template's set of variable template partial specializations.
+ void *InsertPos = 0;
+ VarTemplateSpecializationDecl *PrevDecl =
+ VarTemplate->findPartialSpecialization(Converted.data(), Converted.size(),
+ InsertPos);
+
+ // Build the canonical type that describes the converted template
+ // arguments of the variable template partial specialization.
+ QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
+ TemplateName(VarTemplate), Converted.data(), Converted.size());
+
+ // Build the fully-sugared type for this variable template
+ // specialization as the user wrote in the specialization
+ // itself. This means that we'll pretty-print the type retrieved
+ // from the specialization's declaration the way that the user
+ // actually wrote the specialization, rather than formatting the
+ // name based on the "canonical" representation used to store the
+ // template arguments in the specialization.
+ TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo(
+ TemplateName(VarTemplate), PartialSpec->getLocation(), InstTemplateArgs,
+ CanonType);
+
+ if (PrevDecl) {
+ // We've already seen a partial specialization with the same template
+ // parameters and template arguments. This can happen, for example, when
+ // substituting the outer template arguments ends up causing two
+ // variable template partial specializations of a member variable template
+ // to have identical forms, e.g.,
+ //
+ // template<typename T, typename U>
+ // struct Outer {
+ // template<typename X, typename Y> pair<X,Y> p;
+ // template<typename Y> pair<T, Y> p;
+ // template<typename Y> pair<U, Y> p;
+ // };
+ //
+ // Outer<int, int> outer; // error: the partial specializations of Inner
+ // // have the same signature.
+ SemaRef.Diag(PartialSpec->getLocation(),
+ diag::err_var_partial_spec_redeclared)
+ << WrittenTy->getType();
+ SemaRef.Diag(PrevDecl->getLocation(),
+ diag::note_var_prev_partial_spec_here);
+ return 0;
+ }
+
+ // Do substitution on the type of the declaration
+ TypeSourceInfo *DI = SemaRef.SubstType(
+ PartialSpec->getTypeSourceInfo(), TemplateArgs,
+ PartialSpec->getTypeSpecStartLoc(), PartialSpec->getDeclName());
+ if (!DI)
+ return 0;
+
+ if (DI->getType()->isFunctionType()) {
+ SemaRef.Diag(PartialSpec->getLocation(),
+ diag::err_variable_instantiates_to_function)
+ << PartialSpec->isStaticDataMember() << DI->getType();
+ return 0;
+ }
+
+ // Create the variable template partial specialization declaration.
+ VarTemplatePartialSpecializationDecl *InstPartialSpec =
+ VarTemplatePartialSpecializationDecl::Create(
+ SemaRef.Context, Owner, PartialSpec->getInnerLocStart(),
+ PartialSpec->getLocation(), InstParams, VarTemplate, DI->getType(),
+ DI, PartialSpec->getStorageClass(), Converted.data(),
+ Converted.size(), InstTemplateArgs);
+
+ // Substitute the nested name specifier, if any.
+ if (SubstQualifier(PartialSpec, InstPartialSpec))
+ return 0;
+
+ InstPartialSpec->setInstantiatedFromMember(PartialSpec);
+ InstPartialSpec->setTypeAsWritten(WrittenTy);
+
+ // Add this partial specialization to the set of variable template partial
+ // specializations. The instantiation of the initializer is not necessary.
+ VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0);
+
+ SemaRef.BuildVariableInstantiation(InstPartialSpec, PartialSpec, TemplateArgs,
+ LateAttrs, Owner, StartingScope);
+
+ return InstPartialSpec;
+}
+
TypeSourceInfo*
TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
SmallVectorImpl<ParmVarDecl *> &Params) {
@@ -2449,7 +2868,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
CXXRecordDecl *ThisContext = 0;
unsigned ThisTypeQuals = 0;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
- ThisContext = Method->getParent();
+ ThisContext = cast<CXXRecordDecl>(Owner);
ThisTypeQuals = Method->getTypeQualifiers();
}
@@ -2461,11 +2880,10 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
if (!NewTInfo)
return 0;
- if (NewTInfo != OldTInfo) {
- // Get parameters from the new type info.
- TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens();
- if (FunctionProtoTypeLoc OldProtoLoc =
- OldTL.getAs<FunctionProtoTypeLoc>()) {
+ TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens();
+ if (FunctionProtoTypeLoc OldProtoLoc = OldTL.getAs<FunctionProtoTypeLoc>()) {
+ if (NewTInfo != OldTInfo) {
+ // Get parameters from the new type info.
TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens();
FunctionProtoTypeLoc NewProtoLoc = NewTL.castAs<FunctionProtoTypeLoc>();
unsigned NewIdx = 0;
@@ -2495,22 +2913,45 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
}
}
}
- }
- } else {
- // The function type itself was not dependent and therefore no
- // substitution occurred. However, we still need to instantiate
- // the function parameters themselves.
- TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens();
- if (FunctionProtoTypeLoc OldProtoLoc =
- OldTL.getAs<FunctionProtoTypeLoc>()) {
+ } else {
+ // The function type itself was not dependent and therefore no
+ // substitution occurred. However, we still need to instantiate
+ // the function parameters themselves.
+ const FunctionProtoType *OldProto =
+ cast<FunctionProtoType>(OldProtoLoc.getType());
for (unsigned i = 0, i_end = OldProtoLoc.getNumArgs(); i != i_end; ++i) {
- ParmVarDecl *Parm = VisitParmVarDecl(OldProtoLoc.getArg(i));
+ ParmVarDecl *OldParam = OldProtoLoc.getArg(i);
+ if (!OldParam) {
+ Params.push_back(SemaRef.BuildParmVarDeclForTypedef(
+ D, D->getLocation(), OldProto->getArgType(i)));
+ continue;
+ }
+
+ ParmVarDecl *Parm =
+ cast_or_null<ParmVarDecl>(VisitParmVarDecl(OldParam));
if (!Parm)
return 0;
Params.push_back(Parm);
}
}
+ } else {
+ // If the type of this function, after ignoring parentheses, is not
+ // *directly* a function type, then we're instantiating a function that
+ // was declared via a typedef or with attributes, e.g.,
+ //
+ // typedef int functype(int, int);
+ // functype func;
+ // int __cdecl meth(int, int);
+ //
+ // In this case, we'll just go instantiate the ParmVarDecls that we
+ // synthesized in the method declaration.
+ SmallVector<QualType, 4> ParamTypes;
+ if (SemaRef.SubstParmTypes(D->getLocation(), D->param_begin(),
+ D->getNumParams(), TemplateArgs, ParamTypes,
+ &Params))
+ return 0;
}
+
return NewTInfo;
}
@@ -2585,8 +3026,7 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
bool Expand = false;
bool RetainExpansion = false;
- Optional<unsigned> NumExpansions
- = PackExpansion->getNumExpansions();
+ Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions();
if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
SourceRange(),
Unexpanded,
@@ -2674,9 +3114,7 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
EPI.NoexceptExpr = NoexceptExpr;
New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
- ArrayRef<QualType>(NewProto->arg_type_begin(),
- NewProto->getNumArgs()),
- EPI));
+ NewProto->getArgTypes(), EPI));
}
void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
@@ -2687,15 +3125,13 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
InstantiatingTemplate Inst(*this, PointOfInstantiation, Decl,
InstantiatingTemplate::ExceptionSpecification());
- if (Inst) {
+ if (Inst.isInvalid()) {
// We hit the instantiation depth limit. Clear the exception specification
// so that our callers don't have to cope with EST_Uninstantiated.
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
EPI.ExceptionSpecType = EST_None;
Decl->setType(Context.getFunctionType(Proto->getResultType(),
- ArrayRef<QualType>(Proto->arg_type_begin(),
- Proto->getNumArgs()),
- EPI));
+ Proto->getArgTypes(), EPI));
return;
}
@@ -2774,10 +3210,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
EPI.ExceptionSpecType = NewEST;
EPI.ExceptionSpecDecl = New;
EPI.ExceptionSpecTemplate = ExceptionSpecTemplate;
- New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
- ArrayRef<QualType>(NewProto->arg_type_begin(),
- NewProto->getNumArgs()),
- EPI));
+ New->setType(SemaRef.Context.getFunctionType(
+ NewProto->getResultType(), NewProto->getArgTypes(), EPI));
} else {
::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs);
}
@@ -2862,11 +3296,17 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
return;
}
- // Call the LateTemplateParser callback if there a need to late parse
+ // Call the LateTemplateParser callback if there is a need to late parse
// a templated function definition.
if (!Pattern && PatternDecl->isLateTemplateParsed() &&
LateTemplateParser) {
- LateTemplateParser(OpaqueParser, PatternDecl);
+ // FIXME: Optimize to allow individual templates to be deserialized.
+ if (PatternDecl->isFromASTFile())
+ ExternalSource->ReadLateParsedTemplates(LateParsedTemplateMap);
+
+ LateParsedTemplate *LPT = LateParsedTemplateMap.lookup(PatternDecl);
+ assert(LPT && "missing LateParsedTemplate");
+ LateTemplateParser(OpaqueParser, *LPT);
Pattern = PatternDecl->getBody(PatternDecl);
}
@@ -2902,14 +3342,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (Function->getTemplateSpecializationKind()
== TSK_ExplicitInstantiationDeclaration &&
!PatternDecl->isInlined() &&
- !PatternDecl->getResultType()->isUndeducedType())
+ !PatternDecl->getResultType()->getContainedAutoType())
return;
if (PatternDecl->isInlined())
Function->setImplicitlyInline();
InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
- if (Inst)
+ if (Inst.isInvalid())
return;
// Copy the inner loc start from the pattern.
@@ -2920,6 +3360,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// while we're still within our own instantiation context.
SmallVector<VTableUse, 16> SavedVTableUses;
std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
+ SavePendingLocalImplicitInstantiationsRAII
+ SavedPendingLocalImplicitInstantiations(*this);
if (Recursive) {
VTableUses.swap(SavedVTableUses);
PendingInstantiations.swap(SavedPendingInstantiations);
@@ -3002,6 +3444,202 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
}
}
+VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
+ VarTemplateDecl *VarTemplate, VarDecl *FromVar,
+ const TemplateArgumentList &TemplateArgList,
+ const TemplateArgumentListInfo &TemplateArgsInfo,
+ SmallVectorImpl<TemplateArgument> &Converted,
+ SourceLocation PointOfInstantiation, void *InsertPos,
+ LateInstantiatedAttrVec *LateAttrs,
+ LocalInstantiationScope *StartingScope) {
+ if (FromVar->isInvalidDecl())
+ return 0;
+
+ InstantiatingTemplate Inst(*this, PointOfInstantiation, FromVar);
+ if (Inst.isInvalid())
+ return 0;
+
+ MultiLevelTemplateArgumentList TemplateArgLists;
+ TemplateArgLists.addOuterTemplateArguments(&TemplateArgList);
+
+ // Instantiate the first declaration of the variable template: for a partial
+ // specialization of a static data member template, the first declaration may
+ // or may not be the declaration in the class; if it's in the class, we want
+ // to instantiate a member in the class (a declaration), and if it's outside,
+ // we want to instantiate a definition.
+ FromVar = FromVar->getFirstDecl();
+
+ MultiLevelTemplateArgumentList MultiLevelList(TemplateArgList);
+ TemplateDeclInstantiator Instantiator(*this, FromVar->getDeclContext(),
+ MultiLevelList);
+
+ // TODO: Set LateAttrs and StartingScope ...
+
+ return cast_or_null<VarTemplateSpecializationDecl>(
+ Instantiator.VisitVarTemplateSpecializationDecl(
+ VarTemplate, FromVar, InsertPos, TemplateArgsInfo, Converted));
+}
+
+/// \brief Instantiates a variable template specialization by completing it
+/// with appropriate type information and initializer.
+VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl(
+ VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+
+ // Do substitution on the type of the declaration
+ TypeSourceInfo *DI =
+ SubstType(PatternDecl->getTypeSourceInfo(), TemplateArgs,
+ PatternDecl->getTypeSpecStartLoc(), PatternDecl->getDeclName());
+ if (!DI)
+ return 0;
+
+ // Update the type of this variable template specialization.
+ VarSpec->setType(DI->getType());
+
+ // Instantiate the initializer.
+ InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs);
+
+ return VarSpec;
+}
+
+/// BuildVariableInstantiation - Used after a new variable has been created.
+/// Sets basic variable data and decides whether to postpone the
+/// variable instantiation.
+void Sema::BuildVariableInstantiation(
+ VarDecl *NewVar, VarDecl *OldVar,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ LateInstantiatedAttrVec *LateAttrs, DeclContext *Owner,
+ LocalInstantiationScope *StartingScope,
+ bool InstantiatingVarTemplate) {
+
+ // If we are instantiating a local extern declaration, the
+ // instantiation belongs lexically to the containing function.
+ // If we are instantiating a static data member defined
+ // out-of-line, the instantiation will have the same lexical
+ // context (which will be a namespace scope) as the template.
+ if (OldVar->isLocalExternDecl()) {
+ NewVar->setLocalExternDecl();
+ NewVar->setLexicalDeclContext(Owner);
+ } else if (OldVar->isOutOfLine())
+ NewVar->setLexicalDeclContext(OldVar->getLexicalDeclContext());
+ NewVar->setTSCSpec(OldVar->getTSCSpec());
+ NewVar->setInitStyle(OldVar->getInitStyle());
+ NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl());
+ NewVar->setConstexpr(OldVar->isConstexpr());
+ NewVar->setInitCapture(OldVar->isInitCapture());
+ NewVar->setPreviousDeclInSameBlockScope(
+ OldVar->isPreviousDeclInSameBlockScope());
+ NewVar->setAccess(OldVar->getAccess());
+
+ if (!OldVar->isStaticDataMember()) {
+ if (OldVar->isUsed(false))
+ NewVar->setIsUsed();
+ NewVar->setReferenced(OldVar->isReferenced());
+ }
+
+ // See if the old variable had a type-specifier that defined an anonymous tag.
+ // If it did, mark the new variable as being the declarator for the new
+ // anonymous tag.
+ if (const TagType *OldTagType = OldVar->getType()->getAs<TagType>()) {
+ TagDecl *OldTag = OldTagType->getDecl();
+ if (OldTag->getDeclaratorForAnonDecl() == OldVar) {
+ TagDecl *NewTag = NewVar->getType()->castAs<TagType>()->getDecl();
+ assert(!NewTag->hasNameForLinkage() &&
+ !NewTag->hasDeclaratorForAnonDecl());
+ NewTag->setDeclaratorForAnonDecl(NewVar);
+ }
+ }
+
+ InstantiateAttrs(TemplateArgs, OldVar, NewVar, LateAttrs, StartingScope);
+
+ if (NewVar->hasAttrs())
+ CheckAlignasUnderalignment(NewVar);
+
+ LookupResult Previous(
+ *this, NewVar->getDeclName(), NewVar->getLocation(),
+ NewVar->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage
+ : Sema::LookupOrdinaryName,
+ Sema::ForRedeclaration);
+
+ if (NewVar->isLocalExternDecl() && OldVar->getPreviousDecl()) {
+ // We have a previous declaration. Use that one, so we merge with the
+ // right type.
+ if (NamedDecl *NewPrev = FindInstantiatedDecl(
+ NewVar->getLocation(), OldVar->getPreviousDecl(), TemplateArgs))
+ Previous.addDecl(NewPrev);
+ } else if (!isa<VarTemplateSpecializationDecl>(NewVar) &&
+ OldVar->hasLinkage())
+ LookupQualifiedName(Previous, NewVar->getDeclContext(), false);
+ CheckVariableDeclaration(NewVar, Previous);
+
+ if (!InstantiatingVarTemplate) {
+ NewVar->getLexicalDeclContext()->addHiddenDecl(NewVar);
+ if (!NewVar->isLocalExternDecl() || !NewVar->getPreviousDecl())
+ NewVar->getDeclContext()->makeDeclVisibleInContext(NewVar);
+ }
+
+ if (!OldVar->isOutOfLine()) {
+ if (NewVar->getDeclContext()->isFunctionOrMethod())
+ CurrentInstantiationScope->InstantiatedLocal(OldVar, NewVar);
+ }
+
+ // Link instantiations of static data members back to the template from
+ // which they were instantiated.
+ if (NewVar->isStaticDataMember() && !InstantiatingVarTemplate)
+ NewVar->setInstantiationOfStaticDataMember(OldVar,
+ TSK_ImplicitInstantiation);
+
+ // Delay instantiation of the initializer for variable templates until a
+ // definition of the variable is needed.
+ if (!isa<VarTemplateSpecializationDecl>(NewVar) && !InstantiatingVarTemplate)
+ InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs);
+
+ // Diagnose unused local variables with dependent types, where the diagnostic
+ // will have been deferred.
+ if (!NewVar->isInvalidDecl() &&
+ NewVar->getDeclContext()->isFunctionOrMethod() && !NewVar->isUsed() &&
+ OldVar->getType()->isDependentType())
+ DiagnoseUnusedDecl(NewVar);
+}
+
+/// \brief Instantiate the initializer of a variable.
+void Sema::InstantiateVariableInitializer(
+ VarDecl *Var, VarDecl *OldVar,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+
+ if (Var->getAnyInitializer())
+ // We already have an initializer in the class.
+ return;
+
+ if (OldVar->getInit()) {
+ if (Var->isStaticDataMember() && !OldVar->isOutOfLine())
+ PushExpressionEvaluationContext(Sema::ConstantEvaluated, OldVar);
+ else
+ PushExpressionEvaluationContext(Sema::PotentiallyEvaluated, OldVar);
+
+ // Instantiate the initializer.
+ ExprResult Init =
+ SubstInitializer(OldVar->getInit(), TemplateArgs,
+ OldVar->getInitStyle() == VarDecl::CallInit);
+ if (!Init.isInvalid()) {
+ bool TypeMayContainAuto = true;
+ if (Init.get()) {
+ bool DirectInit = OldVar->isDirectInit();
+ AddInitializerToDecl(Var, Init.take(), DirectInit, TypeMayContainAuto);
+ } else
+ ActOnUninitializedDecl(Var, TypeMayContainAuto);
+ } else {
+ // FIXME: Not too happy about invalidating the declaration
+ // because of a bogus initializer.
+ Var->setInvalidDecl();
+ }
+
+ PopExpressionEvaluationContext();
+ } else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) &&
+ !Var->isCXXForRangeDecl())
+ ActOnUninitializedDecl(Var, false);
+}
+
/// \brief Instantiate the definition of the given variable from its
/// template.
///
@@ -3023,26 +3661,151 @@ void Sema::InstantiateStaticDataMemberDefinition(
VarDecl *Var,
bool Recursive,
bool DefinitionRequired) {
+ InstantiateVariableDefinition(PointOfInstantiation, Var, Recursive,
+ DefinitionRequired);
+}
+
+void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
+ VarDecl *Var, bool Recursive,
+ bool DefinitionRequired) {
if (Var->isInvalidDecl())
return;
- // Find the out-of-line definition of this static data member.
- VarDecl *Def = Var->getInstantiatedFromStaticDataMember();
- assert(Def && "This data member was not instantiated from a template?");
- assert(Def->isStaticDataMember() && "Not a static data member?");
- Def = Def->getOutOfLineDefinition();
+ VarTemplateSpecializationDecl *VarSpec =
+ dyn_cast<VarTemplateSpecializationDecl>(Var);
+ VarDecl *PatternDecl = 0, *Def = 0;
+ MultiLevelTemplateArgumentList TemplateArgs =
+ getTemplateInstantiationArgs(Var);
+
+ if (VarSpec) {
+ // If this is a variable template specialization, make sure that it is
+ // non-dependent, then find its instantiation pattern.
+ bool InstantiationDependent = false;
+ assert(!TemplateSpecializationType::anyDependentTemplateArguments(
+ VarSpec->getTemplateArgsInfo(), InstantiationDependent) &&
+ "Only instantiate variable template specializations that are "
+ "not type-dependent");
+ (void)InstantiationDependent;
+
+ // Find the variable initialization that we'll be substituting. If the
+ // pattern was instantiated from a member template, look back further to
+ // find the real pattern.
+ assert(VarSpec->getSpecializedTemplate() &&
+ "Specialization without specialized template?");
+ llvm::PointerUnion<VarTemplateDecl *,
+ VarTemplatePartialSpecializationDecl *> PatternPtr =
+ VarSpec->getSpecializedTemplateOrPartial();
+ if (PatternPtr.is<VarTemplatePartialSpecializationDecl *>()) {
+ VarTemplatePartialSpecializationDecl *Tmpl =
+ PatternPtr.get<VarTemplatePartialSpecializationDecl *>();
+ while (VarTemplatePartialSpecializationDecl *From =
+ Tmpl->getInstantiatedFromMember()) {
+ if (Tmpl->isMemberSpecialization())
+ break;
+
+ Tmpl = From;
+ }
+ PatternDecl = Tmpl;
+ } else {
+ VarTemplateDecl *Tmpl = PatternPtr.get<VarTemplateDecl *>();
+ while (VarTemplateDecl *From =
+ Tmpl->getInstantiatedFromMemberTemplate()) {
+ if (Tmpl->isMemberSpecialization())
+ break;
+
+ Tmpl = From;
+ }
+ PatternDecl = Tmpl->getTemplatedDecl();
+ }
+
+ // If this is a static data member template, there might be an
+ // uninstantiated initializer on the declaration. If so, instantiate
+ // it now.
+ if (PatternDecl->isStaticDataMember() &&
+ (PatternDecl = PatternDecl->getFirstDecl())->hasInit() &&
+ !Var->hasInit()) {
+ // FIXME: Factor out the duplicated instantiation context setup/tear down
+ // code here.
+ InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
+ if (Inst.isInvalid())
+ return;
+
+ // If we're performing recursive template instantiation, create our own
+ // queue of pending implicit instantiations that we will instantiate
+ // later, while we're still within our own instantiation context.
+ SmallVector<VTableUse, 16> SavedVTableUses;
+ std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
+ if (Recursive) {
+ VTableUses.swap(SavedVTableUses);
+ PendingInstantiations.swap(SavedPendingInstantiations);
+ }
+
+ LocalInstantiationScope Local(*this);
+
+ // Enter the scope of this instantiation. We don't use
+ // PushDeclContext because we don't have a scope.
+ ContextRAII PreviousContext(*this, Var->getDeclContext());
+ InstantiateVariableInitializer(Var, PatternDecl, TemplateArgs);
+ PreviousContext.pop();
+
+ // FIXME: Need to inform the ASTConsumer that we instantiated the
+ // initializer?
+ // This variable may have local implicit instantiations that need to be
+ // instantiated within this scope.
+ PerformPendingInstantiations(/*LocalOnly=*/true);
+
+ Local.Exit();
+
+ if (Recursive) {
+ // Define any newly required vtables.
+ DefineUsedVTables();
+
+ // Instantiate any pending implicit instantiations found during the
+ // instantiation of this template.
+ PerformPendingInstantiations();
+
+ // Restore the set of pending vtables.
+ assert(VTableUses.empty() &&
+ "VTableUses should be empty before it is discarded.");
+ VTableUses.swap(SavedVTableUses);
+
+ // Restore the set of pending implicit instantiations.
+ assert(PendingInstantiations.empty() &&
+ "PendingInstantiations should be empty before it is discarded.");
+ PendingInstantiations.swap(SavedPendingInstantiations);
+ }
+ }
+
+ // Find actual definition
+ Def = PatternDecl->getDefinition(getASTContext());
+ } else {
+ // If this is a static data member, find its out-of-line definition.
+ assert(Var->isStaticDataMember() && "not a static data member?");
+ PatternDecl = Var->getInstantiatedFromStaticDataMember();
+
+ assert(PatternDecl && "data member was not instantiated from a template?");
+ assert(PatternDecl->isStaticDataMember() && "not a static data member?");
+ Def = PatternDecl->getOutOfLineDefinition();
+ }
+
+ // If we don't have a definition of the variable template, we won't perform
+ // any instantiation. Rather, we rely on the user to instantiate this
+ // definition (or provide a specialization for it) in another translation
+ // unit.
if (!Def) {
- // We did not find an out-of-line definition of this static data member,
- // so we won't perform any instantiation. Rather, we rely on the user to
- // instantiate this definition (or provide a specialization for it) in
- // another translation unit.
if (DefinitionRequired) {
- Def = Var->getInstantiatedFromStaticDataMember();
- Diag(PointOfInstantiation,
- diag::err_explicit_instantiation_undefined_member)
- << 2 << Var->getDeclName() << Var->getDeclContext();
- Diag(Def->getLocation(), diag::note_explicit_instantiation_here);
+ if (VarSpec)
+ Diag(PointOfInstantiation,
+ diag::err_explicit_instantiation_undefined_var_template) << Var;
+ else
+ Diag(PointOfInstantiation,
+ diag::err_explicit_instantiation_undefined_member)
+ << 2 << Var->getDeclName() << Var->getDeclContext();
+ Diag(PatternDecl->getLocation(),
+ diag::note_explicit_instantiation_here);
+ if (VarSpec)
+ Var->setInvalidDecl();
} else if (Var->getTemplateSpecializationKind()
== TSK_ExplicitInstantiationDefinition) {
PendingInstantiations.push_back(
@@ -3058,8 +3821,8 @@ void Sema::InstantiateStaticDataMemberDefinition(
if (TSK == TSK_ExplicitSpecialization)
return;
- // C++0x [temp.explicit]p9:
- // Except for inline functions, other explicit instantiation declarations
+ // C++11 [temp.explicit]p10:
+ // Except for inline functions, [...] explicit instantiation declarations
// have the effect of suppressing the implicit instantiation of the entity
// to which they refer.
if (TSK == TSK_ExplicitInstantiationDeclaration)
@@ -3088,7 +3851,7 @@ void Sema::InstantiateStaticDataMemberDefinition(
}
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
- if (Inst)
+ if (Inst.isInvalid())
return;
// If we're performing recursive template instantiation, create our own
@@ -3096,6 +3859,8 @@ void Sema::InstantiateStaticDataMemberDefinition(
// while we're still within our own instantiation context.
SmallVector<VTableUse, 16> SavedVTableUses;
std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
+ SavePendingLocalImplicitInstantiationsRAII
+ SavedPendingLocalImplicitInstantiations(*this);
if (Recursive) {
VTableUses.swap(SavedVTableUses);
PendingInstantiations.swap(SavedPendingInstantiations);
@@ -3103,22 +3868,58 @@ void Sema::InstantiateStaticDataMemberDefinition(
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
- ContextRAII previousContext(*this, Var->getDeclContext());
+ ContextRAII PreviousContext(*this, Var->getDeclContext());
LocalInstantiationScope Local(*this);
-
+
VarDecl *OldVar = Var;
- Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(),
- getTemplateInstantiationArgs(Var)));
+ if (!VarSpec)
+ Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(),
+ TemplateArgs));
+ else if (Var->isStaticDataMember() &&
+ Var->getLexicalDeclContext()->isRecord()) {
+ // We need to instantiate the definition of a static data member template,
+ // and all we have is the in-class declaration of it. Instantiate a separate
+ // declaration of the definition.
+ TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(),
+ TemplateArgs);
+ Var = cast_or_null<VarDecl>(Instantiator.VisitVarTemplateSpecializationDecl(
+ VarSpec->getSpecializedTemplate(), Def, 0,
+ VarSpec->getTemplateArgsInfo(), VarSpec->getTemplateArgs().asArray()));
+ if (Var) {
+ llvm::PointerUnion<VarTemplateDecl *,
+ VarTemplatePartialSpecializationDecl *> PatternPtr =
+ VarSpec->getSpecializedTemplateOrPartial();
+ if (VarTemplatePartialSpecializationDecl *Partial =
+ PatternPtr.dyn_cast<VarTemplatePartialSpecializationDecl *>())
+ cast<VarTemplateSpecializationDecl>(Var)->setInstantiationOf(
+ Partial, &VarSpec->getTemplateInstantiationArgs());
+
+ // Merge the definition with the declaration.
+ LookupResult R(*this, Var->getDeclName(), Var->getLocation(),
+ LookupOrdinaryName, ForRedeclaration);
+ R.addDecl(OldVar);
+ MergeVarDecl(Var, R);
+
+ // Attach the initializer.
+ InstantiateVariableInitializer(Var, Def, TemplateArgs);
+ }
+ } else
+ // Complete the existing variable's definition with an appropriately
+ // substituted type and initializer.
+ Var = CompleteVarTemplateSpecializationDecl(VarSpec, Def, TemplateArgs);
- previousContext.pop();
+ PreviousContext.pop();
if (Var) {
PassToConsumerRAII.Var = Var;
- MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo();
- assert(MSInfo && "Missing member specialization information?");
- Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(),
- MSInfo->getPointOfInstantiation());
+ Var->setTemplateSpecializationKind(OldVar->getTemplateSpecializationKind(),
+ OldVar->getPointOfInstantiation());
}
+
+ // This variable may have local implicit instantiations that need to be
+ // instantiated within this scope.
+ PerformPendingInstantiations(/*LocalOnly=*/true);
+
Local.Exit();
if (Recursive) {
@@ -3131,14 +3932,12 @@ void Sema::InstantiateStaticDataMemberDefinition(
// Restore the set of pending vtables.
assert(VTableUses.empty() &&
- "VTableUses should be empty before it is discarded, "
- "while instantiating static data member.");
+ "VTableUses should be empty before it is discarded.");
VTableUses.swap(SavedVTableUses);
// Restore the set of pending implicit instantiations.
assert(PendingInstantiations.empty() &&
- "PendingInstantiations should be empty before it is discarded, "
- "while instantiating static data member.");
+ "PendingInstantiations should be empty before it is discarded.");
PendingInstantiations.swap(SavedPendingInstantiations);
}
}
@@ -3167,8 +3966,9 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
if (Init->isPackExpansion()) {
// This is a pack expansion. We should expand it now.
TypeLoc BaseTL = Init->getTypeSourceInfo()->getTypeLoc();
- SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ SmallVector<UnexpandedParameterPack, 4> Unexpanded;
collectUnexpandedParameterPacks(BaseTL, Unexpanded);
+ collectUnexpandedParameterPacks(Init->getInit(), Unexpanded);
bool ShouldExpand = false;
bool RetainExpansion = false;
Optional<unsigned> NumExpansions;
@@ -3523,14 +4323,33 @@ DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC,
/// template struct X<int>;
/// \endcode
///
-/// In the instantiation of X<int>::getKind(), we need to map the
-/// EnumConstantDecl for KnownValue (which refers to
-/// X<T>::\<Kind>\::KnownValue) to its instantiation
-/// (X<int>::\<Kind>\::KnownValue). InstantiateCurrentDeclRef() performs
-/// this mapping from within the instantiation of X<int>.
+/// In the instantiation of <tt>X<int>::getKind()</tt>, we need to map the
+/// \p EnumConstantDecl for \p KnownValue (which refers to
+/// <tt>X<T>::<Kind>::KnownValue</tt>) to its instantiation
+/// (<tt>X<int>::<Kind>::KnownValue</tt>). \p FindInstantiatedDecl performs
+/// this mapping from within the instantiation of <tt>X<int></tt>.
NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
const MultiLevelTemplateArgumentList &TemplateArgs) {
DeclContext *ParentDC = D->getDeclContext();
+ // FIXME: Parmeters of pointer to functions (y below) that are themselves
+ // parameters (p below) can have their ParentDC set to the translation-unit
+ // - thus we can not consistently check if the ParentDC of such a parameter
+ // is Dependent or/and a FunctionOrMethod.
+ // For e.g. this code, during Template argument deduction tries to
+ // find an instantiated decl for (T y) when the ParentDC for y is
+ // the translation unit.
+ // e.g. template <class T> void Foo(auto (*p)(T y) -> decltype(y())) {}
+ // float baz(float(*)()) { return 0.0; }
+ // Foo(baz);
+ // The better fix here is perhaps to ensure that a ParmVarDecl, by the time
+ // it gets here, always has a FunctionOrMethod as its ParentDC??
+ // For now:
+ // - as long as we have a ParmVarDecl whose parent is non-dependent and
+ // whose type is not instantiation dependent, do nothing to the decl
+ // - otherwise find its instantiated decl.
+ if (isa<ParmVarDecl>(D) && !ParentDC->isDependentContext() &&
+ !cast<ParmVarDecl>(D)->getType()->isInstantiationDependentType())
+ return D;
if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
(ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) ||
@@ -3550,6 +4369,16 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]);
}
+ // If we're performing a partial substitution during template argument
+ // deduction, we may not have values for template parameters yet. They
+ // just map to themselves.
+ if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
+ isa<TemplateTemplateParmDecl>(D))
+ return D;
+
+ if (D->isInvalidDecl())
+ return 0;
+
// If we didn't find the decl, then we must have a label decl that hasn't
// been found yet. Lazily instantiate it and return it now.
assert(isa<LabelDecl>(D));
@@ -3561,6 +4390,20 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
return cast<LabelDecl>(Inst);
}
+ // For variable template specializations, update those that are still
+ // type-dependent.
+ if (VarTemplateSpecializationDecl *VarSpec =
+ dyn_cast<VarTemplateSpecializationDecl>(D)) {
+ bool InstantiationDependent = false;
+ const TemplateArgumentListInfo &VarTemplateArgs =
+ VarSpec->getTemplateArgsInfo();
+ if (TemplateSpecializationType::anyDependentTemplateArguments(
+ VarTemplateArgs, InstantiationDependent))
+ D = cast<NamedDecl>(
+ SubstDecl(D, VarSpec->getDeclContext(), TemplateArgs));
+ return D;
+ }
+
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
if (!Record->isDependentContext())
return D;
@@ -3573,7 +4416,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
else if (ClassTemplatePartialSpecializationDecl *PartialSpec
= dyn_cast<ClassTemplatePartialSpecializationDecl>(Record))
ClassTemplate = PartialSpec->getSpecializedTemplate()->getCanonicalDecl();
-
+
// Walk the current context to find either the record or an instantiation of
// it.
DeclContext *DC = CurContext;
@@ -3582,7 +4425,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
// definition, we'll find our own context. We're done.
if (DC->Equals(Record))
return Record;
-
+
if (CXXRecordDecl *InstRecord = dyn_cast<CXXRecordDecl>(DC)) {
// Check whether we're in the process of instantiating a class template
// specialization of the template we're mapping.
@@ -3592,13 +4435,12 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
if (ClassTemplate && isInstantiationOf(ClassTemplate, SpecTemplate))
return InstRecord;
}
-
+
// Check whether we're in the process of instantiating a member class.
if (isInstantiationOf(Record, InstRecord))
return InstRecord;
}
-
-
+
// Move to the outer template scope.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) {
if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){
@@ -3606,7 +4448,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
continue;
}
}
-
+
DC = DC->getParent();
}
@@ -3739,9 +4581,13 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
continue;
}
- // Instantiate static data member definitions.
+ // Instantiate variable definitions
VarDecl *Var = cast<VarDecl>(Inst.first);
- assert(Var->isStaticDataMember() && "Not a static data member?");
+
+ assert((Var->isStaticDataMember() ||
+ isa<VarTemplateSpecializationDecl>(Var)) &&
+ "Not a static data member, nor a variable template"
+ " specialization?");
// Don't try to instantiate declarations if the most recent redeclaration
// is invalid.
@@ -3764,14 +4610,15 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
break;
}
- PrettyDeclStackTraceEntry CrashInfo(*this, Var, Var->getLocation(),
- "instantiating static data member "
- "definition");
-
+ PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
+ "instantiating variable definition");
bool DefinitionRequired = Var->getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDefinition;
- InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true,
- DefinitionRequired);
+
+ // Instantiate static data member definitions or variable template
+ // specializations.
+ InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true,
+ DefinitionRequired);
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
index db885aeec7b7..78aa7f893a1a 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -18,6 +18,7 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
+#include "TypeLocBuilder.h"
using namespace clang;
@@ -179,10 +180,14 @@ namespace {
// If any capture names a function parameter pack, that pack is expanded
// when the lambda is expanded.
for (LambdaExpr::capture_iterator I = Lambda->capture_begin(),
- E = Lambda->capture_end(); I != E; ++I)
- if (VarDecl *VD = I->getCapturedVar())
+ E = Lambda->capture_end();
+ I != E; ++I) {
+ if (I->capturesVariable()) {
+ VarDecl *VD = I->getCapturedVar();
if (VD->isParameterPack())
Unexpanded.push_back(std::make_pair(VD, I->getLocation()));
+ }
+ }
inherited::TraverseLambdaExpr(Lambda);
@@ -459,17 +464,13 @@ Sema::CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc,
EllipsisLoc, NumExpansions);
if (Result.isNull())
return 0;
-
- TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
- PackExpansionTypeLoc TL =
- TSResult->getTypeLoc().castAs<PackExpansionTypeLoc>();
+
+ TypeLocBuilder TLB;
+ TLB.pushFullCopy(Pattern->getTypeLoc());
+ PackExpansionTypeLoc TL = TLB.push<PackExpansionTypeLoc>(Result);
TL.setEllipsisLoc(EllipsisLoc);
-
- // Copy over the source-location information from the type.
- memcpy(TL.getNextTypeLoc().getOpaqueData(),
- Pattern->getTypeLoc().getOpaqueData(),
- Pattern->getTypeLoc().getFullDataSize());
- return TSResult;
+
+ return TLB.getTypeSourceInfo(Context, Result);
}
QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange,
@@ -818,16 +819,12 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
R.getLookupKind(), S, 0,
Validator)) {
- std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
+ diagnoseTypo(Corrected,
+ PDiag(diag::err_sizeof_pack_no_pack_name_suggest) << &Name,
+ PDiag(diag::note_parameter_pack_here));
ParameterPack = Corrected.getCorrectionDecl();
- Diag(NameLoc, diag::err_sizeof_pack_no_pack_name_suggest)
- << &Name << CorrectedQuotedStr
- << FixItHint::CreateReplacement(
- NameLoc, Corrected.getAsString(getLangOpts()));
- Diag(ParameterPack->getLocation(), diag::note_parameter_pack_here)
- << CorrectedQuotedStr;
}
-
+
case LookupResult::FoundOverloaded:
case LookupResult::FoundUnresolvedValue:
break;
@@ -848,3 +845,63 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc,
ParameterPack, NameLoc, RParenLoc);
}
+
+TemplateArgumentLoc
+Sema::getTemplateArgumentPackExpansionPattern(
+ TemplateArgumentLoc OrigLoc,
+ SourceLocation &Ellipsis, Optional<unsigned> &NumExpansions) const {
+ const TemplateArgument &Argument = OrigLoc.getArgument();
+ assert(Argument.isPackExpansion());
+ switch (Argument.getKind()) {
+ case TemplateArgument::Type: {
+ // FIXME: We shouldn't ever have to worry about missing
+ // type-source info!
+ TypeSourceInfo *ExpansionTSInfo = OrigLoc.getTypeSourceInfo();
+ if (!ExpansionTSInfo)
+ ExpansionTSInfo = Context.getTrivialTypeSourceInfo(Argument.getAsType(),
+ Ellipsis);
+ PackExpansionTypeLoc Expansion =
+ ExpansionTSInfo->getTypeLoc().castAs<PackExpansionTypeLoc>();
+ Ellipsis = Expansion.getEllipsisLoc();
+
+ TypeLoc Pattern = Expansion.getPatternLoc();
+ NumExpansions = Expansion.getTypePtr()->getNumExpansions();
+
+ // We need to copy the TypeLoc because TemplateArgumentLocs store a
+ // TypeSourceInfo.
+ // FIXME: Find some way to avoid the copy?
+ TypeLocBuilder TLB;
+ TLB.pushFullCopy(Pattern);
+ TypeSourceInfo *PatternTSInfo =
+ TLB.getTypeSourceInfo(Context, Pattern.getType());
+ return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
+ PatternTSInfo);
+ }
+
+ case TemplateArgument::Expression: {
+ PackExpansionExpr *Expansion
+ = cast<PackExpansionExpr>(Argument.getAsExpr());
+ Expr *Pattern = Expansion->getPattern();
+ Ellipsis = Expansion->getEllipsisLoc();
+ NumExpansions = Expansion->getNumExpansions();
+ return TemplateArgumentLoc(Pattern, Pattern);
+ }
+
+ case TemplateArgument::TemplateExpansion:
+ Ellipsis = OrigLoc.getTemplateEllipsisLoc();
+ NumExpansions = Argument.getNumTemplateExpansions();
+ return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
+ OrigLoc.getTemplateQualifierLoc(),
+ OrigLoc.getTemplateNameLoc());
+
+ case TemplateArgument::Declaration:
+ case TemplateArgument::NullPtr:
+ case TemplateArgument::Template:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ case TemplateArgument::Null:
+ return TemplateArgumentLoc();
+ }
+
+ llvm_unreachable("Invalid TemplateArgument Kind!");
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
index 5ce4012fdccd..aa7459de2726 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
@@ -33,8 +34,16 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
+#include "TypeLocBuilder.h"
+
using namespace clang;
+enum TypeDiagSelector {
+ TDS_Function,
+ TDS_Pointer,
+ TDS_ObjCObjOrBlock
+};
+
/// isOmittedBlockReturnType - Return true if this declarator is missing a
/// return type because this is a omitted return type on a block literal.
static bool isOmittedBlockReturnType(const Declarator &D) {
@@ -56,23 +65,15 @@ static bool isOmittedBlockReturnType(const Declarator &D) {
/// doesn't apply to the given type.
static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
QualType type) {
- bool useExpansionLoc = false;
-
- unsigned diagID = 0;
+ TypeDiagSelector WhichType;
+ bool useExpansionLoc = true;
switch (attr.getKind()) {
- case AttributeList::AT_ObjCGC:
- diagID = diag::warn_pointer_attribute_wrong_type;
- useExpansionLoc = true;
- break;
-
- case AttributeList::AT_ObjCOwnership:
- diagID = diag::warn_objc_object_attribute_wrong_type;
- useExpansionLoc = true;
- break;
-
+ case AttributeList::AT_ObjCGC: WhichType = TDS_Pointer; break;
+ case AttributeList::AT_ObjCOwnership: WhichType = TDS_ObjCObjOrBlock; break;
default:
// Assume everything else was a function attribute.
- diagID = diag::warn_function_attribute_wrong_type;
+ WhichType = TDS_Function;
+ useExpansionLoc = false;
break;
}
@@ -80,15 +81,17 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
StringRef name = attr.getName()->getName();
// The GC attributes are usually written with macros; special-case them.
- if (useExpansionLoc && loc.isMacroID() && attr.getParameterName()) {
- if (attr.getParameterName()->isStr("strong")) {
+ IdentifierInfo *II = attr.isArgIdent(0) ? attr.getArgAsIdent(0)->Ident : 0;
+ if (useExpansionLoc && loc.isMacroID() && II) {
+ if (II->isStr("strong")) {
if (S.findMacroSpelling(loc, "__strong")) name = "__strong";
- } else if (attr.getParameterName()->isStr("weak")) {
+ } else if (II->isStr("weak")) {
if (S.findMacroSpelling(loc, "__weak")) name = "__weak";
}
}
- S.Diag(loc, diagID) << name << type;
+ S.Diag(loc, diag::warn_type_attribute_wrong_type) << name << WhichType
+ << type;
}
// objc_gc applies to Objective-C pointers or, otherwise, to the
@@ -110,7 +113,14 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
case AttributeList::AT_Regparm: \
case AttributeList::AT_Pcs: \
case AttributeList::AT_PnaclCall: \
- case AttributeList::AT_IntelOclBicc \
+ case AttributeList::AT_IntelOclBicc
+
+// Microsoft-specific type qualifiers.
+#define MS_TYPE_ATTRS_CASELIST \
+ case AttributeList::AT_Ptr32: \
+ case AttributeList::AT_Ptr64: \
+ case AttributeList::AT_SPtr: \
+ case AttributeList::AT_UPtr
namespace {
/// An object which stores processing state for the entire
@@ -225,26 +235,6 @@ namespace {
savedAttrs.back()->setNext(0);
}
};
-
- /// Basically std::pair except that we really want to avoid an
- /// implicit operator= for safety concerns. It's also a minor
- /// link-time optimization for this to be a private type.
- struct AttrAndList {
- /// The attribute.
- AttributeList &first;
-
- /// The head of the list the attribute is currently in.
- AttributeList *&second;
-
- AttrAndList(AttributeList &attr, AttributeList *&head)
- : first(attr), second(head) {}
- };
-}
-
-namespace llvm {
- template <> struct isPodLike<AttrAndList> {
- static const bool value = true;
- };
}
static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) {
@@ -294,6 +284,10 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
AttributeList &attr,
QualType &type);
+static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &state,
+ AttributeList &attr,
+ QualType &type);
+
static bool handleObjCGCTypeAttr(TypeProcessingState &state,
AttributeList &attr, QualType &type);
@@ -535,12 +529,7 @@ distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
return true;
}
- if (handleFunctionTypeAttr(state, attr, declSpecType)) {
- spliceAttrOutOfList(attr, attrList);
- return true;
- }
-
- return false;
+ return handleFunctionTypeAttr(state, attr, declSpecType);
}
/// A function type attribute was written in the decl spec. Try to
@@ -628,6 +617,10 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType);
break;
+ MS_TYPE_ATTRS_CASELIST:
+ // Microsoft type attributes cannot go after the declarator-id.
+ continue;
+
default:
break;
}
@@ -769,8 +762,13 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// is inferred from the return statements inside the block.
// The declspec is always missing in a lambda expr context; it is either
// specified with a trailing return type or inferred.
- if (declarator.getContext() == Declarator::LambdaExprContext ||
- isOmittedBlockReturnType(declarator)) {
+ if (S.getLangOpts().CPlusPlus1y &&
+ declarator.getContext() == Declarator::LambdaExprContext) {
+ // In C++1y, a lambda's implicit return type is 'auto'.
+ Result = Context.getAutoDeductType();
+ break;
+ } else if (declarator.getContext() == Declarator::LambdaExprContext ||
+ isOmittedBlockReturnType(declarator)) {
Result = Context.DependentTy;
break;
}
@@ -996,11 +994,54 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
case DeclSpec::TST_auto:
// TypeQuals handled by caller.
- Result = Context.getAutoType(QualType(), /*decltype(auto)*/false);
+ // If auto is mentioned in a lambda parameter context, convert it to a
+ // template parameter type immediately, with the appropriate depth and
+ // index, and update sema's state (LambdaScopeInfo) for the current lambda
+ // being analyzed (which tracks the invented type template parameter).
+ if (declarator.getContext() == Declarator::LambdaExprParameterContext) {
+ sema::LambdaScopeInfo *LSI = S.getCurLambda();
+ assert(LSI && "No LambdaScopeInfo on the stack!");
+ const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
+ const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
+ const bool IsParameterPack = declarator.hasEllipsis();
+
+ // Create a name for the invented template parameter type.
+ std::string InventedTemplateParamName = "$auto-";
+ llvm::raw_string_ostream ss(InventedTemplateParamName);
+ ss << TemplateParameterDepth;
+ ss << "-" << AutoParameterPosition;
+ ss.flush();
+
+ IdentifierInfo& TemplateParamII = Context.Idents.get(
+ InventedTemplateParamName.c_str());
+ // Turns out we must create the TemplateTypeParmDecl here to
+ // retrieve the corresponding template parameter type.
+ TemplateTypeParmDecl *CorrespondingTemplateParam =
+ TemplateTypeParmDecl::Create(Context,
+ // Temporarily add to the TranslationUnit DeclContext. When the
+ // associated TemplateParameterList is attached to a template
+ // declaration (such as FunctionTemplateDecl), the DeclContext
+ // for each template parameter gets updated appropriately via
+ // a call to AdoptTemplateParameterList.
+ Context.getTranslationUnitDecl(),
+ /*KeyLoc*/ SourceLocation(),
+ /*NameLoc*/ declarator.getLocStart(),
+ TemplateParameterDepth,
+ AutoParameterPosition, // our template param index
+ /* Identifier*/ &TemplateParamII, false, IsParameterPack);
+ LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
+ // Replace the 'auto' in the function parameter with this invented
+ // template type parameter.
+ Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0);
+ } else {
+ Result = Context.getAutoType(QualType(), /*decltype(auto)*/false, false);
+ }
break;
case DeclSpec::TST_decltype_auto:
- Result = Context.getAutoType(QualType(), /*decltype(auto)*/true);
+ Result = Context.getAutoType(QualType(),
+ /*decltype(auto)*/true,
+ /*IsDependent*/ false);
break;
case DeclSpec::TST_unknown_anytype:
@@ -1547,14 +1588,16 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
ASM = ArrayType::Normal;
}
} else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
- !T->isIncompleteType()) {
+ !T->isIncompleteType() && !T->isUndeducedType()) {
// Is the array too large?
unsigned ActiveSizeBits
= ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
- if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
+ if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
Diag(ArraySize->getLocStart(), diag::err_array_too_large)
<< ConstVal.toString(10)
<< ArraySize->getSourceRange();
+ return QualType();
+ }
}
T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
@@ -1569,7 +1612,6 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (!getLangOpts().C99) {
if (T->isVariableArrayType()) {
// Prohibit the use of non-POD types in VLAs.
- // FIXME: C++1y allows this.
QualType BaseT = Context.getBaseElementType(T);
if (!T->isDependentType() &&
!BaseT.isPODType(Context) &&
@@ -1585,9 +1627,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
}
// Just extwarn about VLAs.
else
- Diag(Loc, getLangOpts().CPlusPlus1y
- ? diag::warn_cxx11_compat_array_of_runtime_bound
- : diag::ext_vla);
+ Diag(Loc, diag::ext_vla);
} else if (ASM != ArrayType::Normal || Quals != 0)
Diag(Loc,
getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx
@@ -1618,8 +1658,9 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) {
llvm::APSInt vecSize(32);
if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) {
- Diag(AttrLoc, diag::err_attribute_argument_not_int)
- << "ext_vector_type" << ArraySize->getSourceRange();
+ Diag(AttrLoc, diag::err_attribute_argument_type)
+ << "ext_vector_type" << AANT_ArgumentIntegerConstant
+ << ArraySize->getSourceRange();
return QualType();
}
@@ -1633,30 +1674,50 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
return QualType();
}
+ if (VectorType::isVectorSizeTooLarge(vectorSize)) {
+ Diag(AttrLoc, diag::err_attribute_size_too_large)
+ << ArraySize->getSourceRange();
+ return QualType();
+ }
+
return Context.getExtVectorType(T, vectorSize);
}
return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc);
}
-QualType Sema::BuildFunctionType(QualType T,
- llvm::MutableArrayRef<QualType> ParamTypes,
- SourceLocation Loc, DeclarationName Entity,
- const FunctionProtoType::ExtProtoInfo &EPI) {
+bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) {
if (T->isArrayType() || T->isFunctionType()) {
Diag(Loc, diag::err_func_returning_array_function)
<< T->isFunctionType() << T;
- return QualType();
+ return true;
}
// Functions cannot return half FP.
if (T->isHalfType()) {
Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 <<
FixItHint::CreateInsertion(Loc, "*");
- return QualType();
+ return true;
}
+ // Methods cannot return interface types. All ObjC objects are
+ // passed by reference.
+ if (T->isObjCObjectType()) {
+ Diag(Loc, diag::err_object_cannot_be_passed_returned_by_value) << 0 << T;
+ return 0;
+ }
+
+ return false;
+}
+
+QualType Sema::BuildFunctionType(QualType T,
+ llvm::MutableArrayRef<QualType> ParamTypes,
+ SourceLocation Loc, DeclarationName Entity,
+ const FunctionProtoType::ExtProtoInfo &EPI) {
bool Invalid = false;
+
+ Invalid |= CheckFunctionReturnType(T, Loc);
+
for (unsigned Idx = 0, Cnt = ParamTypes.size(); Idx < Cnt; ++Idx) {
// FIXME: Loc is too inprecise here, should use proper locations for args.
QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]);
@@ -1751,6 +1812,8 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
}
}
+ // FIXME: Adjust member function pointer calling conventions.
+
return Context.getMemberPointerType(T, Class.getTypePtr());
}
@@ -1919,7 +1982,7 @@ static void diagnoseIgnoredQualifiers(
{ DeclSpec::TQ_atomic, "_Atomic", AtomicQualLoc }
};
- llvm::SmallString<32> QualStr;
+ SmallString<32> QualStr;
unsigned NumQuals = 0;
SourceLocation Loc;
FixItHint FixIts[4];
@@ -2064,6 +2127,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// In C++11, a function declarator using 'auto' must have a trailing return
// type (this is checked later) and we can skip this. In other languages
// using auto, we need to check regardless.
+ // C++14 In generic lambdas allow 'auto' in their parameters.
if (ContainsPlaceholderType &&
(!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) {
int Error = -1;
@@ -2076,7 +2140,12 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case Declarator::ObjCParameterContext:
case Declarator::ObjCResultContext:
case Declarator::PrototypeContext:
- Error = 0; // Function prototype
+ Error = 0;
+ break;
+ case Declarator::LambdaExprParameterContext:
+ if (!(SemaRef.getLangOpts().CPlusPlus1y
+ && D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto))
+ Error = 14;
break;
case Declarator::MemberContext:
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
@@ -2156,8 +2225,10 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
AutoRange = D.getName().getSourceRange();
if (Error != -1) {
+ const bool IsDeclTypeAuto =
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_decltype_auto;
SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)
- << Error << AutoRange;
+ << IsDeclTypeAuto << Error << AutoRange;
T = SemaRef.Context.IntTy;
D.setInvalidType(true);
} else
@@ -2207,6 +2278,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
D.setInvalidType(true);
break;
case Declarator::PrototypeContext:
+ case Declarator::LambdaExprParameterContext:
case Declarator::ObjCParameterContext:
case Declarator::ObjCResultContext:
case Declarator::KNRTypeListContext:
@@ -2377,7 +2449,8 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
S.Diag(DeclType.Loc, diag::note_empty_parens_default_ctor)
<< FixItHint::CreateRemoval(ParenRange);
else {
- std::string Init = S.getFixItZeroInitializerForType(RT);
+ std::string Init =
+ S.getFixItZeroInitializerForType(RT, ParenRange.getBegin());
if (Init.empty() && S.LangOpts.CPlusPlus11)
Init = "{}";
if (!Init.empty())
@@ -2387,6 +2460,52 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
}
}
+/// Helper for figuring out the default CC for a function declarator type. If
+/// this is the outermost chunk, then we can determine the CC from the
+/// declarator context. If not, then this could be either a member function
+/// type or normal function type.
+static CallingConv
+getCCForDeclaratorChunk(Sema &S, Declarator &D,
+ const DeclaratorChunk::FunctionTypeInfo &FTI,
+ unsigned ChunkIndex) {
+ assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function);
+
+ bool IsCXXInstanceMethod = false;
+
+ if (S.getLangOpts().CPlusPlus) {
+ // Look inwards through parentheses to see if this chunk will form a
+ // member pointer type or if we're the declarator. Any type attributes
+ // between here and there will override the CC we choose here.
+ unsigned I = ChunkIndex;
+ bool FoundNonParen = false;
+ while (I && !FoundNonParen) {
+ --I;
+ if (D.getTypeObject(I).Kind != DeclaratorChunk::Paren)
+ FoundNonParen = true;
+ }
+
+ if (FoundNonParen) {
+ // If we're not the declarator, we're a regular function type unless we're
+ // in a member pointer.
+ IsCXXInstanceMethod =
+ D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer;
+ } else {
+ // We're the innermost decl chunk, so must be a function declarator.
+ assert(D.isFunctionDeclarator());
+
+ // If we're inside a record, we're declaring a method, but it could be
+ // explicitly or implicitly static.
+ IsCXXInstanceMethod =
+ D.isFirstDeclarationOfMember() &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+ !D.isStaticMember();
+ }
+ }
+
+ return S.Context.getDefaultCallingConvention(FTI.isVariadic,
+ IsCXXInstanceMethod);
+}
+
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType declSpecType,
TypeSourceInfo *TInfo) {
@@ -2580,8 +2699,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
}
-
- if (const AutoType *AT = T->getContainedAutoType()) {
+ const AutoType *AT = T->getContainedAutoType();
+ // Allow arrays of auto if we are a generic lambda parameter.
+ // i.e. [](auto (&array)[5]) { return array[0]; }; OK
+ if (AT && D.getContext() != Declarator::LambdaExprParameterContext) {
// We've already diagnosed this for decltype(auto).
if (!AT->isDecltypeAuto())
S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
@@ -2667,6 +2788,33 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
+ // Methods cannot return interface types. All ObjC objects are
+ // passed by reference.
+ if (T->isObjCObjectType()) {
+ SourceLocation DiagLoc, FixitLoc;
+ if (TInfo) {
+ DiagLoc = TInfo->getTypeLoc().getLocStart();
+ FixitLoc = S.PP.getLocForEndOfToken(TInfo->getTypeLoc().getLocEnd());
+ } else {
+ DiagLoc = D.getDeclSpec().getTypeSpecTypeLoc();
+ FixitLoc = S.PP.getLocForEndOfToken(D.getDeclSpec().getLocEnd());
+ }
+ S.Diag(DiagLoc, diag::err_object_cannot_be_passed_returned_by_value)
+ << 0 << T
+ << FixItHint::CreateInsertion(FixitLoc, "*");
+
+ T = Context.getObjCObjectPointerType(T);
+ if (TInfo) {
+ TypeLocBuilder TLB;
+ TLB.pushFullCopy(TInfo->getTypeLoc());
+ ObjCObjectPointerTypeLoc TLoc = TLB.push<ObjCObjectPointerTypeLoc>(T);
+ TLoc.setStarLoc(FixitLoc);
+ TInfo = TLB.getTypeSourceInfo(Context, T);
+ }
+
+ D.setInvalidType(true);
+ }
+
// cv-qualifiers on return types are pointless except when the type is a
// class type in C++.
if ((T.getCVRQualifiers() || T->isAtomicType()) &&
@@ -2712,13 +2860,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
- if (LangOpts.CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
+ if (LangOpts.CPlusPlus && D.getDeclSpec().hasTagDefinition()) {
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
- if (Tag->isCompleteDefinition())
- S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
- << Context.getTypeDeclType(Tag);
+ S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
+ << Context.getTypeDeclType(Tag);
}
// Exception specs are not allowed in typedefs. Complain, but add it
@@ -2733,9 +2880,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (FTI.isAmbiguous)
warnAboutAmbiguousFunction(S, D, DeclType, T);
+ FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex));
+
if (!FTI.NumArgs && !FTI.isVariadic && !LangOpts.CPlusPlus) {
// Simple void foo(), where the incoming T is the result type.
- T = Context.getFunctionNoProtoType(T);
+ T = Context.getFunctionNoProtoType(T, EI);
} else {
// We allow a zero-parameter variadic function in C if the
// function is marked with the "overloadable" attribute. Scan
@@ -2760,11 +2909,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
S.Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
D.setInvalidType(true);
// Recover by creating a K&R-style function type.
- T = Context.getFunctionNoProtoType(T);
+ T = Context.getFunctionNoProtoType(T, EI);
break;
}
FunctionProtoType::ExtProtoInfo EPI;
+ EPI.ExtInfo = EI;
EPI.Variadic = FTI.isVariadic;
EPI.HasTrailingReturn = FTI.hasTrailingReturnType();
EPI.TypeQuals = FTI.TypeQuals;
@@ -2786,10 +2936,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType ArgTy = Param->getType();
assert(!ArgTy.isNull() && "Couldn't parse type?");
- // Adjust the parameter type.
- assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) &&
- "Unadjusted type?");
-
// Look for 'void'. void is allowed only as a single argument to a
// function with no other parameters (C99 6.7.5.3p10). We record
// int(void) as a FunctionProtoType with an empty argument list.
@@ -3019,9 +3165,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
EPI.TypeQuals = 0;
EPI.RefQualifier = RQ_None;
- T = Context.getFunctionType(FnTy->getResultType(),
- ArrayRef<QualType>(FnTy->arg_type_begin(),
- FnTy->getNumArgs()),
+ T = Context.getFunctionType(FnTy->getResultType(), FnTy->getArgTypes(),
EPI);
// Rebuild any parens around the identifier in the function type.
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
@@ -3056,6 +3200,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// is a parameter pack (14.5.3). [...]
switch (D.getContext()) {
case Declarator::PrototypeContext:
+ case Declarator::LambdaExprParameterContext:
// C++0x [dcl.fct]p13:
// [...] When it is part of a parameter-declaration-clause, the
// parameter pack is a function parameter pack (14.5.3). The type T
@@ -3074,7 +3219,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
T = Context.getPackExpansionType(T, None);
}
break;
-
case Declarator::TemplateParamContext:
// C++0x [temp.param]p15:
// If a template-parameter is a [...] is a parameter-declaration that
@@ -3183,13 +3327,18 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
case Qualifiers::OCL_Autoreleasing: attrStr = "autoreleasing"; break;
}
+ IdentifierLoc *Arg = new (S.Context) IdentifierLoc;
+ Arg->Ident = &S.Context.Idents.get(attrStr);
+ Arg->Loc = SourceLocation();
+
+ ArgsUnion Args(Arg);
+
// If there wasn't one, add one (with an invalid source location
// so that we don't make an AttributedType for it).
AttributeList *attr = D.getAttributePool()
.create(&S.Context.Idents.get("objc_ownership"), SourceLocation(),
/*scope*/ 0, SourceLocation(),
- &S.Context.Idents.get(attrStr), SourceLocation(),
- /*args*/ 0, 0, AttributeList::AS_GNU);
+ /*args*/ &Args, 1, AttributeList::AS_GNU);
spliceAttrIntoList(*attr, chunk.getAttrListRef());
// TODO: mark whether we did this inference?
@@ -3293,6 +3442,7 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
case AttributedType::attr_pascal:
return AttributeList::AT_Pascal;
case AttributedType::attr_pcs:
+ case AttributedType::attr_pcs_vfp:
return AttributeList::AT_Pcs;
case AttributedType::attr_pnaclcall:
return AttributeList::AT_PnaclCall;
@@ -3302,6 +3452,14 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
return AttributeList::AT_MSABI;
case AttributedType::attr_sysv_abi:
return AttributeList::AT_SysVABI;
+ case AttributedType::attr_ptr32:
+ return AttributeList::AT_Ptr32;
+ case AttributedType::attr_ptr64:
+ return AttributeList::AT_Ptr64;
+ case AttributedType::attr_sptr:
+ return AttributeList::AT_SPtr;
+ case AttributedType::attr_uptr:
+ return AttributeList::AT_UPtr;
}
llvm_unreachable("unexpected attribute kind!");
}
@@ -3318,10 +3476,10 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL,
}
TL.setAttrNameLoc(attrs->getLoc());
- if (TL.hasAttrExprOperand())
- TL.setAttrExprOperand(attrs->getArg(0));
- else if (TL.hasAttrEnumOperand())
- TL.setAttrEnumOperandLoc(attrs->getParameterLoc());
+ if (TL.hasAttrExprOperand() && attrs->isArgExpr(0))
+ TL.setAttrExprOperand(attrs->getArgAsExpr(0));
+ else if (TL.hasAttrEnumOperand() && attrs->isArgIdent(0))
+ TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc);
// FIXME: preserve this information to here.
if (TL.hasAttrOperand())
@@ -3399,9 +3557,11 @@ namespace {
TemplateSpecializationTypeLoc NamedTL = ElabTL.getNamedTypeLoc()
.castAs<TemplateSpecializationTypeLoc>();
TL.copy(NamedTL);
- }
- else
+ } else {
TL.copy(OldTL.castAs<TemplateSpecializationTypeLoc>());
+ assert(TL.getRAngleLoc() == OldTL.castAs<TemplateSpecializationTypeLoc>().getRAngleLoc());
+ }
+
}
void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
@@ -3515,6 +3675,9 @@ namespace {
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
llvm_unreachable("qualified type locs not expected here!");
}
+ void VisitDecayedTypeLoc(DecayedTypeLoc TL) {
+ llvm_unreachable("decayed type locs not expected here!");
+ }
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
fillAttributedTypeLoc(TL, Chunk.getAttrs());
@@ -3775,15 +3938,17 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
Attr.setInvalid();
return;
}
- Expr *ASArgExpr = static_cast<Expr *>(Attr.getArg(0));
+ Expr *ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
llvm::APSInt addrSpace(32);
if (ASArgExpr->isTypeDependent() || ASArgExpr->isValueDependent() ||
!ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_space_not_int)
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
<< ASArgExpr->getSourceRange();
Attr.setInvalid();
return;
@@ -3803,7 +3968,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
max = Qualifiers::MaxAddressSpace;
if (addrSpace > max) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
- << Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange();
+ << int(Qualifiers::MaxAddressSpace) << ASArgExpr->getSourceRange();
Attr.setInvalid();
return;
}
@@ -3878,9 +4043,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
if (AttrLoc.isMacroID())
AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first;
- if (!attr.getParameterName()) {
- S.Diag(AttrLoc, diag::err_attribute_argument_n_not_string)
- << "objc_ownership" << 1;
+ if (!attr.isArgIdent(0)) {
+ S.Diag(AttrLoc, diag::err_attribute_argument_type)
+ << attr.getName() << AANT_ArgumentString;
attr.setInvalid();
return true;
}
@@ -3890,18 +4055,19 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
if (!S.getLangOpts().ObjCAutoRefCount)
return true;
+ IdentifierInfo *II = attr.getArgAsIdent(0)->Ident;
Qualifiers::ObjCLifetime lifetime;
- if (attr.getParameterName()->isStr("none"))
+ if (II->isStr("none"))
lifetime = Qualifiers::OCL_ExplicitNone;
- else if (attr.getParameterName()->isStr("strong"))
+ else if (II->isStr("strong"))
lifetime = Qualifiers::OCL_Strong;
- else if (attr.getParameterName()->isStr("weak"))
+ else if (II->isStr("weak"))
lifetime = Qualifiers::OCL_Weak;
- else if (attr.getParameterName()->isStr("autoreleasing"))
+ else if (II->isStr("autoreleasing"))
lifetime = Qualifiers::OCL_Autoreleasing;
else {
S.Diag(AttrLoc, diag::warn_attribute_type_not_supported)
- << "objc_ownership" << attr.getParameterName();
+ << attr.getName() << II;
attr.setInvalid();
return true;
}
@@ -3942,8 +4108,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
case Qualifiers::OCL_Weak: name = "__weak"; break;
case Qualifiers::OCL_Autoreleasing: name = "__autoreleasing"; break;
}
- S.Diag(AttrLoc, diag::warn_objc_object_attribute_wrong_type)
- << name << type;
+ S.Diag(AttrLoc, diag::warn_type_attribute_wrong_type) << name
+ << TDS_ObjCObjOrBlock << type;
}
QualType origType = type;
@@ -4012,27 +4178,30 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state,
attr.setInvalid();
return true;
}
-
+
// Check the attribute arguments.
- if (!attr.getParameterName()) {
- S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
- << "objc_gc" << 1;
+ if (!attr.isArgIdent(0)) {
+ S.Diag(attr.getLoc(), diag::err_attribute_argument_type)
+ << attr.getName() << AANT_ArgumentString;
attr.setInvalid();
return true;
}
Qualifiers::GC GCAttr;
- if (attr.getNumArgs() != 0) {
- S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ if (attr.getNumArgs() > 1) {
+ S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << attr.getName() << 1;
attr.setInvalid();
return true;
}
- if (attr.getParameterName()->isStr("weak"))
+
+ IdentifierInfo *II = attr.getArgAsIdent(0)->Ident;
+ if (II->isStr("weak"))
GCAttr = Qualifiers::Weak;
- else if (attr.getParameterName()->isStr("strong"))
+ else if (II->isStr("strong"))
GCAttr = Qualifiers::Strong;
else {
S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported)
- << "objc_gc" << attr.getParameterName();
+ << attr.getName() << II;
attr.setInvalid();
return true;
}
@@ -4178,6 +4347,109 @@ namespace {
};
}
+static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
+ AttributeList &Attr,
+ QualType &Type) {
+ Sema &S = State.getSema();
+
+ AttributeList::Kind Kind = Attr.getKind();
+ QualType Desugared = Type;
+ const AttributedType *AT = dyn_cast<AttributedType>(Type);
+ while (AT) {
+ AttributedType::Kind CurAttrKind = AT->getAttrKind();
+
+ // You cannot specify duplicate type attributes, so if the attribute has
+ // already been applied, flag it.
+ if (getAttrListKind(CurAttrKind) == Kind) {
+ S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact)
+ << Attr.getName();
+ return true;
+ }
+
+ // You cannot have both __sptr and __uptr on the same type, nor can you
+ // have __ptr32 and __ptr64.
+ if ((CurAttrKind == AttributedType::attr_ptr32 &&
+ Kind == AttributeList::AT_Ptr64) ||
+ (CurAttrKind == AttributedType::attr_ptr64 &&
+ Kind == AttributeList::AT_Ptr32)) {
+ S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << "'__ptr32'" << "'__ptr64'";
+ return true;
+ } else if ((CurAttrKind == AttributedType::attr_sptr &&
+ Kind == AttributeList::AT_UPtr) ||
+ (CurAttrKind == AttributedType::attr_uptr &&
+ Kind == AttributeList::AT_SPtr)) {
+ S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << "'__sptr'" << "'__uptr'";
+ return true;
+ }
+
+ Desugared = AT->getEquivalentType();
+ AT = dyn_cast<AttributedType>(Desugared);
+ }
+
+ // Pointer type qualifiers can only operate on pointer types, but not
+ // pointer-to-member types.
+ if (!isa<PointerType>(Desugared)) {
+ S.Diag(Attr.getLoc(), Type->isMemberPointerType() ?
+ diag::err_attribute_no_member_pointers :
+ diag::err_attribute_pointers_only) << Attr.getName();
+ return true;
+ }
+
+ AttributedType::Kind TAK;
+ switch (Kind) {
+ default: llvm_unreachable("Unknown attribute kind");
+ case AttributeList::AT_Ptr32: TAK = AttributedType::attr_ptr32; break;
+ case AttributeList::AT_Ptr64: TAK = AttributedType::attr_ptr64; break;
+ case AttributeList::AT_SPtr: TAK = AttributedType::attr_sptr; break;
+ case AttributeList::AT_UPtr: TAK = AttributedType::attr_uptr; break;
+ }
+
+ Type = S.Context.getAttributedType(TAK, Type, Type);
+ return false;
+}
+
+static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
+ assert(!Attr.isInvalid());
+ switch (Attr.getKind()) {
+ default:
+ llvm_unreachable("not a calling convention attribute");
+ case AttributeList::AT_CDecl:
+ return AttributedType::attr_cdecl;
+ case AttributeList::AT_FastCall:
+ return AttributedType::attr_fastcall;
+ case AttributeList::AT_StdCall:
+ return AttributedType::attr_stdcall;
+ case AttributeList::AT_ThisCall:
+ return AttributedType::attr_thiscall;
+ case AttributeList::AT_Pascal:
+ return AttributedType::attr_pascal;
+ case AttributeList::AT_Pcs: {
+ // The attribute may have had a fixit applied where we treated an
+ // identifier as a string literal. The contents of the string are valid,
+ // but the form may not be.
+ StringRef Str;
+ if (Attr.isArgExpr(0))
+ Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString();
+ else
+ Str = Attr.getArgAsIdent(0)->Ident->getName();
+ return llvm::StringSwitch<AttributedType::Kind>(Str)
+ .Case("aapcs", AttributedType::attr_pcs)
+ .Case("aapcs-vfp", AttributedType::attr_pcs_vfp);
+ }
+ case AttributeList::AT_PnaclCall:
+ return AttributedType::attr_pnaclcall;
+ case AttributeList::AT_IntelOclBicc:
+ return AttributedType::attr_inteloclbicc;
+ case AttributeList::AT_MSABI:
+ return AttributedType::attr_ms_abi;
+ case AttributeList::AT_SysVABI:
+ return AttributedType::attr_sysv_abi;
+ }
+ llvm_unreachable("unexpected attribute kind!");
+}
+
/// Process an individual function attribute. Returns true to
/// indicate that the attribute was handled, false if it wasn't.
static bool handleFunctionTypeAttr(TypeProcessingState &state,
@@ -4254,34 +4526,41 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
const FunctionType *fn = unwrapped.get();
CallingConv CCOld = fn->getCallConv();
- if (S.Context.getCanonicalCallConv(CC) ==
- S.Context.getCanonicalCallConv(CCOld)) {
- FunctionType::ExtInfo EI= unwrapped.get()->getExtInfo().withCallingConv(CC);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
- return true;
- }
+ AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr);
- if (CCOld != (S.LangOpts.MRTD ? CC_X86StdCall : CC_Default)) {
- // Should we diagnose reapplications of the same convention?
- S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
- << FunctionType::getNameForCallConv(CC)
- << FunctionType::getNameForCallConv(CCOld);
- attr.setInvalid();
- return true;
+ if (CCOld != CC) {
+ // Error out on when there's already an attribute on the type
+ // and the CCs don't match.
+ const AttributedType *AT = S.getCallingConvAttributedType(type);
+ if (AT && AT->getAttrKind() != CCAttrKind) {
+ S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << FunctionType::getNameForCallConv(CC)
+ << FunctionType::getNameForCallConv(CCOld);
+ attr.setInvalid();
+ return true;
+ }
}
- // Diagnose the use of X86 fastcall on varargs or unprototyped functions.
- if (CC == CC_X86FastCall) {
- if (isa<FunctionNoProtoType>(fn)) {
- S.Diag(attr.getLoc(), diag::err_cconv_knr)
- << FunctionType::getNameForCallConv(CC);
+ // Diagnose use of callee-cleanup calling convention on variadic functions.
+ if (isCalleeCleanup(CC)) {
+ const FunctionProtoType *FnP = dyn_cast<FunctionProtoType>(fn);
+ if (FnP && FnP->isVariadic()) {
+ unsigned DiagID = diag::err_cconv_varargs;
+ // stdcall and fastcall are ignored with a warning for GCC and MS
+ // compatibility.
+ if (CC == CC_X86StdCall || CC == CC_X86FastCall)
+ DiagID = diag::warn_cconv_varargs;
+
+ S.Diag(attr.getLoc(), DiagID) << FunctionType::getNameForCallConv(CC);
attr.setInvalid();
return true;
}
+ }
- const FunctionProtoType *FnP = cast<FunctionProtoType>(fn);
- if (FnP->isVariadic()) {
- S.Diag(attr.getLoc(), diag::err_cconv_varargs)
+ // Diagnose the use of X86 fastcall on unprototyped functions.
+ if (CC == CC_X86FastCall) {
+ if (isa<FunctionNoProtoType>(fn)) {
+ S.Diag(attr.getLoc(), diag::err_cconv_knr)
<< FunctionType::getNameForCallConv(CC);
attr.setInvalid();
return true;
@@ -4297,27 +4576,66 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
}
}
+ // Modify the CC from the wrapped function type, wrap it all back, and then
+ // wrap the whole thing in an AttributedType as written. The modified type
+ // might have a different CC if we ignored the attribute.
FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ QualType Equivalent =
+ unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ type = S.Context.getAttributedType(CCAttrKind, type, Equivalent);
return true;
}
+void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) {
+ const FunctionType *FT = T->castAs<FunctionType>();
+ bool IsVariadic = (isa<FunctionProtoType>(FT) &&
+ cast<FunctionProtoType>(FT)->isVariadic());
+ CallingConv CC = FT->getCallConv();
+
+ // Only adjust types with the default convention. For example, on Windows we
+ // should adjust a __cdecl type to __thiscall for instance methods, and a
+ // __thiscall type to __cdecl for static methods.
+ CallingConv DefaultCC =
+ Context.getDefaultCallingConvention(IsVariadic, IsStatic);
+ if (CC != DefaultCC)
+ return;
+
+ // Check if there was an explicit attribute, but only look through parens.
+ // The intent is to look for an attribute on the current declarator, but not
+ // one that came from a typedef.
+ QualType R = T.IgnoreParens();
+ while (const AttributedType *AT = dyn_cast<AttributedType>(R)) {
+ if (AT->isCallingConv())
+ return;
+ R = AT->getModifiedType().IgnoreParens();
+ }
+
+ // FIXME: This loses sugar. This should probably be fixed with an implicit
+ // AttributedType node that adjusts the convention.
+ CC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
+ FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(CC));
+ FunctionTypeUnwrapper Unwrapped(*this, T);
+ T = Unwrapped.wrap(*this, FT);
+}
+
/// 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;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
Attr.setInvalid();
return;
}
- Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
+ Expr *sizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(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();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << sizeExpr->getSourceRange();
Attr.setInvalid();
return;
}
@@ -4348,21 +4666,25 @@ static void HandleVectorSizeAttr(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;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
Attr.setInvalid();
return;
}
- Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
+ Expr *sizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
llvm::APSInt vecSize(32);
if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "vector_size" << sizeExpr->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << sizeExpr->getSourceRange();
Attr.setInvalid();
return;
}
- // the base type must be integer or float, and can't already be a vector.
- if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) {
+ // The base type must be integer (not Boolean or enumeration) or float, and
+ // can't already be a vector.
+ if (!CurType->isBuiltinType() || CurType->isBooleanType() ||
+ (!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
Attr.setInvalid();
return;
@@ -4378,6 +4700,12 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
Attr.setInvalid();
return;
}
+ if (VectorType::isVectorSizeTooLarge(vectorSize / typeSize)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_size_too_large)
+ << sizeExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
if (vectorSize == 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
<< sizeExpr->getSourceRange();
@@ -4396,14 +4724,21 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
static void HandleExtVectorTypeAttr(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)
+ << Attr.getName() << 1;
+ return;
+ }
+
Expr *sizeExpr;
// Special case where the argument is a template id.
- if (Attr.getParameterName()) {
+ if (Attr.isArgIdent(0)) {
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
UnqualifiedId id;
- id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
+ id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
id, false, false);
@@ -4412,12 +4747,7 @@ static void HandleExtVectorTypeAttr(QualType &CurType,
sizeExpr = Size.get();
} else {
- // check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- return;
- }
- sizeExpr = Attr.getArg(0);
+ sizeExpr = Attr.getArgAsExpr(0);
}
// Create the vector type.
@@ -4426,6 +4756,43 @@ static void HandleExtVectorTypeAttr(QualType &CurType,
CurType = T;
}
+static bool isPermittedNeonBaseType(QualType &Ty,
+ VectorType::VectorKind VecKind,
+ bool IsAArch64) {
+ const BuiltinType *BTy = Ty->getAs<BuiltinType>();
+ if (!BTy)
+ return false;
+
+ if (VecKind == VectorType::NeonPolyVector) {
+ if (IsAArch64) {
+ // AArch64 polynomial vectors are unsigned and support poly64.
+ return BTy->getKind() == BuiltinType::UChar ||
+ BTy->getKind() == BuiltinType::UShort ||
+ BTy->getKind() == BuiltinType::ULongLong;
+ } else {
+ // AArch32 polynomial vector are signed.
+ return BTy->getKind() == BuiltinType::SChar ||
+ BTy->getKind() == BuiltinType::Short;
+ }
+ }
+
+ // Non-polynomial vector types: the usual suspects are allowed, as well as
+ // float64_t on AArch64.
+ if (IsAArch64 && BTy->getKind() == BuiltinType::Double)
+ return true;
+
+ return BTy->getKind() == BuiltinType::SChar ||
+ BTy->getKind() == BuiltinType::UChar ||
+ BTy->getKind() == BuiltinType::Short ||
+ BTy->getKind() == BuiltinType::UShort ||
+ BTy->getKind() == BuiltinType::Int ||
+ BTy->getKind() == BuiltinType::UInt ||
+ BTy->getKind() == BuiltinType::LongLong ||
+ BTy->getKind() == BuiltinType::ULongLong ||
+ BTy->getKind() == BuiltinType::Float ||
+ BTy->getKind() == BuiltinType::Half;
+}
+
/// HandleNeonVectorTypeAttr - The "neon_vector_type" and
/// "neon_polyvector_type" attributes are used to create vector types that
/// are mangled according to ARM's ABI. Otherwise, these types are identical
@@ -4435,43 +4802,41 @@ static void HandleExtVectorTypeAttr(QualType &CurType,
/// match one of the standard Neon vector types.
static void HandleNeonVectorTypeAttr(QualType& CurType,
const AttributeList &Attr, Sema &S,
- VectorType::VectorKind VecKind,
- const char *AttrName) {
+ VectorType::VectorKind VecKind) {
+ // Target must have NEON
+ if (!S.Context.getTargetInfo().hasFeature("neon")) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr.getName();
+ Attr.setInvalid();
+ return;
+ }
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
Attr.setInvalid();
return;
}
// The number of elements must be an ICE.
- Expr *numEltsExpr = static_cast<Expr *>(Attr.getArg(0));
+ Expr *numEltsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
llvm::APSInt numEltsInt(32);
if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() ||
!numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << AttrName << numEltsExpr->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << numEltsExpr->getSourceRange();
Attr.setInvalid();
return;
}
// Only certain element types are supported for Neon vectors.
- const BuiltinType* BTy = CurType->getAs<BuiltinType>();
- if (!BTy ||
- (VecKind == VectorType::NeonPolyVector &&
- BTy->getKind() != BuiltinType::SChar &&
- BTy->getKind() != BuiltinType::Short) ||
- (BTy->getKind() != BuiltinType::SChar &&
- BTy->getKind() != BuiltinType::UChar &&
- BTy->getKind() != BuiltinType::Short &&
- BTy->getKind() != BuiltinType::UShort &&
- BTy->getKind() != BuiltinType::Int &&
- BTy->getKind() != BuiltinType::UInt &&
- BTy->getKind() != BuiltinType::LongLong &&
- BTy->getKind() != BuiltinType::ULongLong &&
- BTy->getKind() != BuiltinType::Float)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) <<CurType;
+ llvm::Triple::ArchType Arch =
+ S.Context.getTargetInfo().getTriple().getArch();
+ if (!isPermittedNeonBaseType(CurType, VecKind,
+ Arch == llvm::Triple::aarch64)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
Attr.setInvalid();
return;
}
+
// The total size of the vector must be 64 or 128 bits.
unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
unsigned numElts = static_cast<unsigned>(numEltsInt.getZExtValue());
@@ -4565,13 +4930,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
break;
case AttributeList::AT_NeonVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
- VectorType::NeonVector, "neon_vector_type");
+ VectorType::NeonVector);
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_NeonPolyVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
- VectorType::NeonPolyVector,
- "neon_polyvector_type");
+ VectorType::NeonPolyVector);
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_OpenCLImageAccess:
@@ -4580,12 +4944,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
break;
case AttributeList::AT_Win64:
- case AttributeList::AT_Ptr32:
- case AttributeList::AT_Ptr64:
- // FIXME: Don't ignore these. We have partial handling for them as
- // declaration attributes in SemaDeclAttr.cpp; that should be moved here.
attr.setUsedAsTypeAttr();
break;
+ MS_TYPE_ATTRS_CASELIST:
+ if (!handleMSPointerTypeQualifierAttr(state, attr, type))
+ attr.setUsedAsTypeAttr();
+ break;
case AttributeList::AT_NSReturnsRetained:
if (!state.getSema().getLangOpts().ObjCAutoRefCount)
@@ -4627,41 +4991,46 @@ bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser){
// Fast path the case where the type is already complete.
if (!T->isIncompleteType())
+ // FIXME: The definition might not be visible.
return false;
// Incomplete array types may be completed by the initializer attached to
- // their definitions. For static data members of class templates we need to
- // instantiate the definition to get this initializer and complete the type.
+ // their definitions. For static data members of class templates and for
+ // variable templates, we need to instantiate the definition to get this
+ // initializer and complete the type.
if (T->isIncompleteArrayType()) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (Var->isStaticDataMember() &&
- Var->getInstantiatedFromStaticDataMember()) {
+ if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
+ SourceLocation PointOfInstantiation = E->getExprLoc();
- MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
- assert(MSInfo && "Missing member specialization information?");
- if (MSInfo->getTemplateSpecializationKind()
- != TSK_ExplicitSpecialization) {
+ if (MemberSpecializationInfo *MSInfo =
+ Var->getMemberSpecializationInfo()) {
// If we don't already have a point of instantiation, this is it.
if (MSInfo->getPointOfInstantiation().isInvalid()) {
- MSInfo->setPointOfInstantiation(E->getLocStart());
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
// This is a modification of an existing AST node. Notify
// listeners.
if (ASTMutationListener *L = getASTMutationListener())
L->StaticDataMemberInstantiated(Var);
}
+ } else {
+ VarTemplateSpecializationDecl *VarSpec =
+ cast<VarTemplateSpecializationDecl>(Var);
+ if (VarSpec->getPointOfInstantiation().isInvalid())
+ VarSpec->setPointOfInstantiation(PointOfInstantiation);
+ }
- InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var);
+ InstantiateVariableDefinition(PointOfInstantiation, Var);
- // Update the type to the newly instantiated definition's type both
- // here and within the expression.
- if (VarDecl *Def = Var->getDefinition()) {
- DRE->setDecl(Def);
- T = Def->getType();
- DRE->setType(T);
- E->setType(T);
- }
+ // Update the type to the newly instantiated definition's type both
+ // here and within the expression.
+ if (VarDecl *Def = Var->getDefinition()) {
+ DRE->setDecl(Def);
+ T = Def->getType();
+ DRE->setType(T);
+ E->setType(T);
}
// We still go on to try to complete the type independently, as it
@@ -4720,6 +5089,20 @@ bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
/// @c false otherwise.
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser) {
+ if (RequireCompleteTypeImpl(Loc, T, Diagnoser))
+ return true;
+ if (const TagType *Tag = T->getAs<TagType>()) {
+ if (!Tag->getDecl()->isCompleteDefinitionRequired()) {
+ Tag->getDecl()->setCompleteDefinitionRequired();
+ Consumer.HandleTagDeclRequiredDefinition(Tag->getDecl());
+ }
+ }
+ return false;
+}
+
+/// \brief The implementation of RequireCompleteType
+bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
+ TypeDiagnoser &Diagnoser) {
// FIXME: Add this assertion to make sure we always get instantiation points.
// assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");
// FIXME: Add this assertion to help us flush out problems with
@@ -4732,7 +5115,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
NamedDecl *Def = 0;
if (!T->isIncompleteType(&Def)) {
// If we know about the definition but it is not visible, complain.
- if (!Diagnoser.Suppressed && Def && !LookupResult::isVisible(Def)) {
+ if (!Diagnoser.Suppressed && Def && !LookupResult::isVisible(*this, Def)) {
// Suppress this error outside of a SFINAE context if we've already
// emitted the error once for this type. There's no usefulness in
// repeating the diagnostic.
@@ -4752,6 +5135,14 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
return false;
}
+ // FIXME: If there's an unimported definition of this type in a module (for
+ // instance, because we forward declared it, then imported the definition),
+ // import that definition now.
+ // FIXME: What about other cases where an import extends a redeclaration
+ // chain for a declaration that can be accessed through a mechanism other
+ // than name lookup (eg, referenced in a template, or a variable whose type
+ // could be completed by the module)?
+
const TagType *Tag = T->getAs<TagType>();
const ObjCInterfaceType *IFace = 0;
@@ -4814,6 +5205,12 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
return true;
// We have an incomplete type. Produce a diagnostic.
+ if (Ident___float128 &&
+ T == Context.getTypeDeclType(Context.getFloat128StubType())) {
+ Diag(Loc, diag::err_typecheck_decl_incomplete_type___float128);
+ return true;
+ }
+
Diagnoser.diagnose(*this, Loc, T);
// If the type was a forward declaration of a class/struct/union
@@ -4828,6 +5225,11 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
if (IFace && !IFace->getDecl()->isInvalidDecl())
Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
+ // If we have external information that we can use to suggest a fix,
+ // produce a note.
+ if (ExternalSource)
+ ExternalSource->MaybeDiagnoseMissingCompleteType(Loc, T);
+
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp
index 2f7701227da6..45067dee9b8d 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp
@@ -26,21 +26,67 @@ bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D,
return false;
}
+static void HandleARMInterruptAttr(Decl *d,
+ const AttributeList &Attr, Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() > 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << 1;
+ return;
+ }
+
+ StringRef Str;
+ SourceLocation ArgLoc;
+
+ if (Attr.getNumArgs() == 0)
+ Str = "";
+ else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
+ return;
+
+ ARMInterruptAttr::InterruptType Kind;
+ if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+ << Attr.getName() << Str << ArgLoc;
+ return;
+ }
+
+ unsigned Index = Attr.getAttributeSpellingListIndex();
+ d->addAttr(::new (S.Context)
+ ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index));
+}
+
+namespace {
+ class ARMAttributesSema : public TargetAttributesSema {
+ public:
+ ARMAttributesSema() { }
+ bool ProcessDeclAttribute(Scope *scope, Decl *D,
+ const AttributeList &Attr, Sema &S) const {
+ if (Attr.getName()->getName() == "interrupt") {
+ HandleARMInterruptAttr(D, Attr, S);
+ return true;
+ }
+ return false;
+ }
+ };
+}
+
static void HandleMSP430InterruptAttr(Decl *d,
const AttributeList &Attr, Sema &S) {
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
return;
}
// FIXME: Check for decl - it should be void ()(void).
- Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
+ Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
llvm::APSInt NumParams(32);
if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "interrupt" << NumParamsExpr->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << NumParamsExpr->getSourceRange();
return;
}
@@ -71,61 +117,13 @@ namespace {
};
}
-static void HandleMBlazeInterruptHandlerAttr(Decl *d, const AttributeList &Attr,
- Sema &S) {
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- return;
- }
-
- // FIXME: Check for decl - it should be void ()(void).
-
- d->addAttr(::new (S.Context) MBlazeInterruptHandlerAttr(Attr.getLoc(),
- S.Context));
- d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
-}
-
-static void HandleMBlazeSaveVolatilesAttr(Decl *d, const AttributeList &Attr,
- Sema &S) {
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- return;
- }
-
- // FIXME: Check for decl - it should be void ()(void).
-
- d->addAttr(::new (S.Context) MBlazeSaveVolatilesAttr(Attr.getLoc(),
- S.Context));
- d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
-}
-
-
-namespace {
- class MBlazeAttributesSema : public TargetAttributesSema {
- public:
- MBlazeAttributesSema() { }
- bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr,
- Sema &S) const {
- if (Attr.getName()->getName() == "interrupt_handler") {
- HandleMBlazeInterruptHandlerAttr(D, Attr, S);
- return true;
- } else if (Attr.getName()->getName() == "save_volatiles") {
- HandleMBlazeSaveVolatilesAttr(D, Attr, S);
- return true;
- }
- return false;
- }
- };
-}
-
static void HandleX86ForceAlignArgPointerAttr(Decl *D,
const AttributeList& Attr,
Sema &S) {
// Check the attribute arguments.
if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 0;
return;
}
@@ -161,6 +159,15 @@ DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
if (D->hasAttr<DLLImportAttr>())
return NULL;
+ if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->hasDefinition()) {
+ // dllimport cannot be applied to definitions.
+ Diag(D->getLocation(), diag::warn_attribute_invalid_on_definition)
+ << "dllimport";
+ return NULL;
+ }
+ }
+
return ::new (Context) DLLImportAttr(Range, Context,
AttrSpellingListIndex);
}
@@ -168,7 +175,8 @@ DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 0;
return;
}
@@ -214,7 +222,8 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 0;
return;
}
@@ -270,8 +279,9 @@ namespace {
static void HandleMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
- if (Attr.hasParameterOrArguments()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ if (Attr.getNumArgs()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 0;
return;
}
// Attribute can only be applied to function types.
@@ -286,8 +296,9 @@ static void HandleMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
static void HandleNoMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
- if (Attr.hasParameterOrArguments()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ if (Attr.getNumArgs()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 0;
return;
}
// Attribute can only be applied to function types.
@@ -325,10 +336,11 @@ const TargetAttributesSema &Sema::getTargetAttributesSema() const {
const llvm::Triple &Triple(Context.getTargetInfo().getTriple());
switch (Triple.getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ return *(TheTargetAttributesSema = new ARMAttributesSema);
case llvm::Triple::msp430:
return *(TheTargetAttributesSema = new MSP430AttributesSema);
- case llvm::Triple::mblaze:
- return *(TheTargetAttributesSema = new MBlazeAttributesSema);
case llvm::Triple::x86:
case llvm::Triple::x86_64:
return *(TheTargetAttributesSema = new X86AttributesSema);
diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
index faa47e826eee..f940da4d276d 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
@@ -24,6 +24,7 @@
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtOpenMP.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Lookup.h"
@@ -141,7 +142,11 @@ public:
///
/// Subclasses may override this function to specify when the transformation
/// should rebuild all AST nodes.
- bool AlwaysRebuild() { return false; }
+ ///
+ /// We must always rebuild all AST nodes when performing variadic template
+ /// pack expansion, in order to avoid violating the AST invariant that each
+ /// statement node appears at most once in its containing declaration.
+ bool AlwaysRebuild() { return SemaRef.ArgumentPackSubstitutionIndex != -1; }
/// \brief Returns the location of the entity being transformed, if that
/// information was not available elsewhere in the AST.
@@ -313,6 +318,16 @@ public:
/// \returns the transformed statement.
StmtResult TransformStmt(Stmt *S);
+ /// \brief Transform the given statement.
+ ///
+ /// By default, this routine transforms a statement by delegating to the
+ /// appropriate TransformOMPXXXClause function to transform a specific kind
+ /// of clause. Subclasses may override this function to transform statements
+ /// using some other mechanism.
+ ///
+ /// \returns the transformed OpenMP clause.
+ OMPClause *TransformOMPClause(OMPClause *S);
+
/// \brief Transform the given expression.
///
/// By default, this routine transforms an expression by delegating to the
@@ -533,8 +548,7 @@ public:
CXXRecordDecl *ThisContext,
unsigned ThisTypeQuals);
- StmtResult
- TransformSEHHandler(Stmt *Handler);
+ StmtResult TransformSEHHandler(Stmt *Handler);
QualType
TransformTemplateSpecializationType(TypeLocBuilder &TLB,
@@ -579,21 +593,37 @@ public:
StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
ExprResult TransformCXXNamedCastExpr(CXXNamedCastExpr *E);
-
+
+ typedef std::pair<ExprResult, QualType> InitCaptureInfoTy;
/// \brief Transform the captures and body of a lambda expression.
- ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl *CallOperator);
+ ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl *CallOperator,
+ ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes);
+
+ TemplateParameterList *TransformTemplateParameterList(
+ TemplateParameterList *TPL) {
+ return TPL;
+ }
ExprResult TransformAddressOfOperand(Expr *E);
ExprResult TransformDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E,
bool IsAddressOfOperand);
+// FIXME: We use LLVM_ATTRIBUTE_NOINLINE because inlining causes a ridiculous
+// amount of stack usage with clang.
#define STMT(Node, Parent) \
+ LLVM_ATTRIBUTE_NOINLINE \
StmtResult Transform##Node(Node *S);
#define EXPR(Node, Parent) \
+ LLVM_ATTRIBUTE_NOINLINE \
ExprResult Transform##Node(Node *E);
#define ABSTRACT_STMT(Stmt)
#include "clang/AST/StmtNodes.inc"
+#define OPENMP_CLAUSE(Name, Class) \
+ LLVM_ATTRIBUTE_NOINLINE \
+ OMPClause *Transform ## Class(Class *S);
+#include "clang/Basic/OpenMPKinds.def"
+
/// \brief Build a new pointer type given its pointee type.
///
/// By default, performs semantic analysis when building the pointer type.
@@ -767,7 +797,8 @@ public:
// Note, IsDependent is always false here: we implicitly convert an 'auto'
// which has been deduced to a dependent type into an undeduced 'auto', so
// that we'll retry deduction after the transformation.
- return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto);
+ return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto,
+ /*IsDependent*/ false);
}
/// \brief Build a new template specialization type.
@@ -1163,10 +1194,9 @@ public:
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- StmtResult RebuildDeclStmt(Decl **Decls, unsigned NumDecls,
- SourceLocation StartLoc,
- SourceLocation EndLoc) {
- Sema::DeclGroupPtrTy DG = getSema().BuildDeclaratorGroup(Decls, NumDecls);
+ StmtResult RebuildDeclStmt(llvm::MutableArrayRef<Decl *> Decls,
+ SourceLocation StartLoc, SourceLocation EndLoc) {
+ Sema::DeclGroupPtrTy DG = getSema().BuildDeclaratorGroup(Decls);
return getSema().ActOnDeclStmt(DG, StartLoc, EndLoc);
}
@@ -1256,6 +1286,63 @@ public:
return getSema().BuildObjCAtThrowStmt(AtLoc, Operand);
}
+ /// \brief Build a new OpenMP parallel directive.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildOMPParallelDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPParallelDirective(Clauses, AStmt,
+ StartLoc, EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'default' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPDefaultClause(OpenMPDefaultClauseKind Kind,
+ SourceLocation KindKwLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPDefaultClause(Kind, KindKwLoc,
+ StartLoc, LParenLoc, EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'private' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPPrivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'firstprivate' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPFirstprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ OMPClause *RebuildOMPSharedClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -1333,9 +1420,8 @@ public:
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- StmtResult RebuildCXXTryStmt(SourceLocation TryLoc,
- Stmt *TryBlock,
- MultiStmtArg Handlers) {
+ StmtResult RebuildCXXTryStmt(SourceLocation TryLoc, Stmt *TryBlock,
+ ArrayRef<Stmt *> Handlers) {
return getSema().ActOnCXXTryBlock(TryLoc, TryBlock, Handlers);
}
@@ -1392,22 +1478,18 @@ public:
return getSema().FinishCXXForRangeStmt(ForRange, Body);
}
- StmtResult RebuildSEHTryStmt(bool IsCXXTry,
- SourceLocation TryLoc,
- Stmt *TryBlock,
- Stmt *Handler) {
- return getSema().ActOnSEHTryBlock(IsCXXTry,TryLoc,TryBlock,Handler);
+ StmtResult RebuildSEHTryStmt(bool IsCXXTry, SourceLocation TryLoc,
+ Stmt *TryBlock, Stmt *Handler) {
+ return getSema().ActOnSEHTryBlock(IsCXXTry, TryLoc, TryBlock, Handler);
}
- StmtResult RebuildSEHExceptStmt(SourceLocation Loc,
- Expr *FilterExpr,
+ StmtResult RebuildSEHExceptStmt(SourceLocation Loc, Expr *FilterExpr,
Stmt *Block) {
- return getSema().ActOnSEHExceptBlock(Loc,FilterExpr,Block);
+ return getSema().ActOnSEHExceptBlock(Loc, FilterExpr, Block);
}
- StmtResult RebuildSEHFinallyStmt(SourceLocation Loc,
- Stmt *Block) {
- return getSema().ActOnSEHFinallyBlock(Loc,Block);
+ StmtResult RebuildSEHFinallyStmt(SourceLocation Loc, Stmt *Block) {
+ return getSema().ActOnSEHFinallyBlock(Loc, Block);
}
/// \brief Build a new expression that references a declaration.
@@ -1767,12 +1849,10 @@ public:
SourceLocation DefaultLoc,
SourceLocation RParenLoc,
Expr *ControllingExpr,
- TypeSourceInfo **Types,
- Expr **Exprs,
- unsigned NumAssocs) {
+ ArrayRef<TypeSourceInfo *> Types,
+ ArrayRef<Expr *> Exprs) {
return getSema().CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
- ControllingExpr, Types, Exprs,
- NumAssocs);
+ ControllingExpr, Types, Exprs);
}
/// \brief Build a new overloaded operator call expression.
@@ -2485,6 +2565,14 @@ public:
return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.take()));
}
+ /// \brief Build a new convert vector expression.
+ ExprResult RebuildConvertVectorExpr(SourceLocation BuiltinLoc,
+ Expr *SrcExpr, TypeSourceInfo *DstTInfo,
+ SourceLocation RParenLoc) {
+ return SemaRef.SemaConvertVectorExpr(SrcExpr, DstTInfo,
+ BuiltinLoc, RParenLoc);
+ }
+
/// \brief Build a new template argument pack expansion.
///
/// By default, performs semantic analysis to build a new pack expansion
@@ -2603,6 +2691,23 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
return SemaRef.Owned(S);
}
+template<typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPClause(OMPClause *S) {
+ if (!S)
+ return S;
+
+ switch (S->getClauseKind()) {
+ default: break;
+ // Transform individual clause nodes
+#define OPENMP_CLAUSE(Name, Class) \
+ case OMPC_ ## Name : \
+ return getDerived().Transform ## Class(cast<Class>(S));
+#include "clang/Basic/OpenMPKinds.def"
+ }
+
+ return S;
+}
+
template<typename Derived>
ExprResult TreeTransform<Derived>::TransformExpr(Expr *E) {
@@ -2632,12 +2737,19 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
Init = ExprTemp->getSubExpr();
+ if (MaterializeTemporaryExpr *MTE = dyn_cast<MaterializeTemporaryExpr>(Init))
+ Init = MTE->GetTemporaryExpr();
+
while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init))
Init = Binder->getSubExpr();
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init))
Init = ICE->getSubExprAsWritten();
+ if (CXXStdInitializerListExpr *ILE =
+ dyn_cast<CXXStdInitializerListExpr>(Init))
+ return TransformInitializer(ILE->getSubExpr(), CXXDirectInit);
+
// If this is not a direct-initializer, we only need to reconstruct
// InitListExprs. Other forms of copy-initialization will be a no-op if
// the initializer is already the right type.
@@ -2675,7 +2787,7 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
Construct->getType());
// Build a ParenListExpr to represent anything else.
- SourceRange Parens = Construct->getParenRange();
+ SourceRange Parens = Construct->getParenOrBraceRange();
return getDerived().RebuildParenListExpr(Parens.getBegin(), NewArgs,
Parens.getEnd());
}
@@ -3228,8 +3340,8 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
SourceLocation Ellipsis;
Optional<unsigned> OrigNumExpansions;
TemplateArgumentLoc Pattern
- = In.getPackExpansionPattern(Ellipsis, OrigNumExpansions,
- getSema().Context);
+ = getSema().getTemplateArgumentPackExpansionPattern(
+ In, Ellipsis, OrigNumExpansions);
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
@@ -3421,12 +3533,13 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
Qs.removeObjCLifetime();
Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(),
Qs);
- Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto());
+ Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto(),
+ AutoTy->isDependentType());
TLB.TypeWasModifiedSafely(Result);
} else {
// Otherwise, complain about the addition of a qualifier to an
// already-qualified type.
- SourceRange R = TLB.getTemporaryTypeLoc(Result).getSourceRange();
+ SourceRange R = T.getUnqualifiedLoc().getSourceRange();
SemaRef.Diag(R.getBegin(), diag::err_attr_objc_ownership_redundant)
<< Result << R;
@@ -3581,6 +3694,22 @@ QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB,
}
template<typename Derived>
+QualType TreeTransform<Derived>::TransformDecayedType(TypeLocBuilder &TLB,
+ DecayedTypeLoc TL) {
+ QualType OriginalType = getDerived().TransformType(TLB, TL.getOriginalLoc());
+ if (OriginalType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ OriginalType != TL.getOriginalLoc().getType())
+ Result = SemaRef.Context.getDecayedType(OriginalType);
+ TLB.push<DecayedTypeLoc>(Result);
+ // Nothing to set for DecayedTypeLoc.
+ return Result;
+}
+
+template<typename Derived>
QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB,
PointerTypeLoc TL) {
QualType PointeeType
@@ -5584,8 +5713,7 @@ TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) {
if (!getDerived().AlwaysRebuild() && !DeclChanged)
return SemaRef.Owned(S);
- return getDerived().RebuildDeclStmt(Decls.data(), Decls.size(),
- S->getStartLoc(), S->getEndLoc());
+ return getDerived().RebuildDeclStmt(Decls, S->getStartLoc(), S->getEndLoc());
}
template<typename Derived>
@@ -5879,23 +6007,19 @@ TreeTransform<Derived>::TransformObjCForCollectionStmt(
Body.get());
}
-
-template<typename Derived>
-StmtResult
-TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
// Transform the exception declaration, if any.
VarDecl *Var = 0;
- if (S->getExceptionDecl()) {
- VarDecl *ExceptionDecl = S->getExceptionDecl();
- TypeSourceInfo *T = getDerived().TransformType(
- ExceptionDecl->getTypeSourceInfo());
+ if (VarDecl *ExceptionDecl = S->getExceptionDecl()) {
+ TypeSourceInfo *T =
+ getDerived().TransformType(ExceptionDecl->getTypeSourceInfo());
if (!T)
return StmtError();
- Var = getDerived().RebuildExceptionDecl(ExceptionDecl, T,
- ExceptionDecl->getInnerLocStart(),
- ExceptionDecl->getLocation(),
- ExceptionDecl->getIdentifier());
+ Var = getDerived().RebuildExceptionDecl(
+ ExceptionDecl, T, ExceptionDecl->getInnerLocStart(),
+ ExceptionDecl->getLocation(), ExceptionDecl->getIdentifier());
if (!Var || Var->isInvalidDecl())
return StmtError();
}
@@ -5905,31 +6029,25 @@ TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
if (Handler.isInvalid())
return StmtError();
- if (!getDerived().AlwaysRebuild() &&
- !Var &&
+ if (!getDerived().AlwaysRebuild() && !Var &&
Handler.get() == S->getHandlerBlock())
return SemaRef.Owned(S);
- return getDerived().RebuildCXXCatchStmt(S->getCatchLoc(),
- Var,
- Handler.get());
+ return getDerived().RebuildCXXCatchStmt(S->getCatchLoc(), Var, Handler.get());
}
-template<typename Derived>
-StmtResult
-TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
// Transform the try block itself.
- StmtResult TryBlock
- = getDerived().TransformCompoundStmt(S->getTryBlock());
+ StmtResult TryBlock = getDerived().TransformCompoundStmt(S->getTryBlock());
if (TryBlock.isInvalid())
return StmtError();
// Transform the handlers.
bool HandlerChanged = false;
- SmallVector<Stmt*, 8> Handlers;
+ SmallVector<Stmt *, 8> Handlers;
for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) {
- StmtResult Handler
- = getDerived().TransformCXXCatchStmt(S->getHandler(I));
+ StmtResult Handler = getDerived().TransformCXXCatchStmt(S->getHandler(I));
if (Handler.isInvalid())
return StmtError();
@@ -5937,8 +6055,7 @@ TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
Handlers.push_back(Handler.takeAs<Stmt>());
}
- if (!getDerived().AlwaysRebuild() &&
- TryBlock.get() == S->getTryBlock() &&
+ if (!getDerived().AlwaysRebuild() && TryBlock.get() == S->getTryBlock() &&
!HandlerChanged)
return SemaRef.Owned(S);
@@ -6110,57 +6227,166 @@ TreeTransform<Derived>::TransformMSPropertyRefExpr(MSPropertyRefExpr *E) {
QualifierLoc, E->getMemberLoc());
}
-template<typename Derived>
-StmtResult
-TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) {
- StmtResult TryBlock; // = getDerived().TransformCompoundStmt(S->getTryBlock());
- if(TryBlock.isInvalid()) return StmtError();
+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())
+ if (Handler.isInvalid())
+ return StmtError();
+
+ 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());
+ 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();
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformSEHFinallyStmt(SEHFinallyStmt *S) {
+ StmtResult Block = getDerived().TransformCompoundStmt(S->getBlock());
+ if (Block.isInvalid())
+ return StmtError();
- return getDerived().RebuildSEHFinallyStmt(S->getFinallyLoc(),
- Block.take());
+ return getDerived().RebuildSEHFinallyStmt(S->getFinallyLoc(), Block.take());
}
-template<typename Derived>
-StmtResult
-TreeTransform<Derived>::TransformSEHExceptStmt(SEHExceptStmt *S) {
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformSEHExceptStmt(SEHExceptStmt *S) {
ExprResult FilterExpr = getDerived().TransformExpr(S->getFilterExpr());
- if(FilterExpr.isInvalid()) return StmtError();
+ if (FilterExpr.isInvalid())
+ return StmtError();
- StmtResult Block; // = getDerived().TransformCompoundStatement(S->getBlock());
- if(Block.isInvalid()) return StmtError();
+ StmtResult Block = getDerived().TransformCompoundStmt(S->getBlock());
+ if (Block.isInvalid())
+ return StmtError();
- return getDerived().RebuildSEHExceptStmt(S->getExceptLoc(),
- FilterExpr.take(),
+ return getDerived().RebuildSEHExceptStmt(S->getExceptLoc(), FilterExpr.take(),
Block.take());
}
-template<typename Derived>
-StmtResult
-TreeTransform<Derived>::TransformSEHHandler(Stmt *Handler) {
- if(isa<SEHFinallyStmt>(Handler))
+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));
}
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) {
+ DeclarationNameInfo DirName;
+ getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, 0);
+
+ // Transform the clauses
+ llvm::SmallVector<OMPClause *, 16> TClauses;
+ ArrayRef<OMPClause *> Clauses = D->clauses();
+ TClauses.reserve(Clauses.size());
+ for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end();
+ I != E; ++I) {
+ if (*I) {
+ OMPClause *Clause = getDerived().TransformOMPClause(*I);
+ if (!Clause) {
+ getSema().EndOpenMPDSABlock(0);
+ return StmtError();
+ }
+ TClauses.push_back(Clause);
+ }
+ else {
+ TClauses.push_back(0);
+ }
+ }
+ if (!D->getAssociatedStmt()) {
+ getSema().EndOpenMPDSABlock(0);
+ return StmtError();
+ }
+ StmtResult AssociatedStmt =
+ getDerived().TransformStmt(D->getAssociatedStmt());
+ if (AssociatedStmt.isInvalid()) {
+ getSema().EndOpenMPDSABlock(0);
+ return StmtError();
+ }
+
+ StmtResult Res = getDerived().RebuildOMPParallelDirective(TClauses,
+ AssociatedStmt.take(),
+ D->getLocStart(),
+ D->getLocEnd());
+ getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template<typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) {
+ return getDerived().RebuildOMPDefaultClause(C->getDefaultKind(),
+ C->getDefaultKindKwLoc(),
+ C->getLocStart(),
+ C->getLParenLoc(),
+ C->getLocEnd());
+}
+
+template<typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (OMPPrivateClause::varlist_iterator I = C->varlist_begin(),
+ E = C->varlist_end();
+ I != E; ++I) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(*I));
+ if (EVar.isInvalid())
+ return 0;
+ Vars.push_back(EVar.take());
+ }
+ return getDerived().RebuildOMPPrivateClause(Vars,
+ C->getLocStart(),
+ C->getLParenLoc(),
+ C->getLocEnd());
+}
+
+template<typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPFirstprivateClause(
+ OMPFirstprivateClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (OMPFirstprivateClause::varlist_iterator I = C->varlist_begin(),
+ E = C->varlist_end();
+ I != E; ++I) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(*I));
+ if (EVar.isInvalid())
+ return 0;
+ Vars.push_back(EVar.take());
+ }
+ return getDerived().RebuildOMPFirstprivateClause(Vars,
+ C->getLocStart(),
+ C->getLParenLoc(),
+ C->getLocEnd());
+}
+
+template<typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPSharedClause(OMPSharedClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (OMPSharedClause::varlist_iterator I = C->varlist_begin(),
+ E = C->varlist_end();
+ I != E; ++I) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(*I));
+ if (EVar.isInvalid())
+ return 0;
+ Vars.push_back(EVar.take());
+ }
+ return getDerived().RebuildOMPSharedClause(Vars,
+ C->getLocStart(),
+ C->getLParenLoc(),
+ C->getLocEnd());
+}
+
//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//
@@ -6291,9 +6517,8 @@ TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) {
E->getDefaultLoc(),
E->getRParenLoc(),
ControllingExpr.release(),
- AssocTypes.data(),
- AssocExprs.data(),
- E->getNumAssocs());
+ AssocTypes,
+ AssocExprs);
}
template<typename Derived>
@@ -6325,7 +6550,11 @@ TreeTransform<Derived>::TransformAddressOfOperand(Expr *E) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) {
- ExprResult SubExpr = TransformAddressOfOperand(E->getSubExpr());
+ ExprResult SubExpr;
+ if (E->getOpcode() == UO_AddrOf)
+ SubExpr = TransformAddressOfOperand(E->getSubExpr());
+ else
+ SubExpr = TransformExpr(E->getSubExpr());
if (SubExpr.isInvalid())
return ExprError();
@@ -7167,7 +7396,7 @@ TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
return SemaRef.Owned(E);
return getDerived().RebuildCXXFunctionalCastExpr(Type,
- /*FIXME:*/E->getSubExpr()->getLocStart(),
+ E->getLParenLoc(),
SubExpr.get(),
E->getRParenLoc());
}
@@ -7263,18 +7492,7 @@ TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr(
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
- DeclContext *DC = getSema().getFunctionLevelDeclContext();
- QualType T;
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC))
- T = MD->getThisType(getSema().Context);
- else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) {
- T = getSema().Context.getPointerType(
- getSema().Context.getRecordType(Record));
- } else {
- assert(SemaRef.Context.getDiagnostics().hasErrorOccurred() &&
- "this in the wrong scope?");
- return ExprError();
- }
+ QualType T = getSema().getCurrentThisType();
if (!getDerived().AlwaysRebuild() && T == E->getType()) {
// Make sure that we capture 'this'.
@@ -7604,8 +7822,10 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
// This can happen because of dependent hiding.
if (isa<UsingShadowDecl>(*I))
continue;
- else
+ else {
+ R.clear();
return ExprError();
+ }
}
// Expand using declarations.
@@ -7640,8 +7860,10 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
= cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
Old->getNameLoc(),
Old->getNamingClass()));
- if (!NamingClass)
+ if (!NamingClass) {
+ R.clear();
return ExprError();
+ }
R.setNamingClass(NamingClass);
}
@@ -7659,8 +7881,10 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
if (Old->hasExplicitTemplateArgs() &&
getDerived().TransformTemplateArguments(Old->getTemplateArgs(),
Old->getNumTemplateArgs(),
- TransArgs))
+ TransArgs)) {
+ R.clear();
return ExprError();
+ }
return getDerived().RebuildTemplateIdExpr(SS, TemplateKWLoc, R,
Old->requiresADL(), &TransArgs);
@@ -7787,6 +8011,19 @@ TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) {
if (To.isNull())
return ExprError();
+ if (To->containsUnexpandedParameterPack()) {
+ To = getDerived().RebuildPackExpansionType(To,
+ PatternTL.getSourceRange(),
+ ExpansionTL.getEllipsisLoc(),
+ NumExpansions);
+ if (To.isNull())
+ return ExprError();
+
+ PackExpansionTypeLoc ToExpansionTL
+ = TLB.push<PackExpansionTypeLoc>(To);
+ ToExpansionTL.setEllipsisLoc(ExpansionTL.getEllipsisLoc());
+ }
+
Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To));
}
@@ -7885,6 +8122,7 @@ ExprResult
TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *E,
bool IsAddressOfOperand) {
+ assert(E->getQualifierLoc());
NestedNameSpecifierLoc QualifierLoc
= getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
if (!QualifierLoc)
@@ -7976,7 +8214,7 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
E->isListInitialization(),
E->requiresZeroInitialization(),
E->getConstructionKind(),
- E->getParenRange());
+ E->getParenOrBraceRange());
}
/// \brief Transform a C++ temporary-binding expression.
@@ -8041,57 +8279,157 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
- // Transform the type of the lambda parameters and start the definition of
- // the lambda itself.
- TypeSourceInfo *MethodTy
- = TransformType(E->getCallOperator()->getTypeSourceInfo());
- if (!MethodTy)
+
+ // Transform any init-capture expressions before entering the scope of the
+ // lambda body, because they are not semantically within that scope.
+ SmallVector<InitCaptureInfoTy, 8> InitCaptureExprsAndTypes;
+ InitCaptureExprsAndTypes.resize(E->explicit_capture_end() -
+ E->explicit_capture_begin());
+
+ for (LambdaExpr::capture_iterator C = E->capture_begin(),
+ CEnd = E->capture_end();
+ C != CEnd; ++C) {
+ if (!C->isInitCapture())
+ continue;
+ EnterExpressionEvaluationContext EEEC(getSema(),
+ Sema::PotentiallyEvaluated);
+ ExprResult NewExprInitResult = getDerived().TransformInitializer(
+ C->getCapturedVar()->getInit(),
+ C->getCapturedVar()->getInitStyle() == VarDecl::CallInit);
+
+ if (NewExprInitResult.isInvalid())
+ return ExprError();
+ Expr *NewExprInit = NewExprInitResult.get();
+
+ VarDecl *OldVD = C->getCapturedVar();
+ QualType NewInitCaptureType =
+ getSema().performLambdaInitCaptureInitialization(C->getLocation(),
+ OldVD->getType()->isReferenceType(), OldVD->getIdentifier(),
+ NewExprInit);
+ NewExprInitResult = NewExprInit;
+ InitCaptureExprsAndTypes[C - E->capture_begin()] =
+ std::make_pair(NewExprInitResult, NewInitCaptureType);
+
+ }
+
+ LambdaScopeInfo *LSI = getSema().PushLambdaScope();
+ // Transform the template parameters, and add them to the current
+ // instantiation scope. The null case is handled correctly.
+ LSI->GLTemplateParameterList = getDerived().TransformTemplateParameterList(
+ E->getTemplateParameterList());
+
+ // Check to see if the TypeSourceInfo of the call operator needs to
+ // be transformed, and if so do the transformation in the
+ // CurrentInstantiationScope.
+
+ TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
+ FunctionProtoTypeLoc OldCallOpFPTL =
+ OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
+ TypeSourceInfo *NewCallOpTSI = 0;
+
+ const bool CallOpWasAlreadyTransformed =
+ getDerived().AlreadyTransformed(OldCallOpTSI->getType());
+
+ // Use the Old Call Operator's TypeSourceInfo if it is already transformed.
+ if (CallOpWasAlreadyTransformed)
+ NewCallOpTSI = OldCallOpTSI;
+ else {
+ // Transform the TypeSourceInfo of the Original Lambda's Call Operator.
+ // The transformation MUST be done in the CurrentInstantiationScope since
+ // it introduces a mapping of the original to the newly created
+ // transformed parameters.
+
+ TypeLocBuilder NewCallOpTLBuilder;
+ QualType NewCallOpType = TransformFunctionProtoType(NewCallOpTLBuilder,
+ OldCallOpFPTL,
+ 0, 0);
+ NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
+ NewCallOpType);
+ }
+ // Extract the ParmVarDecls from the NewCallOpTSI and add them to
+ // the vector below - this will be used to synthesize the
+ // NewCallOperator. Additionally, add the parameters of the untransformed
+ // lambda call operator to the CurrentInstantiationScope.
+ SmallVector<ParmVarDecl *, 4> Params;
+ {
+ FunctionProtoTypeLoc NewCallOpFPTL =
+ NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
+ ParmVarDecl **NewParamDeclArray = NewCallOpFPTL.getParmArray();
+ const unsigned NewNumArgs = NewCallOpFPTL.getNumArgs();
+
+ for (unsigned I = 0; I < NewNumArgs; ++I) {
+ // If this call operator's type does not require transformation,
+ // the parameters do not get added to the current instantiation scope,
+ // - so ADD them! This allows the following to compile when the enclosing
+ // template is specialized and the entire lambda expression has to be
+ // transformed.
+ // template<class T> void foo(T t) {
+ // auto L = [](auto a) {
+ // auto M = [](char b) { <-- note: non-generic lambda
+ // auto N = [](auto c) {
+ // int x = sizeof(a);
+ // x = sizeof(b); <-- specifically this line
+ // x = sizeof(c);
+ // };
+ // };
+ // };
+ // }
+ // foo('a')
+ if (CallOpWasAlreadyTransformed)
+ getDerived().transformedLocalDecl(NewParamDeclArray[I],
+ NewParamDeclArray[I]);
+ // Add to Params array, so these parameters can be used to create
+ // the newly transformed call operator.
+ Params.push_back(NewParamDeclArray[I]);
+ }
+ }
+
+ if (!NewCallOpTSI)
return ExprError();
// Create the local class that will describe the lambda.
CXXRecordDecl *Class
= getSema().createLambdaClosureType(E->getIntroducerRange(),
- MethodTy,
- /*KnownDependent=*/false);
- getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
+ NewCallOpTSI,
+ /*KnownDependent=*/false,
+ E->getCaptureDefault());
- // Transform lambda parameters.
- SmallVector<QualType, 4> ParamTypes;
- SmallVector<ParmVarDecl *, 4> Params;
- if (getDerived().TransformFunctionTypeParams(E->getLocStart(),
- E->getCallOperator()->param_begin(),
- E->getCallOperator()->param_size(),
- 0, ParamTypes, &Params))
- return ExprError();
+ getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
// Build the call operator.
- CXXMethodDecl *CallOperator
+ CXXMethodDecl *NewCallOperator
= getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
- MethodTy,
+ NewCallOpTSI,
E->getCallOperator()->getLocEnd(),
Params);
- getDerived().transformAttrs(E->getCallOperator(), CallOperator);
+ LSI->CallOperator = NewCallOperator;
+
+ getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
- return getDerived().TransformLambdaScope(E, CallOperator);
+ return getDerived().TransformLambdaScope(E, NewCallOperator,
+ InitCaptureExprsAndTypes);
}
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
- CXXMethodDecl *CallOperator) {
+ CXXMethodDecl *CallOperator,
+ ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes) {
+ bool Invalid = false;
+
// Introduce the context of the call operator.
Sema::ContextRAII SavedContext(getSema(), CallOperator);
+ LambdaScopeInfo *const LSI = getSema().getCurLambda();
// Enter the scope of the lambda.
- sema::LambdaScopeInfo *LSI
- = getSema().enterLambdaScope(CallOperator, E->getIntroducerRange(),
+ getSema().buildLambdaScope(LSI, CallOperator, E->getIntroducerRange(),
E->getCaptureDefault(),
+ E->getCaptureDefaultLoc(),
E->hasExplicitParameters(),
E->hasExplicitResultType(),
E->isMutable());
// Transform captures.
- bool Invalid = false;
bool FinishedExplicitCaptures = false;
for (LambdaExpr::capture_iterator C = E->capture_begin(),
CEnd = E->capture_end();
@@ -8109,6 +8447,32 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
continue;
}
+ // Rebuild init-captures, including the implied field declaration.
+ if (C->isInitCapture()) {
+
+ InitCaptureInfoTy InitExprTypePair =
+ InitCaptureExprsAndTypes[C - E->capture_begin()];
+ ExprResult Init = InitExprTypePair.first;
+ QualType InitQualType = InitExprTypePair.second;
+ if (Init.isInvalid() || InitQualType.isNull()) {
+ Invalid = true;
+ continue;
+ }
+ VarDecl *OldVD = C->getCapturedVar();
+ VarDecl *NewVD = getSema().createLambdaInitCaptureVarDecl(
+ OldVD->getLocation(), InitExprTypePair.second,
+ OldVD->getIdentifier(), Init.get());
+ if (!NewVD)
+ Invalid = true;
+ else {
+ getDerived().transformedLocalDecl(OldVD, NewVD);
+ }
+ getSema().buildInitCaptureField(LSI, NewVD);
+ continue;
+ }
+
+ assert(C->capturesVariable() && "unexpected kind of lambda capture");
+
// Determine the capture kind for Sema.
Sema::TryCaptureKind Kind
= C->isImplicit()? Sema::TryCapture_Implicit
@@ -8125,8 +8489,10 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
C->getLocation(),
Unexpanded,
ShouldExpand, RetainExpansion,
- NumExpansions))
- return ExprError();
+ NumExpansions)) {
+ Invalid = true;
+ continue;
+ }
if (ShouldExpand) {
// The transform has determined that we should perform an expansion;
@@ -8521,6 +8887,13 @@ TreeTransform<Derived>::TransformMaterializeTemporaryExpr(
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformCXXStdInitializerListExpr(
+ CXXStdInitializerListExpr *E) {
+ return getDerived().TransformExpr(E->getSubExpr());
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) {
return SemaRef.MaybeBindToTemporary(E);
}
@@ -8921,6 +9294,27 @@ TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) {
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformConvertVectorExpr(ConvertVectorExpr *E) {
+ ExprResult SrcExpr = getDerived().TransformExpr(E->getSrcExpr());
+ if (SrcExpr.isInvalid())
+ return ExprError();
+
+ TypeSourceInfo *Type = getDerived().TransformType(E->getTypeSourceInfo());
+ if (!Type)
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Type == E->getTypeSourceInfo() &&
+ SrcExpr.get() == E->getSrcExpr())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildConvertVectorExpr(E->getBuiltinLoc(),
+ SrcExpr.get(), Type,
+ E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
BlockDecl *oldBlock = E->getBlockDecl();
@@ -8947,15 +9341,6 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
QualType exprResultType =
getDerived().TransformType(exprFunctionType->getResultType());
- // Don't allow returning a objc interface by value.
- if (exprResultType->isObjCObjectType()) {
- getSema().Diag(E->getCaretLocation(),
- diag::err_object_cannot_be_passed_returned_by_value)
- << 0 << exprResultType;
- getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0);
- return ExprError();
- }
-
QualType functionType =
getDerived().RebuildFunctionProtoType(exprResultType, paramTypes,
exprFunctionType->getExtProtoInfo());
@@ -9082,7 +9467,7 @@ TreeTransform<Derived>::RebuildArrayType(QualType ElementType,
SemaRef.Context.UnsignedIntTy, SemaRef.Context.UnsignedLongTy,
SemaRef.Context.UnsignedLongLongTy, SemaRef.Context.UnsignedInt128Ty
};
- const unsigned NumTypes = sizeof(Types) / sizeof(QualType);
+ const unsigned NumTypes = llvm::array_lengthof(Types);
QualType SizeType;
for (unsigned I = 0; I != NumTypes; ++I)
if (Size->getBitWidth() == SemaRef.Context.getIntWidth(Types[I])) {
@@ -9198,7 +9583,7 @@ QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) {
TypeDecl *Ty;
if (isa<UsingDecl>(D)) {
UsingDecl *Using = cast<UsingDecl>(D);
- assert(Using->isTypeName() &&
+ assert(Using->hasTypename() &&
"UnresolvedUsingTypenameDecl transformed to non-typename using");
// A valid resolved using typename decl points to exactly one type decl.
@@ -9297,7 +9682,7 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
ParsedType::make(ObjectType),
/*EnteringContext=*/false,
Template);
- return Template.template getAsVal<TemplateName>();
+ return Template.get();
}
template<typename Derived>
diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.cpp b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.cpp
new file mode 100644
index 000000000000..c7d43b704690
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.cpp
@@ -0,0 +1,136 @@
+//===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines TypeLocBuilder, a class for building TypeLocs
+// bottom-up.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TypeLocBuilder.h"
+
+using namespace clang;
+
+void TypeLocBuilder::pushFullCopy(TypeLoc L) {
+ size_t Size = L.getFullDataSize();
+ reserve(Size);
+
+ SmallVector<TypeLoc, 4> TypeLocs;
+ TypeLoc CurTL = L;
+ while (CurTL) {
+ TypeLocs.push_back(CurTL);
+ CurTL = CurTL.getNextTypeLoc();
+ }
+
+ for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i) {
+ TypeLoc CurTL = TypeLocs[e-i-1];
+ switch (CurTL.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ case TypeLoc::CLASS: { \
+ CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \
+ memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \
+ break; \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ }
+ }
+}
+
+void TypeLocBuilder::grow(size_t NewCapacity) {
+ assert(NewCapacity > Capacity);
+
+ // Allocate the new buffer and copy the old data into it.
+ char *NewBuffer = new char[NewCapacity];
+ unsigned NewIndex = Index + NewCapacity - Capacity;
+ memcpy(&NewBuffer[NewIndex],
+ &Buffer[Index],
+ Capacity - Index);
+
+ if (Buffer != InlineBuffer.buffer)
+ delete[] Buffer;
+
+ Buffer = NewBuffer;
+ Capacity = NewCapacity;
+ Index = NewIndex;
+}
+
+TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {
+#ifndef NDEBUG
+ QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
+ assert(TLast == LastTy &&
+ "mismatch between last type and new type's inner type");
+ LastTy = T;
+#endif
+
+ assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment");
+
+ // If we need to grow, grow by a factor of 2.
+ if (LocalSize > Index) {
+ size_t RequiredCapacity = Capacity + (LocalSize - Index);
+ size_t NewCapacity = Capacity * 2;
+ while (RequiredCapacity > NewCapacity)
+ NewCapacity *= 2;
+ grow(NewCapacity);
+ }
+
+ // Because we're adding elements to the TypeLoc backwards, we have to
+ // do some extra work to keep everything aligned appropriately.
+ // FIXME: This algorithm is a absolute mess because every TypeLoc returned
+ // needs to be valid. Partial TypeLocs are a terrible idea.
+ // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to
+ // hardcode them.
+ if (LocalAlignment == 4) {
+ if (NumBytesAtAlign8 == 0) {
+ NumBytesAtAlign4 += LocalSize;
+ } else {
+ unsigned Padding = NumBytesAtAlign4 % 8;
+ if (Padding == 0) {
+ if (LocalSize % 8 == 0) {
+ // Everything is set: there's no padding and we don't need to add
+ // any.
+ } else {
+ assert(LocalSize % 8 == 4);
+ // No existing padding; add in 4 bytes padding
+ memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
+ Index -= 4;
+ }
+ } else {
+ assert(Padding == 4);
+ if (LocalSize % 8 == 0) {
+ // Everything is set: there's 4 bytes padding and we don't need
+ // to add any.
+ } else {
+ assert(LocalSize % 8 == 4);
+ // There are 4 bytes padding, but we don't need any; remove it.
+ memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
+ Index += 4;
+ }
+ }
+ NumBytesAtAlign4 += LocalSize;
+ }
+ } else if (LocalAlignment == 8) {
+ if (!NumBytesAtAlign8 && NumBytesAtAlign4 % 8 != 0) {
+ // No existing padding and misaligned members; add in 4 bytes padding
+ memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
+ Index -= 4;
+ }
+ // Forget about any padding.
+ NumBytesAtAlign4 = 0;
+ NumBytesAtAlign8 += LocalSize;
+ } else {
+ assert(LocalSize == 0);
+ }
+
+ Index -= LocalSize;
+
+ assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) &&
+ "incorrect data size provided to CreateTypeSourceInfo!");
+
+ return getTemporaryTypeLoc(T);
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
index f36ec9f3e209..b1e909859b2f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
@@ -39,14 +39,19 @@ class TypeLocBuilder {
#endif
/// The inline buffer.
- char InlineBuffer[InlineCapacity];
+ enum { BufferMaxAlignment = llvm::AlignOf<void*>::Alignment };
+ llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer;
+ unsigned NumBytesAtAlign4, NumBytesAtAlign8;
public:
TypeLocBuilder()
- : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {}
+ : Buffer(InlineBuffer.buffer), Capacity(InlineCapacity),
+ Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0)
+ {
+ }
~TypeLocBuilder() {
- if (Buffer != InlineBuffer)
+ if (Buffer != InlineBuffer.buffer)
delete[] Buffer;
}
@@ -59,23 +64,14 @@ class TypeLocBuilder {
/// Pushes a copy of the given TypeLoc onto this builder. The builder
/// must be empty for this to work.
- void pushFullCopy(TypeLoc L) {
- size_t Size = L.getFullDataSize();
- TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size);
- memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size);
- }
-
- /// Pushes uninitialized space for the given type. The builder must
- /// be empty.
- TypeLoc pushFullUninitialized(QualType T) {
- return pushFullUninitializedImpl(T, TypeLoc::getFullDataSizeForType(T));
- }
+ void pushFullCopy(TypeLoc L);
/// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
/// previously retrieved from this builder.
TypeSpecTypeLoc pushTypeSpec(QualType T) {
size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
- return pushImpl(T, LocalSize).castAs<TypeSpecTypeLoc>();
+ unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment;
+ return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>();
}
/// Resets this builder to the newly-initialized state.
@@ -84,6 +80,7 @@ class TypeLocBuilder {
LastTy = QualType();
#endif
Index = Capacity;
+ NumBytesAtAlign4 = NumBytesAtAlign8 = 0;
}
/// \brief Tell the TypeLocBuilder that the type it is storing has been
@@ -97,8 +94,10 @@ class TypeLocBuilder {
/// Pushes space for a new TypeLoc of the given type. Invalidates
/// any TypeLocs previously retrieved from this builder.
template <class TyLocType> TyLocType push(QualType T) {
- size_t LocalSize = TypeLoc(T, 0).castAs<TyLocType>().getLocalDataSize();
- return pushImpl(T, LocalSize).castAs<TyLocType>();
+ TyLocType Loc = TypeLoc(T, 0).castAs<TyLocType>();
+ size_t LocalSize = Loc.getLocalDataSize();
+ unsigned LocalAlign = Loc.getLocalDataAlignment();
+ return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>();
}
/// Creates a TypeSourceInfo for the given type.
@@ -127,61 +126,12 @@ class TypeLocBuilder {
}
private:
- TypeLoc pushImpl(QualType T, size_t LocalSize) {
-#ifndef NDEBUG
- QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
- assert(TLast == LastTy &&
- "mismatch between last type and new type's inner type");
- LastTy = T;
-#endif
-
- // If we need to grow, grow by a factor of 2.
- if (LocalSize > Index) {
- size_t RequiredCapacity = Capacity + (LocalSize - Index);
- size_t NewCapacity = Capacity * 2;
- while (RequiredCapacity > NewCapacity)
- NewCapacity *= 2;
- grow(NewCapacity);
- }
- Index -= LocalSize;
-
- return getTemporaryTypeLoc(T);
- }
+ TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment);
/// Grow to the given capacity.
- void grow(size_t NewCapacity) {
- assert(NewCapacity > Capacity);
-
- // Allocate the new buffer and copy the old data into it.
- char *NewBuffer = new char[NewCapacity];
- unsigned NewIndex = Index + NewCapacity - Capacity;
- memcpy(&NewBuffer[NewIndex],
- &Buffer[Index],
- Capacity - Index);
-
- if (Buffer != InlineBuffer)
- delete[] Buffer;
-
- Buffer = NewBuffer;
- Capacity = NewCapacity;
- Index = NewIndex;
- }
-
- TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) {
-#ifndef NDEBUG
- assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder");
- LastTy = T;
-#endif
- assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder");
-
- reserve(Size);
- Index -= Size;
-
- return getTemporaryTypeLoc(T);
- }
+ void grow(size_t NewCapacity);
-public:
/// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
/// object.
///