Updated to Clang 3.5a.
Change-Id: I8127eb568f674c2e72635b639a3295381fe8af82
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 93e3ecf..3e40485 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -65,16 +65,157 @@
public:
UnreachableCodeHandler(Sema &s) : S(s) {}
- void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) {
- S.Diag(L, diag::warn_unreachable) << R1 << R2;
+ void HandleUnreachable(reachable_code::UnreachableKind UK,
+ SourceLocation L,
+ SourceRange SilenceableCondVal,
+ SourceRange R1,
+ SourceRange R2) override {
+ unsigned diag = diag::warn_unreachable;
+ switch (UK) {
+ case reachable_code::UK_Break:
+ diag = diag::warn_unreachable_break;
+ break;
+ case reachable_code::UK_Return:
+ diag = diag::warn_unreachable_return;
+ break;
+ case reachable_code::UK_Loop_Increment:
+ diag = diag::warn_unreachable_loop_increment;
+ break;
+ case reachable_code::UK_Other:
+ break;
+ }
+
+ S.Diag(L, diag) << R1 << R2;
+
+ SourceLocation Open = SilenceableCondVal.getBegin();
+ if (Open.isValid()) {
+ SourceLocation Close = SilenceableCondVal.getEnd();
+ Close = S.PP.getLocForEndOfToken(Close);
+ if (Close.isValid()) {
+ S.Diag(Open, diag::note_unreachable_silence)
+ << FixItHint::CreateInsertion(Open, "/* DISABLES CODE */ (")
+ << FixItHint::CreateInsertion(Close, ")");
+ }
+ }
}
};
}
/// CheckUnreachable - Check for unreachable code.
static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) {
+ // As a heuristic prune all diagnostics not in the main file. Currently
+ // the majority of warnings in headers are false positives. These
+ // are largely caused by configuration state, e.g. preprocessor
+ // defined code, etc.
+ //
+ // Note that this is also a performance optimization. Analyzing
+ // headers many times can be expensive.
+ if (!S.getSourceManager().isInMainFile(AC.getDecl()->getLocStart()))
+ return;
+
UnreachableCodeHandler UC(S);
- reachable_code::FindUnreachableCode(AC, UC);
+ reachable_code::FindUnreachableCode(AC, S.getPreprocessor(), UC);
+}
+
+//===----------------------------------------------------------------------===//
+// Check for infinite self-recursion in functions
+//===----------------------------------------------------------------------===//
+
+// All blocks are in one of three states. States are ordered so that blocks
+// can only move to higher states.
+enum RecursiveState {
+ FoundNoPath,
+ FoundPath,
+ FoundPathWithNoRecursiveCall
+};
+
+static void checkForFunctionCall(Sema &S, const FunctionDecl *FD,
+ CFGBlock &Block, unsigned ExitID,
+ llvm::SmallVectorImpl<RecursiveState> &States,
+ RecursiveState State) {
+ unsigned ID = Block.getBlockID();
+
+ // A block's state can only move to a higher state.
+ if (States[ID] >= State)
+ return;
+
+ States[ID] = State;
+
+ // Found a path to the exit node without a recursive call.
+ if (ID == ExitID && State == FoundPathWithNoRecursiveCall)
+ return;
+
+ if (State == FoundPathWithNoRecursiveCall) {
+ // If the current state is FoundPathWithNoRecursiveCall, the successors
+ // will be either FoundPathWithNoRecursiveCall or FoundPath. To determine
+ // which, process all the Stmt's in this block to find any recursive calls.
+ for (CFGBlock::iterator I = Block.begin(), E = Block.end(); I != E; ++I) {
+ if (I->getKind() != CFGElement::Statement)
+ continue;
+
+ const CallExpr *CE = dyn_cast<CallExpr>(I->getAs<CFGStmt>()->getStmt());
+ if (CE && CE->getCalleeDecl() &&
+ CE->getCalleeDecl()->getCanonicalDecl() == FD) {
+
+ // Skip function calls which are qualified with a templated class.
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
+ CE->getCallee()->IgnoreParenImpCasts())) {
+ if (NestedNameSpecifier *NNS = DRE->getQualifier()) {
+ if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&
+ isa<TemplateSpecializationType>(NNS->getAsType())) {
+ continue;
+ }
+ }
+ }
+
+ if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE)) {
+ if (isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||
+ !MCE->getMethodDecl()->isVirtual()) {
+ State = FoundPath;
+ break;
+ }
+ } else {
+ State = FoundPath;
+ break;
+ }
+ }
+ }
+ }
+
+ for (CFGBlock::succ_iterator I = Block.succ_begin(), E = Block.succ_end();
+ I != E; ++I)
+ if (*I)
+ checkForFunctionCall(S, FD, **I, ExitID, States, State);
+}
+
+static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
+ const Stmt *Body,
+ AnalysisDeclContext &AC) {
+ FD = FD->getCanonicalDecl();
+
+ // Only run on non-templated functions and non-templated members of
+ // templated classes.
+ if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate &&
+ FD->getTemplatedKind() != FunctionDecl::TK_MemberSpecialization)
+ return;
+
+ CFG *cfg = AC.getCFG();
+ if (cfg == 0) return;
+
+ // If the exit block is unreachable, skip processing the function.
+ if (cfg->getExit().pred_empty())
+ return;
+
+ // Mark all nodes as FoundNoPath, then begin processing the entry block.
+ llvm::SmallVector<RecursiveState, 16> states(cfg->getNumBlockIDs(),
+ FoundNoPath);
+ checkForFunctionCall(S, FD, cfg->getEntry(), cfg->getExit().getBlockID(),
+ states, FoundPathWithNoRecursiveCall);
+
+ // Check that the exit block is reachable. This prevents triggering the
+ // warning on functions that do not terminate.
+ if (states[cfg->getExit().getBlockID()] == FoundPath)
+ S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function);
}
//===----------------------------------------------------------------------===//
@@ -330,18 +471,18 @@
bool HasNoReturn = false;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- ReturnsVoid = FD->getResultType()->isVoidType();
+ ReturnsVoid = FD->getReturnType()->isVoidType();
HasNoReturn = FD->isNoReturn();
}
else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
- ReturnsVoid = MD->getResultType()->isVoidType();
+ ReturnsVoid = MD->getReturnType()->isVoidType();
HasNoReturn = MD->hasAttr<NoReturnAttr>();
}
else if (isa<BlockDecl>(D)) {
QualType BlockTy = blkExpr->getType();
if (const FunctionType *FT =
BlockTy->getPointeeType()->getAs<FunctionType>()) {
- if (FT->getResultType()->isVoidType())
+ if (FT->getReturnType()->isVoidType())
ReturnsVoid = true;
if (FT->getNoReturnAttr())
HasNoReturn = true;
@@ -776,6 +917,7 @@
while (!BlockQueue.empty()) {
const CFGBlock *P = BlockQueue.front();
BlockQueue.pop_front();
+ if (!P) continue;
const Stmt *Term = P->getTerminator();
if (Term && isa<SwitchStmt>(Term))
@@ -977,24 +1119,6 @@
}
-namespace {
-typedef std::pair<const Stmt *,
- sema::FunctionScopeInfo::WeakObjectUseMap::const_iterator>
- StmtUsesPair;
-
-class StmtUseSorter {
- const SourceManager &SM;
-
-public:
- explicit StmtUseSorter(const SourceManager &SM) : SM(SM) { }
-
- bool operator()(const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
- return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(),
- RHS.first->getLocStart());
- }
-};
-}
-
static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,
const Stmt *S) {
assert(S);
@@ -1029,6 +1153,8 @@
typedef sema::FunctionScopeInfo::WeakObjectProfileTy WeakObjectProfileTy;
typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap;
typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector;
+ typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator>
+ StmtUsesPair;
ASTContext &Ctx = S.getASTContext();
@@ -1087,8 +1213,12 @@
return;
// Sort by first use so that we emit the warnings in a deterministic order.
+ SourceManager &SM = S.getSourceManager();
std::sort(UsesByStmt.begin(), UsesByStmt.end(),
- StmtUseSorter(S.getSourceManager()));
+ [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) {
+ return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(),
+ RHS.first->getLocStart());
+ });
// Classify the current code body for better warning text.
// This enum should stay in sync with the cases in
@@ -1169,19 +1299,7 @@
}
}
-
namespace {
-struct SLocSort {
- bool operator()(const UninitUse &a, const UninitUse &b) {
- // Prefer a more confident report over a less confident one.
- if (a.getKind() != b.getKind())
- return a.getKind() > b.getKind();
- SourceLocation aLoc = a.getUser()->getLocStart();
- SourceLocation bLoc = b.getUser()->getLocStart();
- return aLoc.getRawEncoding() < bLoc.getRawEncoding();
- }
-};
-
class UninitValsDiagReporter : public UninitVariablesHandler {
Sema &S;
typedef SmallVector<UninitUse, 2> UsesVec;
@@ -1208,12 +1326,13 @@
return V;
}
-
- void handleUseOfUninitVariable(const VarDecl *vd, const UninitUse &use) {
+
+ void handleUseOfUninitVariable(const VarDecl *vd,
+ const UninitUse &use) override {
getUses(vd).getPointer()->push_back(use);
}
- void handleSelfInit(const VarDecl *vd) {
+ void handleSelfInit(const VarDecl *vd) override {
getUses(vd).setInt(true);
}
@@ -1240,8 +1359,14 @@
// Sort the uses by their SourceLocations. While not strictly
// guaranteed to produce them in line/column order, this will provide
// a stable ordering.
- std::sort(vec->begin(), vec->end(), SLocSort());
-
+ std::sort(vec->begin(), vec->end(),
+ [](const UninitUse &a, const UninitUse &b) {
+ // Prefer a more confident report over a less confident one.
+ if (a.getKind() != b.getKind())
+ return a.getKind() > b.getKind();
+ return a.getUser()->getLocStart() < b.getUser()->getLocStart();
+ });
+
for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve;
++vi) {
// If we have self-init, downgrade all uses to 'may be uninitialized'.
@@ -1304,12 +1429,13 @@
SourceLocation FunLocation, FunEndLocation;
// Helper functions
- void warnLockMismatch(unsigned DiagID, Name LockName, SourceLocation Loc) {
+ void warnLockMismatch(unsigned DiagID, StringRef Kind, Name LockName,
+ SourceLocation Loc) {
// Gracefully handle rare cases when the analysis can't get a more
// precise source location.
if (!Loc.isValid())
Loc = FunLocation;
- PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << LockName);
+ PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind << LockName);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
@@ -1332,22 +1458,33 @@
}
}
- void handleInvalidLockExp(SourceLocation Loc) {
- PartialDiagnosticAt Warning(Loc,
- S.PDiag(diag::warn_cannot_resolve_lock) << Loc);
+ void handleInvalidLockExp(StringRef Kind, SourceLocation Loc) override {
+ PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_cannot_resolve_lock)
+ << Loc);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
- void handleUnmatchedUnlock(Name LockName, SourceLocation Loc) {
- warnLockMismatch(diag::warn_unlock_but_no_lock, LockName, Loc);
+ void handleUnmatchedUnlock(StringRef Kind, Name LockName,
+ SourceLocation Loc) override {
+ warnLockMismatch(diag::warn_unlock_but_no_lock, Kind, LockName, Loc);
+ }
+ void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
+ LockKind Expected, LockKind Received,
+ SourceLocation Loc) override {
+ if (Loc.isInvalid())
+ Loc = FunLocation;
+ PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unlock_kind_mismatch)
+ << Kind << LockName << Received
+ << Expected);
+ Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ }
+ void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation Loc) override {
+ warnLockMismatch(diag::warn_double_lock, Kind, LockName, Loc);
}
- void handleDoubleLock(Name LockName, SourceLocation Loc) {
- warnLockMismatch(diag::warn_double_lock, LockName, Loc);
- }
-
- void handleMutexHeldEndOfScope(Name LockName, SourceLocation LocLocked,
+ void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
+ SourceLocation LocLocked,
SourceLocation LocEndOfScope,
- LockErrorKind LEK){
+ LockErrorKind LEK) override {
unsigned DiagID = 0;
switch (LEK) {
case LEK_LockedSomePredecessors:
@@ -1366,29 +1503,33 @@
if (LocEndOfScope.isInvalid())
LocEndOfScope = FunEndLocation;
- PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << LockName);
+ PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << Kind
+ << LockName);
if (LocLocked.isValid()) {
- PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here));
+ PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here)
+ << Kind);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
return;
}
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
-
- void handleExclusiveAndShared(Name LockName, SourceLocation Loc1,
- SourceLocation Loc2) {
- PartialDiagnosticAt Warning(
- Loc1, S.PDiag(diag::warn_lock_exclusive_and_shared) << LockName);
- PartialDiagnosticAt Note(
- Loc2, S.PDiag(diag::note_lock_exclusive_and_shared) << LockName);
+ void handleExclusiveAndShared(StringRef Kind, Name LockName,
+ SourceLocation Loc1,
+ SourceLocation Loc2) override {
+ PartialDiagnosticAt Warning(Loc1,
+ S.PDiag(diag::warn_lock_exclusive_and_shared)
+ << Kind << LockName);
+ PartialDiagnosticAt Note(Loc2, S.PDiag(diag::note_lock_exclusive_and_shared)
+ << Kind << LockName);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
}
- void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK,
- AccessKind AK, SourceLocation Loc) {
- assert((POK == POK_VarAccess || POK == POK_VarDereference)
- && "Only works for variables");
+ void handleNoMutexHeld(StringRef Kind, const NamedDecl *D,
+ ProtectedOperationKind POK, AccessKind AK,
+ SourceLocation Loc) override {
+ assert((POK == POK_VarAccess || POK == POK_VarDereference) &&
+ "Only works for variables");
unsigned DiagID = POK == POK_VarAccess?
diag::warn_variable_requires_any_lock:
diag::warn_var_deref_requires_any_lock;
@@ -1397,9 +1538,10 @@
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
- void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK,
- Name LockName, LockKind LK, SourceLocation Loc,
- Name *PossibleMatch) {
+ void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
+ ProtectedOperationKind POK, Name LockName,
+ LockKind LK, SourceLocation Loc,
+ Name *PossibleMatch) override {
unsigned DiagID = 0;
if (PossibleMatch) {
switch (POK) {
@@ -1413,10 +1555,11 @@
DiagID = diag::warn_fun_requires_lock_precise;
break;
}
- PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
- << D->getNameAsString() << LockName << LK);
+ PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
+ << D->getNameAsString()
+ << LockName << LK);
PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match)
- << *PossibleMatch);
+ << *PossibleMatch);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
} else {
switch (POK) {
@@ -1430,15 +1573,17 @@
DiagID = diag::warn_fun_requires_lock;
break;
}
- PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
- << D->getNameAsString() << LockName << LK);
+ PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
+ << D->getNameAsString()
+ << LockName << LK);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
}
- void handleFunExcludesLock(Name FunName, Name LockName, SourceLocation Loc) {
- PartialDiagnosticAt Warning(Loc,
- S.PDiag(diag::warn_fun_excludes_mutex) << FunName << LockName);
+ void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
+ SourceLocation Loc) override {
+ PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex)
+ << Kind << FunName << LockName);
Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
}
};
@@ -1461,8 +1606,8 @@
public:
ConsumedWarningsHandler(Sema &S) : S(S) {}
-
- void emitDiagnostics() {
+
+ void emitDiagnostics() override {
Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
for (DiagList::iterator I = Warnings.begin(), E = Warnings.end();
@@ -1476,8 +1621,9 @@
}
}
}
-
- void warnLoopStateMismatch(SourceLocation Loc, StringRef VariableName) {
+
+ void warnLoopStateMismatch(SourceLocation Loc,
+ StringRef VariableName) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_loop_state_mismatch) <<
VariableName);
@@ -1487,7 +1633,7 @@
void warnParamReturnTypestateMismatch(SourceLocation Loc,
StringRef VariableName,
StringRef ExpectedState,
- StringRef ObservedState) {
+ StringRef ObservedState) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_param_return_typestate_mismatch) << VariableName <<
@@ -1497,7 +1643,7 @@
}
void warnParamTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
- StringRef ObservedState) {
+ StringRef ObservedState) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState);
@@ -1506,7 +1652,7 @@
}
void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
- StringRef TypeName) {
+ StringRef TypeName) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_return_typestate_for_unconsumable_type) << TypeName);
@@ -1514,7 +1660,7 @@
}
void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState,
- StringRef ObservedState) {
+ StringRef ObservedState) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState);
@@ -1523,7 +1669,7 @@
}
void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State,
- SourceLocation Loc) {
+ SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(
diag::warn_use_of_temp_in_invalid_state) << MethodName << State);
@@ -1532,7 +1678,7 @@
}
void warnUseInInvalidState(StringRef MethodName, StringRef VariableName,
- StringRef State, SourceLocation Loc) {
+ StringRef State, SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) <<
MethodName << VariableName << State);
@@ -1554,6 +1700,11 @@
enableConsumedAnalysis = 0;
}
+static unsigned isEnabled(DiagnosticsEngine &D, unsigned diag) {
+ return (unsigned) D.getDiagnosticLevel(diag, SourceLocation()) !=
+ DiagnosticsEngine::Ignored;
+}
+
clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s)
: S(s),
NumFunctionsAnalyzed(0),
@@ -1565,16 +1716,21 @@
MaxUninitAnalysisVariablesPerFunction(0),
NumUninitAnalysisBlockVisits(0),
MaxUninitAnalysisBlockVisitsPerFunction(0) {
+
+ using namespace diag;
DiagnosticsEngine &D = S.getDiagnostics();
- DefaultPolicy.enableCheckUnreachable = (unsigned)
- (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) !=
- DiagnosticsEngine::Ignored);
- 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);
+
+ DefaultPolicy.enableCheckUnreachable =
+ isEnabled(D, warn_unreachable) ||
+ isEnabled(D, warn_unreachable_break) ||
+ isEnabled(D, warn_unreachable_return) ||
+ isEnabled(D, warn_unreachable_loop_increment);
+
+ DefaultPolicy.enableThreadSafetyAnalysis =
+ isEnabled(D, warn_double_lock);
+
+ DefaultPolicy.enableConsumedAnalysis =
+ isEnabled(D, warn_use_in_invalid_state);
}
static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) {
@@ -1629,6 +1785,7 @@
AC.getCFGBuildOptions().AddInitializers = true;
AC.getCFGBuildOptions().AddImplicitDtors = true;
AC.getCFGBuildOptions().AddTemporaryDtors = true;
+ AC.getCFGBuildOptions().AddCXXNewAllocator = false;
// Force that certain expressions appear as CFGElements in the CFG. This
// is used to speed up various analyses.
@@ -1789,6 +1946,16 @@
D->getLocStart()) != DiagnosticsEngine::Ignored)
diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap());
+
+ // Check for infinite self-recursion in functions
+ if (Diags.getDiagnosticLevel(diag::warn_infinite_recursive_function,
+ D->getLocStart())
+ != DiagnosticsEngine::Ignored) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ checkRecursiveFunction(S, FD, Body, AC);
+ }
+ }
+
// Collect statistics about the CFG if it was built.
if (S.CollectStats && AC.isCFGBuilt()) {
++NumFunctionsAnalyzed;
diff --git a/lib/Sema/Android.mk b/lib/Sema/Android.mk
index b9b496a..77a2e93 100644
--- a/lib/Sema/Android.mk
+++ b/lib/Sema/Android.mk
@@ -13,6 +13,7 @@
AttrParsedAttrList.inc \
AttrSpellingListIndex.inc \
AttrTemplateInstantiate.inc \
+ AttrVisitor.inc \
CommentCommandList.inc \
CommentNodes.inc \
DeclNodes.inc \
@@ -69,7 +70,6 @@
SemaTemplateInstantiateDecl.cpp \
SemaTemplateVariadic.cpp \
SemaType.cpp \
- TargetAttributesSema.cpp \
TypeLocBuilder.cpp
LOCAL_SRC_FILES := $(clang_sema_SRC_FILES)
diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp
index c980772..476a22b 100644
--- a/lib/Sema/AttributeList.cpp
+++ b/lib/Sema/AttributeList.cpp
@@ -13,8 +13,11 @@
#include "clang/Sema/AttributeList.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
@@ -103,14 +106,6 @@
} while (pool);
}
-AttributeList *
-AttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
- SourceLocation TokLoc, int Arg) {
- ArgsUnion IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg),
- C.IntTy, TokLoc);
- return create(Name, TokLoc, 0, TokLoc, &IArg, 1, AttributeList::AS_GNU);
-}
-
#include "clang/Sema/AttrParsedAttrKinds.inc"
AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
@@ -118,21 +113,25 @@
Syntax SyntaxUsed) {
StringRef AttrName = Name->getName();
- // Normalize the attribute name, __foo__ becomes foo.
- if (AttrName.startswith("__") && AttrName.endswith("__") &&
- AttrName.size() >= 4)
- AttrName = AttrName.substr(2, AttrName.size() - 4);
-
- SmallString<64> Buf;
+ SmallString<64> FullName;
if (ScopeName)
- Buf += ScopeName->getName();
+ FullName += ScopeName->getName();
+
+ // Normalize the attribute name, __foo__ becomes foo. This is only allowable
+ // for GNU attributes.
+ bool IsGNU = SyntaxUsed == AS_GNU || (SyntaxUsed == AS_CXX11 &&
+ FullName == "gnu");
+ if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
+ AttrName.endswith("__"))
+ AttrName = AttrName.slice(2, AttrName.size() - 2);
+
// Ensure that in the case of C++11 attributes, we look for '::foo' if it is
// unscoped.
if (ScopeName || SyntaxUsed == AS_CXX11)
- Buf += "::";
- Buf += AttrName;
+ FullName += "::";
+ FullName += AttrName;
- return ::getAttrKind(Buf);
+ return ::getAttrKind(FullName, SyntaxUsed);
}
unsigned AttributeList::getAttributeSpellingListIndex() const {
@@ -149,6 +148,15 @@
unsigned NumArgs : 4;
unsigned OptArgs : 4;
unsigned HasCustomParsing : 1;
+ unsigned IsTargetSpecific : 1;
+ unsigned IsType : 1;
+ unsigned IsKnownToGCC : 1;
+
+ bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
+ const Decl *);
+ bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
+ bool (*ExistsInTarget)(const llvm::Triple &T);
+ unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr);
};
namespace {
@@ -170,3 +178,31 @@
bool AttributeList::hasCustomParsing() const {
return getInfo(*this).HasCustomParsing;
}
+
+bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
+ return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
+}
+
+bool AttributeList::diagnoseLangOpts(Sema &S) const {
+ return getInfo(*this).DiagLangOpts(S, *this);
+}
+
+bool AttributeList::isTargetSpecificAttr() const {
+ return getInfo(*this).IsTargetSpecific;
+}
+
+bool AttributeList::isTypeAttr() const {
+ return getInfo(*this).IsType;
+}
+
+bool AttributeList::existsInTarget(const llvm::Triple &T) const {
+ return getInfo(*this).ExistsInTarget(T);
+}
+
+bool AttributeList::isKnownToGCC() const {
+ return getInfo(*this).IsKnownToGCC;
+}
+
+unsigned AttributeList::getSemanticSpelling() const {
+ return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
+}
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 5e09140..7847d2c 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -1,8 +1,5 @@
set(LLVM_LINK_COMPONENTS
- ${LLVM_TARGETS_TO_BUILD}
- asmparser
- support
- mc
+ Support
)
add_clang_library(clangSema
@@ -50,30 +47,9 @@
SemaTemplateInstantiateDecl.cpp
SemaTemplateVariadic.cpp
SemaType.cpp
- TargetAttributesSema.cpp
TypeLocBuilder.cpp
- )
-add_dependencies(clangSema
- ClangARMNeon
- ClangAttrClasses
- ClangAttrList
- ClangAttrParsedAttrList
- ClangAttrParsedAttrKinds
- ClangAttrParsedAttrImpl
- ClangAttrSpellingListIndex
- ClangAttrTemplateInstantiate
- ClangCommentNodes
- ClangDeclNodes
- ClangDiagnosticAST
- ClangDiagnosticComment
- ClangDiagnosticCommon
- ClangDiagnosticParse
- ClangDiagnosticSema
- ClangStmtNodes
- )
-
-target_link_libraries(clangSema
+ LINK_LIBS
clangAST
clangAnalysis
clangBasic
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index c2f1615..5c2006f 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -149,8 +149,8 @@
DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
bool isAmbiguous,
SourceLocation LParenLoc,
- ParamInfo *ArgInfo,
- unsigned NumArgs,
+ ParamInfo *Params,
+ unsigned NumParams,
SourceLocation EllipsisLoc,
SourceLocation RParenLoc,
unsigned TypeQuals,
@@ -185,10 +185,10 @@
I.Fun.LParenLoc = LParenLoc.getRawEncoding();
I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
I.Fun.RParenLoc = RParenLoc.getRawEncoding();
- I.Fun.DeleteArgInfo = false;
+ I.Fun.DeleteParams = false;
I.Fun.TypeQuals = TypeQuals;
- I.Fun.NumArgs = NumArgs;
- I.Fun.ArgInfo = 0;
+ I.Fun.NumParams = NumParams;
+ I.Fun.Params = 0;
I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef;
I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
I.Fun.ConstQualifierLoc = ConstQualifierLoc.getRawEncoding();
@@ -203,22 +203,22 @@
TrailingReturnType.isInvalid();
I.Fun.TrailingReturnType = TrailingReturnType.get();
- // new[] an argument array if needed.
- if (NumArgs) {
+ // new[] a parameter array if needed.
+ if (NumParams) {
// If the 'InlineParams' in Declarator is unused and big enough, put our
// parameter list there (in an effort to avoid new/delete traffic). If it
// is already used (consider a function returning a function pointer) or too
- // small (function taking too many arguments), go to the heap.
+ // small (function with too many parameters), go to the heap.
if (!TheDeclarator.InlineParamsUsed &&
- NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
- I.Fun.ArgInfo = TheDeclarator.InlineParams;
- I.Fun.DeleteArgInfo = false;
+ NumParams <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
+ I.Fun.Params = TheDeclarator.InlineParams;
+ I.Fun.DeleteParams = false;
TheDeclarator.InlineParamsUsed = true;
} else {
- I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs];
- I.Fun.DeleteArgInfo = true;
+ I.Fun.Params = new DeclaratorChunk::ParamInfo[NumParams];
+ I.Fun.DeleteParams = true;
}
- memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
+ memcpy(I.Fun.Params, Params, sizeof(Params[0]) * NumParams);
}
// Check what exception specification information we should actually store.
@@ -285,14 +285,6 @@
case TST_unspecified:
case TST_void:
case TST_wchar:
- case TST_image1d_t:
- case TST_image1d_array_t:
- case TST_image1d_buffer_t:
- case TST_image2d_t:
- case TST_image2d_array_t:
- case TST_image3d_t:
- case TST_sampler_t:
- case TST_event_t:
return false;
case TST_decltype_auto:
@@ -426,12 +418,13 @@
llvm_unreachable("Unknown typespec!");
}
-const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
+const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
+ const PrintingPolicy &Policy) {
switch (T) {
case DeclSpec::TST_unspecified: return "unspecified";
case DeclSpec::TST_void: return "void";
case DeclSpec::TST_char: return "char";
- case DeclSpec::TST_wchar: return "wchar_t";
+ case DeclSpec::TST_wchar: return Policy.MSWChar ? "__wchar_t" : "wchar_t";
case DeclSpec::TST_char16: return "char16_t";
case DeclSpec::TST_char32: return "char32_t";
case DeclSpec::TST_int: return "int";
@@ -439,7 +432,7 @@
case DeclSpec::TST_half: return "half";
case DeclSpec::TST_float: return "float";
case DeclSpec::TST_double: return "double";
- case DeclSpec::TST_bool: return "_Bool";
+ case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool";
case DeclSpec::TST_decimal32: return "_Decimal32";
case DeclSpec::TST_decimal64: return "_Decimal64";
case DeclSpec::TST_decimal128: return "_Decimal128";
@@ -457,14 +450,6 @@
case DeclSpec::TST_underlyingType: return "__underlying_type";
case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
case DeclSpec::TST_atomic: return "_Atomic";
- case DeclSpec::TST_image1d_t: return "image1d_t";
- case DeclSpec::TST_image1d_array_t: return "image1d_array_t";
- case DeclSpec::TST_image1d_buffer_t: return "image1d_buffer_t";
- case DeclSpec::TST_image2d_t: return "image2d_t";
- case DeclSpec::TST_image2d_array_t: return "image2d_array_t";
- case DeclSpec::TST_image3d_t: return "image3d_t";
- case DeclSpec::TST_sampler_t: return "sampler_t";
- case DeclSpec::TST_event_t: return "event_t";
case DeclSpec::TST_error: return "(error)";
}
llvm_unreachable("Unknown typespec!");
@@ -483,7 +468,8 @@
bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
const char *&PrevSpec,
- unsigned &DiagID) {
+ unsigned &DiagID,
+ const PrintingPolicy &Policy) {
// OpenCL v1.1 s6.8g: "The extern, static, auto and register storage-class
// specifiers are not supported.
// It seems sensible to prohibit private_extern too
@@ -518,10 +504,10 @@
bool isInvalid = true;
if (TypeSpecType == TST_unspecified && S.getLangOpts().CPlusPlus) {
if (SC == SCS_auto)
- return SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID);
+ return SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID, Policy);
if (StorageClassSpec == SCS_auto) {
isInvalid = SetTypeSpecType(TST_auto, StorageClassSpecLoc,
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
assert(!isInvalid && "auto SCS -> TST recovery failed");
}
}
@@ -557,7 +543,8 @@
/// specified).
bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
const char *&PrevSpec,
- unsigned &DiagID) {
+ unsigned &DiagID,
+ const PrintingPolicy &Policy) {
// Overwrite TSWLoc only if TypeSpecWidth was unspecified, so that
// for 'long long' we will keep the source location of the first 'long'.
if (TypeSpecWidth == TSW_unspecified)
@@ -568,7 +555,7 @@
TypeSpecWidth = W;
if (TypeAltiVecVector && !TypeAltiVecBool &&
((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::warn_vector_long_decl_spec_combination;
return true;
}
@@ -598,19 +585,21 @@
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
const char *&PrevSpec,
unsigned &DiagID,
- ParsedType Rep) {
- return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep);
+ ParsedType Rep,
+ const PrintingPolicy &Policy) {
+ return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Policy);
}
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
SourceLocation TagNameLoc,
const char *&PrevSpec,
unsigned &DiagID,
- ParsedType Rep) {
+ ParsedType Rep,
+ const PrintingPolicy &Policy) {
assert(isTypeRep(T) && "T does not store a type");
assert(Rep && "no type provided!");
if (TypeSpecType != TST_unspecified) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_decl_spec_combination;
return true;
}
@@ -625,11 +614,12 @@
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
const char *&PrevSpec,
unsigned &DiagID,
- Expr *Rep) {
+ Expr *Rep,
+ const PrintingPolicy &Policy) {
assert(isExprRep(T) && "T does not store an expr");
assert(Rep && "no expression provided!");
if (TypeSpecType != TST_unspecified) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_decl_spec_combination;
return true;
}
@@ -644,20 +634,22 @@
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
const char *&PrevSpec,
unsigned &DiagID,
- Decl *Rep, bool Owned) {
- return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Owned);
+ Decl *Rep, bool Owned,
+ const PrintingPolicy &Policy) {
+ return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Owned, Policy);
}
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
SourceLocation TagNameLoc,
const char *&PrevSpec,
unsigned &DiagID,
- Decl *Rep, bool Owned) {
+ Decl *Rep, bool Owned,
+ const PrintingPolicy &Policy) {
assert(isDeclRep(T) && "T does not store a decl");
// Unlike the other cases, we don't assert that we actually get a decl.
if (TypeSpecType != TST_unspecified) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_decl_spec_combination;
return true;
}
@@ -671,11 +663,12 @@
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
const char *&PrevSpec,
- unsigned &DiagID) {
+ unsigned &DiagID,
+ const PrintingPolicy &Policy) {
assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) &&
"rep required for these type-spec kinds!");
if (TypeSpecType != TST_unspecified) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_decl_spec_combination;
return true;
}
@@ -688,7 +681,7 @@
TypeSpecType = T;
TypeSpecOwned = false;
if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_vector_decl_spec;
return true;
}
@@ -696,9 +689,10 @@
}
bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
- const char *&PrevSpec, unsigned &DiagID) {
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy) {
if (TypeSpecType != TST_unspecified) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_vector_decl_spec_combination;
return true;
}
@@ -708,10 +702,11 @@
}
bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
- const char *&PrevSpec, unsigned &DiagID) {
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy) {
if (!TypeAltiVecVector || TypeAltiVecPixel ||
(TypeSpecType != TST_unspecified)) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_pixel_decl_spec_combination;
return true;
}
@@ -722,10 +717,11 @@
}
bool DeclSpec::SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc,
- const char *&PrevSpec, unsigned &DiagID) {
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy) {
if (!TypeAltiVecVector || TypeAltiVecBool ||
(TypeSpecType != TST_unspecified)) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
DiagID = diag::err_invalid_vector_bool_decl_spec;
return true;
}
@@ -843,7 +839,12 @@
unsigned &DiagID) {
if (Friend_specified) {
PrevSpec = "friend";
- DiagID = diag::ext_duplicate_declspec;
+ // Keep the later location, so that we can later diagnose ill-formed
+ // declarations like 'friend class X friend;'. Per [class.friend]p3,
+ // 'friend' must be the first token in a friend declaration that is
+ // not a function declaration.
+ FriendLoc = Loc;
+ DiagID = diag::warn_duplicate_declspec;
return true;
}
@@ -866,7 +867,13 @@
bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID) {
- // 'constexpr constexpr' is ok.
+ // 'constexpr constexpr' is ok, but warn as this is likely not what the user
+ // intended.
+ if (Constexpr_specified) {
+ DiagID = diag::warn_duplicate_declspec;
+ PrevSpec = "constexpr";
+ return true;
+ }
Constexpr_specified = true;
ConstexprLoc = Loc;
return false;
@@ -906,7 +913,7 @@
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
-void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
+void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPolicy &Policy) {
// Before possibly changing their values, save specs as written.
SaveWrittenBuiltinSpecs();
@@ -959,7 +966,7 @@
(TypeSpecType != TST_int)) || TypeAltiVecPixel) {
Diag(D, TSTLoc, diag::err_invalid_vector_bool_decl_spec)
<< (TypeAltiVecPixel ? "__pixel" :
- getSpecifierName((TST)TypeSpecType));
+ getSpecifierName((TST)TypeSpecType, Policy));
}
// Only 'short' is valid with vector bool. (PIM 2.1)
@@ -989,7 +996,7 @@
else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 &&
TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
Diag(D, TSSLoc, diag::err_invalid_sign_spec)
- << getSpecifierName((TST)TypeSpecType);
+ << getSpecifierName((TST)TypeSpecType, Policy);
// signed double -> double.
TypeSpecSign = TSS_unspecified;
}
@@ -1006,7 +1013,7 @@
Diag(D, TSWLoc,
TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec
: diag::err_invalid_longlong_spec)
- << getSpecifierName((TST)TypeSpecType);
+ << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
TypeSpecOwned = false;
}
@@ -1016,7 +1023,7 @@
TypeSpecType = TST_int; // long -> long int.
else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
Diag(D, TSWLoc, diag::err_invalid_long_spec)
- << getSpecifierName((TST)TypeSpecType);
+ << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
TypeSpecOwned = false;
}
@@ -1038,7 +1045,7 @@
Diag(D, TSTLoc, diag::ext_integer_complex);
} else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
Diag(D, TSCLoc, diag::err_invalid_complex_spec)
- << getSpecifierName((TST)TypeSpecType);
+ << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecComplex = TSC_unspecified;
}
}
diff --git a/lib/Sema/DelayedDiagnostic.cpp b/lib/Sema/DelayedDiagnostic.cpp
index 3100432..533b7ef 100644
--- a/lib/Sema/DelayedDiagnostic.cpp
+++ b/lib/Sema/DelayedDiagnostic.cpp
@@ -19,13 +19,22 @@
using namespace clang;
using namespace sema;
-DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc,
+DelayedDiagnostic
+DelayedDiagnostic::makeAvailability(Sema::AvailabilityDiagnostic AD,
+ SourceLocation Loc,
const NamedDecl *D,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
StringRef Msg) {
DelayedDiagnostic DD;
- DD.Kind = Deprecation;
+ switch (AD) {
+ case Sema::AD_Deprecation:
+ DD.Kind = Deprecation;
+ break;
+ case Sema::AD_Unavailable:
+ DD.Kind = Unavailable;
+ break;
+ }
DD.Triggered = false;
DD.Loc = Loc;
DD.DeprecationData.Decl = D;
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index 6e354b9..705fb07 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -95,7 +95,7 @@
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S,
- bool ExplicitInstantiationOrSpecialization) const {
+ bool AllowInlineNamespace) const {
Ctx = Ctx->getRedeclContext();
if (Ctx->isFunctionOrMethod() || S->isFunctionPrototypeScope()) {
@@ -131,9 +131,8 @@
}
DeclContext *DCtx = D->getDeclContext()->getRedeclContext();
- return ExplicitInstantiationOrSpecialization
- ? Ctx->InEnclosingNamespaceSetOf(DCtx)
- : Ctx->Equals(DCtx);
+ return AllowInlineNamespace ? Ctx->InEnclosingNamespaceSetOf(DCtx)
+ : Ctx->Equals(DCtx);
}
/// AddDecl - Link the decl to its shadowed decl chain.
@@ -274,10 +273,8 @@
// If the existing declaration is somewhere in the previous declaration
// chain of the new declaration, then prefer the new declaration.
- for (Decl::redecl_iterator RD = New->redecls_begin(),
- RDEnd = New->redecls_end();
- RD != RDEnd; ++RD) {
- if (*RD == Existing)
+ for (auto RD : New->redecls()) {
+ if (RD == Existing)
return DMK_Replace;
if (RD->isCanonicalDecl())
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index d3de173..1f5d682 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -121,9 +121,11 @@
/// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a
/// diagnostic that should be emitted if control goes over it. If not, return 0.
-static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) {
+static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
unsigned InDiag = 0;
+ unsigned OutDiag = 0;
+
if (VD->getType()->isVariablyModifiedType())
InDiag = diag::note_protected_by_vla;
@@ -135,21 +137,24 @@
return ScopePair(diag::note_protected_by_cleanup,
diag::note_exits_cleanup);
- if (Context.getLangOpts().ObjCAutoRefCount && VD->hasLocalStorage()) {
- switch (VD->getType().getObjCLifetime()) {
- case Qualifiers::OCL_None:
- case Qualifiers::OCL_ExplicitNone:
- case Qualifiers::OCL_Autoreleasing:
- break;
-
- case Qualifiers::OCL_Strong:
- case Qualifiers::OCL_Weak:
+ if (VD->hasLocalStorage()) {
+ switch (VD->getType().isDestructedType()) {
+ case QualType::DK_objc_strong_lifetime:
+ case QualType::DK_objc_weak_lifetime:
return ScopePair(diag::note_protected_by_objc_ownership,
diag::note_exits_objc_ownership);
+
+ case QualType::DK_cxx_destructor:
+ OutDiag = diag::note_exits_dtor;
+ break;
+
+ case QualType::DK_none:
+ break;
}
}
- if (Context.getLangOpts().CPlusPlus && VD->hasLocalStorage()) {
+ const Expr *Init = VD->getInit();
+ if (S.Context.getLangOpts().CPlusPlus && VD->hasLocalStorage() && Init) {
// C++11 [stmt.dcl]p3:
// A program that jumps from a point where a variable with automatic
// storage duration is not in scope to a point where it is in scope
@@ -164,68 +169,34 @@
// where it is in scope is ill-formed unless the variable has
// POD type and is declared without an initializer.
- const Expr *Init = VD->getInit();
- if (!Init)
- return ScopePair(InDiag, 0);
+ InDiag = diag::note_protected_by_variable_init;
- const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init);
- if (EWC)
- Init = EWC->getSubExpr();
-
- const MaterializeTemporaryExpr *M = NULL;
- Init = Init->findMaterializedTemporary(M);
-
- SmallVector<const Expr *, 2> CommaLHSs;
- SmallVector<SubobjectAdjustment, 2> Adjustments;
- Init = Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
-
- QualType QT = Init->getType();
- if (QT.isNull())
- return ScopePair(diag::note_protected_by_variable_init, 0);
-
- const Type *T = QT.getTypePtr();
- if (T->isArrayType())
- T = T->getBaseElementTypeUnsafe();
-
- const CXXRecordDecl *Record = T->getAsCXXRecordDecl();
- if (!Record)
- return ScopePair(diag::note_protected_by_variable_init, 0);
-
- // If we need to call a non trivial destructor for this variable,
- // record an out diagnostic.
- unsigned OutDiag = 0;
- if (!Init->isGLValue() && !Record->hasTrivialDestructor())
- OutDiag = diag::note_exits_dtor;
-
- if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(Init)) {
- const CXXConstructorDecl *ctor = cce->getConstructor();
- // 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) {
+ // For a variable of (array of) class type declared without an
+ // initializer, we will have call-style initialization and the initializer
+ // will be the CXXConstructExpr with no intervening nodes.
+ if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) {
+ const CXXConstructorDecl *Ctor = CCE->getConstructor();
+ if (Ctor->isTrivial() && Ctor->isDefaultConstructor() &&
+ VD->getInitStyle() == VarDecl::CallInit) {
if (OutDiag)
InDiag = diag::note_protected_by_variable_nontriv_destructor;
- else if (!Record->isPOD())
+ else if (!Ctor->getParent()->isPOD())
InDiag = diag::note_protected_by_variable_non_pod;
- return ScopePair(InDiag, OutDiag);
+ else
+ InDiag = 0;
}
}
-
- return ScopePair(diag::note_protected_by_variable_init, OutDiag);
}
- return ScopePair(InDiag, 0);
+ return ScopePair(InDiag, OutDiag);
}
- if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+ if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
if (TD->getUnderlyingType()->isVariablyModifiedType())
- return ScopePair(diag::note_protected_by_vla_typedef, 0);
- }
-
- if (const TypeAliasDecl *TD = dyn_cast<TypeAliasDecl>(D)) {
- if (TD->getUnderlyingType()->isVariablyModifiedType())
- return ScopePair(diag::note_protected_by_vla_type_alias, 0);
+ return ScopePair(isa<TypedefDecl>(TD)
+ ? diag::note_protected_by_vla_typedef
+ : diag::note_protected_by_vla_type_alias,
+ 0);
}
return ScopePair(0U, 0U);
@@ -234,7 +205,7 @@
/// \brief Build scope information for a declaration that is part of a DeclStmt.
void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
// If this decl causes a new scope, push and switch to it.
- std::pair<unsigned,unsigned> Diags = GetDiagForGotoScopeDecl(S.Context, D);
+ std::pair<unsigned,unsigned> Diags = GetDiagForGotoScopeDecl(S, D);
if (Diags.first || Diags.second) {
Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second,
D->getLocation()));
@@ -396,9 +367,8 @@
if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) {
// The decl statement creates a scope if any of the decls in it are VLAs
// or have the cleanup attribute.
- for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
- I != E; ++I)
- BuildScopeInformation(*I, ParentScope);
+ for (auto *I : DS->decls())
+ BuildScopeInformation(I, ParentScope);
continue;
}
// Disallow jumps into any part of an @try statement by pushing a scope and
@@ -474,14 +444,32 @@
if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(SubStmt)) {
for (unsigned i = 0, e = EWC->getNumObjects(); i != e; ++i) {
const BlockDecl *BDecl = EWC->getObject(i);
- for (BlockDecl::capture_const_iterator ci = BDecl->capture_begin(),
- ce = BDecl->capture_end(); ci != ce; ++ci) {
- VarDecl *variable = ci->getVariable();
+ for (const auto &CI : BDecl->captures()) {
+ VarDecl *variable = CI.getVariable();
BuildScopeInformation(variable, BDecl, ParentScope);
}
}
}
-
+
+ // Disallow jumps out of scopes containing temporaries lifetime-extended to
+ // automatic storage duration.
+ if (MaterializeTemporaryExpr *MTE =
+ dyn_cast<MaterializeTemporaryExpr>(SubStmt)) {
+ if (MTE->getStorageDuration() == SD_Automatic) {
+ SmallVector<const Expr *, 4> CommaLHS;
+ SmallVector<SubobjectAdjustment, 4> Adjustments;
+ const Expr *ExtendedObject =
+ MTE->GetTemporaryExpr()->skipRValueSubobjectAdjustments(
+ CommaLHS, Adjustments);
+ if (ExtendedObject->getType().isDestructedType()) {
+ Scopes.push_back(GotoScope(ParentScope, 0,
+ diag::note_exits_temporary_dtor,
+ ExtendedObject->getExprLoc()));
+ ParentScope = Scopes.size()-1;
+ }
+ }
+ }
+
// Recursively walk the AST.
BuildScopeInformation(SubStmt, ParentScope);
}
@@ -762,7 +750,7 @@
SmallVector<unsigned, 10> ToScopesError;
SmallVector<unsigned, 10> ToScopesWarning;
for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope) {
- if (S.getLangOpts().MicrosoftMode && JumpDiagWarning != 0 &&
+ if (S.getLangOpts().MSVCCompat && JumpDiagWarning != 0 &&
IsMicrosoftJumpWarning(JumpDiagError, Scopes[I].InDiag))
ToScopesWarning.push_back(I);
else if (IsCXX98CompatWarning(S, Scopes[I].InDiag))
diff --git a/lib/Sema/Scope.cpp b/lib/Sema/Scope.cpp
index 10f12ce..494768d 100644
--- a/lib/Sema/Scope.cpp
+++ b/lib/Sema/Scope.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/Scope.h"
+#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -36,16 +37,24 @@
FnParent = parent->FnParent;
BlockParent = parent->BlockParent;
TemplateParamParent = parent->TemplateParamParent;
+ MSLocalManglingParent = parent->MSLocalManglingParent;
} else {
Depth = 0;
PrototypeDepth = 0;
PrototypeIndex = 0;
- FnParent = BlockParent = 0;
+ MSLocalManglingParent = FnParent = BlockParent = 0;
TemplateParamParent = 0;
+ MSLocalManglingNumber = 1;
}
// If this scope is a function or contains breaks/continues, remember it.
if (flags & FnScope) FnParent = this;
+ // The MS mangler uses the number of scopes that can hold declarations as
+ // part of an external name.
+ if (Flags & (ClassScope | FnScope)) {
+ MSLocalManglingNumber = getMSLocalManglingNumber();
+ MSLocalManglingParent = this;
+ }
if (flags & BreakScope) BreakParent = this;
if (flags & ContinueScope) ContinueParent = this;
if (flags & BlockScope) BlockParent = this;
@@ -53,6 +62,16 @@
// If this is a prototype scope, record that.
if (flags & FunctionPrototypeScope) PrototypeDepth++;
+ if (flags & DeclScope) {
+ if (flags & FunctionPrototypeScope)
+ ; // Prototype scopes are uninteresting.
+ else if ((flags & ClassScope) && getParent()->isClassScope())
+ ; // Nested class scopes aren't ambiguous.
+ else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
+ ; // Classes inside of namespaces aren't ambiguous.
+ else
+ incrementMSLocalManglingNumber();
+ }
DeclsInScope.clear();
UsingDirectives.clear();
@@ -69,3 +88,92 @@
}
return false;
}
+
+void Scope::AddFlags(unsigned FlagsToSet) {
+ assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
+ "Unsupported scope flags");
+ if (FlagsToSet & BreakScope) {
+ assert((Flags & BreakScope) == 0 && "Already set");
+ BreakParent = this;
+ }
+ if (FlagsToSet & ContinueScope) {
+ assert((Flags & ContinueScope) == 0 && "Already set");
+ ContinueParent = this;
+ }
+ Flags |= FlagsToSet;
+}
+
+void Scope::dump() const { dumpImpl(llvm::errs()); }
+
+void Scope::dumpImpl(raw_ostream &OS) const {
+ unsigned Flags = getFlags();
+ bool HasFlags = Flags != 0;
+
+ if (HasFlags)
+ OS << "Flags: ";
+
+ while (Flags) {
+ if (Flags & FnScope) {
+ OS << "FnScope";
+ Flags &= ~FnScope;
+ } else if (Flags & BreakScope) {
+ OS << "BreakScope";
+ Flags &= ~BreakScope;
+ } else if (Flags & ContinueScope) {
+ OS << "ContinueScope";
+ Flags &= ~ContinueScope;
+ } else if (Flags & DeclScope) {
+ OS << "DeclScope";
+ Flags &= ~DeclScope;
+ } else if (Flags & ControlScope) {
+ OS << "ControlScope";
+ Flags &= ~ControlScope;
+ } else if (Flags & ClassScope) {
+ OS << "ClassScope";
+ Flags &= ~ClassScope;
+ } else if (Flags & BlockScope) {
+ OS << "BlockScope";
+ Flags &= ~BlockScope;
+ } else if (Flags & TemplateParamScope) {
+ OS << "TemplateParamScope";
+ Flags &= ~TemplateParamScope;
+ } else if (Flags & FunctionPrototypeScope) {
+ OS << "FunctionPrototypeScope";
+ Flags &= ~FunctionPrototypeScope;
+ } else if (Flags & FunctionDeclarationScope) {
+ OS << "FunctionDeclarationScope";
+ Flags &= ~FunctionDeclarationScope;
+ } else if (Flags & AtCatchScope) {
+ OS << "AtCatchScope";
+ Flags &= ~AtCatchScope;
+ } else if (Flags & ObjCMethodScope) {
+ OS << "ObjCMethodScope";
+ Flags &= ~ObjCMethodScope;
+ } else if (Flags & SwitchScope) {
+ OS << "SwitchScope";
+ Flags &= ~SwitchScope;
+ } else if (Flags & TryScope) {
+ OS << "TryScope";
+ Flags &= ~TryScope;
+ } else if (Flags & FnTryCatchScope) {
+ OS << "FnTryCatchScope";
+ Flags &= ~FnTryCatchScope;
+ } else if (Flags & OpenMPDirectiveScope) {
+ OS << "OpenMPDirectiveScope";
+ Flags &= ~OpenMPDirectiveScope;
+ }
+
+ if (Flags)
+ OS << " | ";
+ }
+ if (HasFlags)
+ OS << '\n';
+
+ if (const Scope *Parent = getParent())
+ OS << "Parent: (clang::Scope*)" << Parent << '\n';
+
+ OS << "Depth: " << Depth << '\n';
+ OS << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n';
+ if (const DeclContext *DC = getEntity())
+ OS << "Entity : (clang::DeclContext*)" << DC << '\n';
+}
diff --git a/lib/Sema/ScopeInfo.cpp b/lib/Sema/ScopeInfo.cpp
index 8b3493e..1e54c5a 100644
--- a/lib/Sema/ScopeInfo.cpp
+++ b/lib/Sema/ScopeInfo.cpp
@@ -26,6 +26,12 @@
HasBranchProtectedScope = false;
HasBranchIntoScope = false;
HasIndirectGoto = false;
+ HasDroppedStmt = false;
+ ObjCShouldCallSuper = false;
+ ObjCIsDesignatedInit = false;
+ ObjCWarnForNoDesignatedInitChain = false;
+ ObjCIsSecondaryInit = false;
+ ObjCWarnForNoInitDelegation = false;
SwitchStack.clear();
Returns.clear();
@@ -184,10 +190,11 @@
ThisUse->markSafe();
}
-void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E) {
+void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD,
+ Expr *&E) const {
assert(Idx < getNumPotentialVariableCaptures() &&
- "Index of potential capture must be within 0 to less than the "
- "number of captures!");
+ "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());
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 4d01fb0..3612bb9 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "TargetAttributesSema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/DeclCXX.h"
@@ -70,13 +69,17 @@
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind,
CodeCompleteConsumer *CodeCompleter)
- : TheTargetAttributesSema(0), ExternalSource(0),
+ : ExternalSource(0),
isMultiplexExternalSource(false), FPFeatures(pp.getLangOpts()),
LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
CollectStats(false), CodeCompleter(CodeCompleter),
CurContext(0), OriginalLexicalContext(0),
- PackContext(0), MSStructPragmaOn(false), VisContext(0),
+ PackContext(0), MSStructPragmaOn(false),
+ MSPointerToMemberRepresentationMethod(
+ LangOpts.getMSPointerToMemberRepresentationMethod()),
+ VtorDispModeStack(1, MSVtorDispAttr::Mode(LangOpts.VtorDispMode)),
+ VisContext(0),
IsBuildingRecoveryCallExpr(false),
ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0),
IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
@@ -86,7 +89,7 @@
NSDictionaryDecl(0), DictionaryWithObjectsMethod(0),
GlobalNewDeleteDeclared(false),
TUKind(TUKind),
- NumSFINAEErrors(0), InFunctionDeclarator(0),
+ NumSFINAEErrors(0),
AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
CurrentInstantiationScope(0), DisableTypoCorrection(false),
@@ -120,6 +123,12 @@
InitDataSharingAttributesStack();
}
+void Sema::addImplicitTypedef(StringRef Name, QualType T) {
+ DeclarationName DN = &Context.Idents.get(Name);
+ if (IdResolver.begin(DN) == IdResolver.end())
+ PushOnScopeChains(Context.buildImplicitTypedef(T, Name), TUScope);
+}
+
void Sema::Initialize() {
// Tell the AST consumer about this Sema object.
Consumer.Initialize(Context);
@@ -172,20 +181,36 @@
PushOnScopeChains(Context.getObjCProtocolDecl(), TUScope);
}
+ // Initialize Microsoft "predefined C++ types".
+ if (PP.getLangOpts().MSVCCompat && PP.getLangOpts().CPlusPlus) {
+ if (IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end())
+ PushOnScopeChains(Context.buildImplicitRecord("type_info", TTK_Class),
+ TUScope);
+
+ addImplicitTypedef("size_t", Context.getSizeType());
+ }
+
+ // Initialize predefined OpenCL types.
+ if (PP.getLangOpts().OpenCL) {
+ addImplicitTypedef("image1d_t", Context.OCLImage1dTy);
+ addImplicitTypedef("image1d_array_t", Context.OCLImage1dArrayTy);
+ addImplicitTypedef("image1d_buffer_t", Context.OCLImage1dBufferTy);
+ addImplicitTypedef("image2d_t", Context.OCLImage2dTy);
+ addImplicitTypedef("image2d_array_t", Context.OCLImage2dArrayTy);
+ addImplicitTypedef("image3d_t", Context.OCLImage3dTy);
+ addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
+ addImplicitTypedef("event_t", Context.OCLEventTy);
+ }
+
DeclarationName BuiltinVaList = &Context.Idents.get("__builtin_va_list");
if (IdResolver.begin(BuiltinVaList) == IdResolver.end())
PushOnScopeChains(Context.getBuiltinVaListDecl(), TUScope);
}
Sema::~Sema() {
- for (LateParsedTemplateMapT::iterator I = LateParsedTemplateMap.begin(),
- E = LateParsedTemplateMap.end();
- I != E; ++I)
- delete I->second;
+ llvm::DeleteContainerSeconds(LateParsedTemplateMap);
if (PackContext) FreePackedContext();
if (VisContext) FreeVisContext();
- delete TheTargetAttributesSema;
- MSStructPragmaOn = false;
// Kill all the active scopes.
for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
delete FunctionScopes[I];
@@ -230,7 +255,7 @@
// If the function is already unavailable, it's not an error.
if (fn->hasAttr<UnavailableAttr>()) return true;
- fn->addAttr(new (Context) UnavailableAttr(loc, Context, msg));
+ fn->addAttr(UnavailableAttr::CreateImplicit(Context, msg, loc));
return true;
}
@@ -384,25 +409,6 @@
return false;
}
-namespace {
- struct SortUndefinedButUsed {
- const SourceManager &SM;
- explicit SortUndefinedButUsed(SourceManager &SM) : SM(SM) {}
-
- bool operator()(const std::pair<NamedDecl *, SourceLocation> &l,
- const std::pair<NamedDecl *, SourceLocation> &r) const {
- if (l.second.isValid() && !r.second.isValid())
- return true;
- if (!l.second.isValid() && r.second.isValid())
- return false;
- if (l.second != r.second)
- return SM.isBeforeInTranslationUnit(l.second, r.second);
- return SM.isBeforeInTranslationUnit(l.first->getLocation(),
- r.first->getLocation());
- }
- };
-}
-
/// Obtains a sorted list of functions that are undefined but ODR-used.
void Sema::getUndefinedButUsed(
SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined) {
@@ -435,8 +441,19 @@
// Sort (in order of use site) so that we're not dependent on the iteration
// order through an llvm::DenseMap.
+ SourceManager &SM = Context.getSourceManager();
std::sort(Undefined.begin(), Undefined.end(),
- SortUndefinedButUsed(Context.getSourceManager()));
+ [&SM](const std::pair<NamedDecl *, SourceLocation> &l,
+ const std::pair<NamedDecl *, SourceLocation> &r) {
+ if (l.second.isValid() && !r.second.isValid())
+ return true;
+ if (!l.second.isValid() && r.second.isValid())
+ return false;
+ if (l.second != r.second)
+ return SM.isBeforeInTranslationUnit(l.second, r.second);
+ return SM.isBeforeInTranslationUnit(l.first->getLocation(),
+ r.first->getLocation());
+ });
}
/// checkUndefinedButUsed - Check for undefined objects with internal linkage
@@ -603,7 +620,15 @@
// 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.
+ if (ExternalSource) {
+ // Load pending instantiations from the external source.
+ SmallVector<PendingImplicitInstantiation, 4> Pending;
+ ExternalSource->ReadPendingInstantiations(Pending);
+ PendingInstantiations.insert(PendingInstantiations.begin(),
+ Pending.begin(), Pending.end());
+ }
PerformPendingInstantiations();
+
CheckDelayedMemberExceptionSpecs();
}
@@ -1215,7 +1240,7 @@
ZeroArgCallReturnTy = QualType();
Ambiguous = true;
} else
- ZeroArgCallReturnTy = OverloadDecl->getResultType();
+ ZeroArgCallReturnTy = OverloadDecl->getReturnType();
}
}
}
@@ -1244,7 +1269,7 @@
if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E.IgnoreParens())) {
if (const FunctionDecl *Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) {
if (Fun->getMinRequiredArguments() == 0)
- ZeroArgCallReturnTy = Fun->getResultType();
+ ZeroArgCallReturnTy = Fun->getReturnType();
return true;
}
}
@@ -1261,8 +1286,8 @@
if (const FunctionProtoType *FPT =
dyn_cast_or_null<FunctionProtoType>(FunTy)) {
- if (FPT->getNumArgs() == 0)
- ZeroArgCallReturnTy = FunTy->getResultType();
+ if (FPT->getNumParams() == 0)
+ ZeroArgCallReturnTy = FunTy->getReturnType();
return true;
}
return false;
@@ -1313,7 +1338,7 @@
for (OverloadExpr::decls_iterator It = Overloads.begin(),
DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) {
const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*It);
- QualType OverloadResultTy = OverloadDecl->getResultType();
+ QualType OverloadResultTy = OverloadDecl->getReturnType();
if (IsPlausibleResult(OverloadResultTy))
PlausibleOverloads.addDecl(It.getDecl());
}
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 61dc157..f7806d2 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -288,12 +288,10 @@
if (Derived->isDependentContext() && !Derived->hasDefinition())
return AR_dependent;
- for (CXXRecordDecl::base_class_const_iterator
- I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) {
-
+ for (const auto &I : Derived->bases()) {
const CXXRecordDecl *RD;
- QualType T = I->getType();
+ QualType T = I.getType();
if (const RecordType *RT = T->getAs<RecordType>()) {
RD = cast<CXXRecordDecl>(RT->getDecl());
} else if (const InjectedClassNameType *IT
@@ -376,18 +374,16 @@
if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
return false;
- if (FriendTy->getNumArgs() != ContextTy->getNumArgs())
+ if (FriendTy->getNumParams() != ContextTy->getNumParams())
return false;
- if (!MightInstantiateTo(S,
- ContextTy->getResultType(),
- FriendTy->getResultType()))
+ if (!MightInstantiateTo(S, ContextTy->getReturnType(),
+ FriendTy->getReturnType()))
return false;
- for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I)
- if (!MightInstantiateTo(S,
- ContextTy->getArgType(I),
- FriendTy->getArgType(I)))
+ for (unsigned I = 0, E = FriendTy->getNumParams(); I != E; ++I)
+ if (!MightInstantiateTo(S, ContextTy->getParamType(I),
+ FriendTy->getParamType(I)))
return false;
return true;
@@ -575,10 +571,7 @@
AccessResult OnFailure = AR_inaccessible;
// Okay, check friends.
- for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
- E = Class->friend_end(); I != E; ++I) {
- FriendDecl *Friend = *I;
-
+ for (auto *Friend : Class->friends()) {
switch (MatchesFriend(S, EC, Friend)) {
case AR_accessible:
return AR_accessible;
@@ -648,18 +641,16 @@
EverDependent = true;
// Recurse into the base classes.
- for (CXXRecordDecl::base_class_const_iterator
- I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) {
-
+ for (const auto &I : Cur->bases()) {
// If this is private inheritance, then a public member of the
// base will not have any access in classes derived from Cur.
unsigned BasePrivateDepth = PrivateDepth;
- if (I->getAccessSpecifier() == AS_private)
+ if (I.getAccessSpecifier() == AS_private)
BasePrivateDepth = CurPath.size() - 1;
const CXXRecordDecl *RD;
- QualType T = I->getType();
+ QualType T = I.getType();
if (const RecordType *RT = T->getAs<RecordType>()) {
RD = cast<CXXRecordDecl>(RT->getDecl());
} else if (const InjectedClassNameType *IT
@@ -797,7 +788,7 @@
// Emulate a MSVC bug where the creation of pointer-to-member
// to protected member of base class is allowed but only from
// static member functions.
- if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty())
+ if (S.getLangOpts().MSVCCompat && !EC.Functions.empty())
if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front()))
if (MD->isStatic()) return AR_accessible;
@@ -1082,15 +1073,15 @@
(isa<FunctionTemplateDecl>(D) &&
isa<CXXConstructorDecl>(
cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) {
- S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor)
- << isa<CXXDestructorDecl>(D);
- return true;
+ return S.Diag(D->getLocation(),
+ diag::note_access_protected_restricted_ctordtor)
+ << isa<CXXDestructorDecl>(D->getAsFunction());
}
// Otherwise, use the generic diagnostic.
- S.Diag(D->getLocation(), diag::note_access_protected_restricted_object)
- << S.Context.getTypeDeclType(ECRecord);
- return true;
+ return S.Diag(D->getLocation(),
+ diag::note_access_protected_restricted_object)
+ << S.Context.getTypeDeclType(ECRecord);
}
return false;
@@ -1140,11 +1131,9 @@
// Check whether there's an AccessSpecDecl preceding this in the
// chain of the DeclContext.
bool isImplicit = true;
- for (CXXRecordDecl::decl_iterator
- I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end();
- I != E; ++I) {
- if (*I == ImmediateChild) break;
- if (isa<AccessSpecDecl>(*I)) {
+ for (const auto *I : DeclaringClass->decls()) {
+ if (I == ImmediateChild) break;
+ if (isa<AccessSpecDecl>(I)) {
isImplicit = false;
break;
}
@@ -1422,16 +1411,15 @@
AccessTarget &Entity) {
assert(Entity.getAccess() != AS_public && "called for public access!");
- if (S.getLangOpts().MicrosoftMode &&
- IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))
- return AR_accessible;
-
switch (IsAccessible(S, EC, Entity)) {
case AR_dependent:
DelayDependentAccess(S, EC, Loc, Entity);
return AR_dependent;
case AR_inaccessible:
+ if (S.getLangOpts().MSVCCompat &&
+ IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))
+ return AR_accessible;
if (!Entity.isQuiet())
DiagnoseBadAccess(S, Loc, EC, Entity);
return AR_inaccessible;
@@ -1482,11 +1470,10 @@
// However, this does not apply to local extern declarations.
DeclContext *DC = D->getDeclContext();
- if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) {
- if (D->getLexicalDeclContext()->isFunctionOrMethod())
- DC = D->getLexicalDeclContext();
- else
- DC = FN;
+ if (D->isLocalExternDecl()) {
+ DC = D->getLexicalDeclContext();
+ } else if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) {
+ DC = FN;
} else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) {
DC = cast<DeclContext>(TD->getTemplatedDecl());
}
@@ -1750,10 +1737,7 @@
/// Checks access to the target of a friend declaration.
Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) {
- assert(isa<CXXMethodDecl>(target) ||
- (isa<FunctionTemplateDecl>(target) &&
- isa<CXXMethodDecl>(cast<FunctionTemplateDecl>(target)
- ->getTemplatedDecl())));
+ assert(isa<CXXMethodDecl>(target->getAsFunction()));
// Friendship lookup is a redeclaration lookup, so there's never an
// inheritance path modifying access.
@@ -1762,10 +1746,7 @@
if (!getLangOpts().AccessControl || access == AS_public)
return AR_accessible;
- CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(target);
- if (!method)
- method = cast<CXXMethodDecl>(
- cast<FunctionTemplateDecl>(target)->getTemplatedDecl());
+ CXXMethodDecl *method = cast<CXXMethodDecl>(target->getAsFunction());
assert(method->getQualifier());
AccessTarget entity(Context, AccessTarget::Member,
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 8f9ab32..2e344ff 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -122,18 +122,23 @@
// Otherwise, check to see if we need a max field alignment attribute.
if (unsigned Alignment = Stack->getAlignment()) {
if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
- RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context));
+ RD->addAttr(AlignMac68kAttr::CreateImplicit(Context));
else
- RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(),
- Context,
+ RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(Context,
Alignment * 8));
}
}
void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
- if (!MSStructPragmaOn)
- return;
- RD->addAttr(::new (Context) MsStructAttr(SourceLocation(), Context));
+ if (MSStructPragmaOn)
+ RD->addAttr(MsStructAttr::CreateImplicit(Context));
+
+ // FIXME: We should merge AddAlignmentAttributesForRecord with
+ // AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes
+ // all active pragmas and applies them as attributes to class definitions.
+ if (VtorDispModeStack.back() != getLangOpts().VtorDispMode)
+ RD->addAttr(
+ MSVtorDispAttr::CreateImplicit(Context, VtorDispModeStack.back()));
}
void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
@@ -247,8 +252,8 @@
// If a name was specified then failure indicates the name
// wasn't found. Otherwise failure indicates the stack was
// empty.
- Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
- << (Name ? "no record matching name" : "stack empty");
+ Diag(PragmaLoc, diag::warn_pragma_pop_failed)
+ << "pack" << (Name ? "no record matching name" : "stack empty");
// FIXME: Warn about popping named records as MSVC does.
} else {
@@ -288,6 +293,38 @@
Consumer.HandleDetectMismatch(Name, Value);
}
+void Sema::ActOnPragmaMSPointersToMembers(
+ LangOptions::PragmaMSPointersToMembersKind RepresentationMethod,
+ SourceLocation PragmaLoc) {
+ MSPointerToMemberRepresentationMethod = RepresentationMethod;
+ ImplicitMSInheritanceAttrLoc = PragmaLoc;
+}
+
+void Sema::ActOnPragmaMSVtorDisp(PragmaVtorDispKind Kind,
+ SourceLocation PragmaLoc,
+ MSVtorDispAttr::Mode Mode) {
+ switch (Kind) {
+ case PVDK_Set:
+ VtorDispModeStack.back() = Mode;
+ break;
+ case PVDK_Push:
+ VtorDispModeStack.push_back(Mode);
+ break;
+ case PVDK_Reset:
+ VtorDispModeStack.clear();
+ VtorDispModeStack.push_back(MSVtorDispAttr::Mode(LangOpts.VtorDispMode));
+ break;
+ case PVDK_Pop:
+ VtorDispModeStack.pop_back();
+ if (VtorDispModeStack.empty()) {
+ Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "vtordisp"
+ << "stack empty";
+ VtorDispModeStack.push_back(MSVtorDispAttr::Mode(LangOpts.VtorDispMode));
+ }
+ break;
+ }
+}
+
void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
SourceLocation PragmaLoc) {
@@ -312,7 +349,7 @@
if (VD->isUsed())
Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
- VD->addAttr(::new (Context) UnusedAttr(IdTok.getLocation(), Context));
+ VD->addAttr(UnusedAttr::CreateImplicit(Context, IdTok.getLocation()));
}
void Sema::AddCFAuditedAttribute(Decl *D) {
@@ -324,11 +361,11 @@
D->hasAttr<CFUnknownTransferAttr>())
return;
- D->addAttr(::new (Context) CFAuditedTransferAttr(Loc, Context));
+ D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc));
}
typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
-enum { NoVisibility = (unsigned) -1 };
+enum : unsigned { NoVisibility = ~0U };
void Sema::AddPushedVisibilityAttribute(Decl *D) {
if (!VisContext)
@@ -346,7 +383,7 @@
= (VisibilityAttr::VisibilityType) rawType;
SourceLocation loc = Stack->back().second;
- D->addAttr(::new (Context) VisibilityAttr(loc, Context, type));
+ D->addAttr(VisibilityAttr::CreateImplicit(Context, type, loc));
}
/// FreeVisContext - Deallocate and null out VisContext.
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 554a114..ce47cff 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -363,7 +363,7 @@
explicit NestedNameSpecifierValidatorCCC(Sema &SRef)
: SRef(SRef) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
return SRef.isAcceptableNestedNameSpecifier(candidate.getCorrectionDecl());
}
@@ -484,7 +484,7 @@
// FIXME: Deal with ambiguities cleanly.
- if (Found.empty() && !ErrorRecoveryLookup && !getLangOpts().MicrosoftMode) {
+ if (Found.empty() && !ErrorRecoveryLookup && !getLangOpts().MSVCCompat) {
// We haven't found anything, and we're not recovering from a
// different kind of error, so look for typos.
DeclarationName Name = Found.getLookupName();
@@ -646,7 +646,7 @@
// public:
// void foo() { D::foo2(); }
// };
- if (getLangOpts().MicrosoftMode) {
+ if (getLangOpts().MSVCCompat) {
DeclContext *DC = LookupCtx ? LookupCtx : CurContext;
if (DC->isDependentContext() && DC->isFunctionOrMethod()) {
SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
@@ -654,20 +654,23 @@
}
}
- unsigned DiagID;
- if (!Found.empty())
- DiagID = diag::err_expected_class_or_namespace;
- else if (SS.isSet()) {
- Diag(IdentifierLoc, diag::err_no_member)
- << &Identifier << LookupCtx << SS.getRange();
- return true;
- } else
- DiagID = diag::err_undeclared_var_use;
-
- if (SS.isSet())
- Diag(IdentifierLoc, DiagID) << &Identifier << SS.getRange();
+ if (!Found.empty()) {
+ if (TypeDecl *TD = Found.getAsSingle<TypeDecl>())
+ Diag(IdentifierLoc, diag::err_expected_class_or_namespace)
+ << QualType(TD->getTypeForDecl(), 0) << getLangOpts().CPlusPlus;
+ else {
+ Diag(IdentifierLoc, diag::err_expected_class_or_namespace)
+ << &Identifier << getLangOpts().CPlusPlus;
+ if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
+ Diag(ND->getLocation(),
+ diag::note_expected_class_or_namespace_declared_here)
+ << &Identifier;
+ }
+ } else if (SS.isSet())
+ Diag(IdentifierLoc, diag::err_no_member) << &Identifier << LookupCtx
+ << SS.getRange();
else
- Diag(IdentifierLoc, DiagID) << &Identifier;
+ Diag(IdentifierLoc, diag::err_undeclared_var_use) << &Identifier;
return true;
}
@@ -698,7 +701,7 @@
QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
if (!T->isDependentType() && !T->getAs<TagType>()) {
- Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class)
+ Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class_or_namespace)
<< T << getLangOpts().CPlusPlus;
return true;
}
@@ -749,7 +752,8 @@
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
- if (DependentTemplateName *DTN = Template.get().getAsDependentTemplateName()){
+ DependentTemplateName *DTN = Template.get().getAsDependentTemplateName();
+ if (DTN && DTN->isIdentifier()) {
// Handle a dependent template specialization for which we cannot resolve
// the template name.
assert(DTN->getQualifier() == SS.getScopeRep());
@@ -775,20 +779,20 @@
CCLoc);
return false;
}
-
-
- if (Template.get().getAsOverloadedTemplate() ||
- isa<FunctionTemplateDecl>(Template.get().getAsTemplateDecl())) {
+
+ TemplateDecl *TD = Template.get().getAsTemplateDecl();
+ if (Template.get().getAsOverloadedTemplate() || DTN ||
+ isa<FunctionTemplateDecl>(TD) || isa<VarTemplateDecl>(TD)) {
SourceRange R(TemplateNameLoc, RAngleLoc);
if (SS.getRange().isValid())
R.setBegin(SS.getRange().getBegin());
-
+
Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier)
- << Template.get() << R;
+ << (TD && isa<VarTemplateDecl>(TD)) << Template.get() << R;
NoteAllFoundTemplates(Template.get());
return true;
}
-
+
// We were able to resolve the template name to an actual template.
// Build an appropriate nested-name-specifier.
QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc,
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index ba00b71..5d49225 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/lib/Sema/SemaCast.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Initialization.h"
#include "llvm/ADT/SmallVector.h"
#include <set>
@@ -1346,7 +1347,8 @@
QualType DestClass(DestMemPtr->getClass(), 0);
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
- if (!Self.IsDerivedFrom(SrcClass, DestClass, Paths)) {
+ if (Self.RequireCompleteType(OpRange.getBegin(), SrcClass, 0) ||
+ !Self.IsDerivedFrom(SrcClass, DestClass, Paths)) {
return TC_NotApplicable;
}
@@ -1431,6 +1433,10 @@
msg = 0;
return TC_Failed;
}
+ } else if (DestType->isMemberPointerType()) {
+ if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ Self.RequireCompleteType(OpRange.getBegin(), DestType, 0);
+ }
}
InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
@@ -1778,6 +1784,13 @@
return TC_Failed;
}
+ if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ // We need to determine the inheritance model that the class will use if
+ // haven't yet.
+ Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0);
+ Self.RequireCompleteType(OpRange.getBegin(), DestType, 0);
+ }
+
// Don't allow casting between member pointers of different sizes.
if (Self.Context.getTypeSize(DestMemPtr) !=
Self.Context.getTypeSize(SrcMemPtr)) {
@@ -2074,6 +2087,8 @@
if (Self.getLangOpts().ObjCAutoRefCount && tcr == TC_Success)
checkObjCARCConversion(CCK);
+ else if (Self.getLangOpts().ObjC1 && tcr == TC_Success)
+ Self.CheckTollFreeBridgeCast(DestType, SrcExpr.get());
if (tcr != TC_Success && msg != 0) {
if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
@@ -2168,6 +2183,21 @@
assert(!SrcType->isPlaceholderType());
+ // OpenCL v1 s6.5: Casting a pointer to address space A to a pointer to
+ // address space B is illegal.
+ if (Self.getLangOpts().OpenCL && DestType->isPointerType() &&
+ SrcType->isPointerType()) {
+ if (DestType->getPointeeType().getAddressSpace() !=
+ SrcType->getPointeeType().getAddressSpace()) {
+ Self.Diag(OpRange.getBegin(),
+ diag::err_typecheck_incompatible_address_space)
+ << SrcType << DestType << Sema::AA_Casting
+ << SrcExpr.get()->getSourceRange();
+ SrcExpr = ExprError();
+ return;
+ }
+ }
+
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
diag::err_typecheck_cast_to_incomplete)) {
SrcExpr = ExprError();
@@ -2319,6 +2349,9 @@
return;
}
}
+ else if (Self.getLangOpts().ObjC1)
+ Self.CheckTollFreeBridgeCast(DestType, SrcExpr.get());
+
DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType);
DiagnoseBadFunctionCast(Self, SrcExpr, DestType);
Kind = Self.PrepareScalarCast(SrcExpr, DestType);
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 0b95c48..27cc8a3 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/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/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>
@@ -142,6 +142,7 @@
break;
case Builtin::BI__builtin_stdarg_start:
case Builtin::BI__builtin_va_start:
+ case Builtin::BI__va_start:
if (SemaBuiltinVAStart(TheCall))
return ExprError();
break;
@@ -302,11 +303,18 @@
if (BuiltinID >= Builtin::FirstTSBuiltin) {
switch (Context.getTargetInfo().getTriple().getArch()) {
case llvm::Triple::arm:
+ case llvm::Triple::armeb:
case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
+ case llvm::Triple::arm64:
+ if (CheckARM64BuiltinFunctionCall(BuiltinID, TheCall))
+ return ExprError();
+ break;
case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
if (CheckAArch64BuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
@@ -317,6 +325,11 @@
if (CheckMipsBuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ if (CheckX86BuiltinFunctionCall(BuiltinID, TheCall))
+ return ExprError();
+ break;
default:
break;
}
@@ -326,9 +339,9 @@
}
// Get the valid immediate range for the specified NEON type code.
-static unsigned RFT(unsigned t, bool shift = false) {
+static unsigned RFT(unsigned t, bool shift = false, bool ForceQuad = false) {
NeonTypeFlags Type(t);
- int IsQuad = Type.isQuad();
+ int IsQuad = ForceQuad ? true : Type.isQuad();
switch (Type.getEltType()) {
case NeonTypeFlags::Int8:
case NeonTypeFlags::Poly8:
@@ -341,6 +354,8 @@
case NeonTypeFlags::Int64:
case NeonTypeFlags::Poly64:
return shift ? 63 : (1 << IsQuad) - 1;
+ case NeonTypeFlags::Poly128:
+ return shift ? 127 : (1 << IsQuad) - 1;
case NeonTypeFlags::Float16:
assert(!shift && "cannot shift float types!");
return (4 << IsQuad) - 1;
@@ -358,7 +373,7 @@
/// 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,
- bool IsAArch64) {
+ bool IsPolyUnsigned, bool IsInt64Long) {
switch (Flags.getEltType()) {
case NeonTypeFlags::Int8:
return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy;
@@ -367,13 +382,19 @@
case NeonTypeFlags::Int32:
return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy;
case NeonTypeFlags::Int64:
- return Flags.isUnsigned() ? Context.UnsignedLongLongTy : Context.LongLongTy;
+ if (IsInt64Long)
+ return Flags.isUnsigned() ? Context.UnsignedLongTy : Context.LongTy;
+ else
+ return Flags.isUnsigned() ? Context.UnsignedLongLongTy
+ : Context.LongLongTy;
case NeonTypeFlags::Poly8:
- return IsAArch64 ? Context.UnsignedCharTy : Context.SignedCharTy;
+ return IsPolyUnsigned ? Context.UnsignedCharTy : Context.SignedCharTy;
case NeonTypeFlags::Poly16:
- return IsAArch64 ? Context.UnsignedShortTy : Context.ShortTy;
+ return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy;
case NeonTypeFlags::Poly64:
- return Context.UnsignedLongLongTy;
+ return Context.UnsignedLongTy;
+ case NeonTypeFlags::Poly128:
+ break;
case NeonTypeFlags::Float16:
return Context.HalfTy;
case NeonTypeFlags::Float32:
@@ -384,24 +405,21 @@
llvm_unreachable("Invalid NeonTypeFlag!");
}
-bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
- CallExpr *TheCall) {
-
+bool Sema::CheckNeonBuiltinFunctionCall(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
+#define GET_NEON_OVERLOAD_CHECK
#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_AARCH64_OVERLOAD_CHECK
+#undef GET_NEON_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;
+ unsigned ImmArg = TheCall->getNumArgs()-1;
if (mask) {
if (SemaBuiltinConstantArg(TheCall, ImmArg, Result))
return true;
@@ -409,7 +427,7 @@
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();
+ << TheCall->getArg(ImmArg)->getSourceRange();
}
if (PtrArgNum >= 0) {
@@ -419,7 +437,14 @@
Arg = ICE->getSubExpr();
ExprResult RHS = DefaultFunctionArrayLvalueConversion(Arg);
QualType RHSTy = RHS.get()->getType();
- QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context, true);
+
+ llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
+ bool IsPolyUnsigned =
+ Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::arm64;
+ bool IsInt64Long =
+ Context.getTargetInfo().getInt64Type() == TargetInfo::SignedLong;
+ QualType EltTy =
+ getNeonEltType(NeonTypeFlags(TV), Context, IsPolyUnsigned, IsInt64Long);
if (HasConstPtr)
EltTy = EltTy.withConst();
QualType LHSTy = Context.getPointerType(EltTy);
@@ -438,9 +463,9 @@
switch (BuiltinID) {
default:
return false;
-#define GET_NEON_AARCH64_IMMEDIATE_CHECK
+#define GET_NEON_IMMEDIATE_CHECK
#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_AARCH64_IMMEDIATE_CHECK
+#undef GET_NEON_IMMEDIATE_CHECK
}
;
@@ -462,11 +487,23 @@
return false;
}
-bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall) {
+bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
+ CallExpr *TheCall) {
+ if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
+ return true;
+
+ return false;
+}
+
+bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
+ unsigned MaxWidth) {
assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
- BuiltinID == ARM::BI__builtin_arm_strex) &&
+ BuiltinID == ARM::BI__builtin_arm_strex ||
+ BuiltinID == ARM64::BI__builtin_arm_ldrex ||
+ BuiltinID == ARM64::BI__builtin_arm_strex) &&
"unexpected ARM builtin");
- bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex;
+ bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||
+ BuiltinID == ARM64::BI__builtin_arm_ldrex;
DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
@@ -527,7 +564,8 @@
}
// But ARM doesn't have instructions to deal with 128-bit versions.
- if (Context.getTypeSize(ValType) > 64) {
+ if (Context.getTypeSize(ValType) > MaxWidth) {
+ assert(MaxWidth == 64 && "Diagnostic unexpectedly inaccurate");
Diag(DRE->getLocStart(), diag::err_atomic_exclusive_builtin_pointer_size)
<< PointerArg->getType() << PointerArg->getSourceRange();
return true;
@@ -573,53 +611,13 @@
if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
BuiltinID == ARM::BI__builtin_arm_strex) {
- return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall);
+ return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 64);
}
- uint64_t mask = 0;
- unsigned TV = 0;
- int PtrArgNum = -1;
- bool HasConstPtr = false;
- switch (BuiltinID) {
-#define GET_NEON_OVERLOAD_CHECK
-#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_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 (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
+ return true;
- 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, false);
- 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
+ // 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) {
@@ -630,9 +628,6 @@
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
};
// We can't check the value of a dependent argument.
@@ -654,6 +649,21 @@
return false;
}
+bool Sema::CheckARM64BuiltinFunctionCall(unsigned BuiltinID,
+ CallExpr *TheCall) {
+ llvm::APSInt Result;
+
+ if (BuiltinID == ARM64::BI__builtin_arm_ldrex ||
+ BuiltinID == ARM64::BI__builtin_arm_strex) {
+ return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 128);
+ }
+
+ if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
+ return true;
+
+ return false;
+}
+
bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
unsigned i = 0, l = 0, u = 0;
switch (BuiltinID) {
@@ -686,6 +696,14 @@
return false;
}
+bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+ switch (BuiltinID) {
+ case X86::BI_mm_prefetch:
+ return SemaBuiltinMMPrefetch(TheCall);
+ }
+ return false;
+}
+
/// Given a FunctionDecl's FormatAttr, attempts to populate the FomatStringInfo
/// parameter with the FormatAttr's correct format_idx and firstDataArg.
/// Returns true when the format fits the function and the FormatStringInfo has
@@ -709,14 +727,69 @@
return true;
}
+/// Checks if a the given expression evaluates to null.
+///
+/// \brief Returns true if the value evaluates to null.
+static bool CheckNonNullExpr(Sema &S,
+ const Expr *Expr) {
+ // As a special case, transparent unions initialized with zero are
+ // considered null for the purposes of the nonnull attribute.
+ if (const RecordType *UT = Expr->getType()->getAsUnionType()) {
+ if (UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ if (const CompoundLiteralExpr *CLE =
+ dyn_cast<CompoundLiteralExpr>(Expr))
+ if (const InitListExpr *ILE =
+ dyn_cast<InitListExpr>(CLE->getInitializer()))
+ Expr = ILE->getInit(0);
+ }
+
+ bool Result;
+ return (!Expr->isValueDependent() &&
+ Expr->EvaluateAsBooleanCondition(Result, S.Context) &&
+ !Result);
+}
+
+static void CheckNonNullArgument(Sema &S,
+ const Expr *ArgExpr,
+ SourceLocation CallSiteLoc) {
+ if (CheckNonNullExpr(S, ArgExpr))
+ S.Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
+}
+
+static void CheckNonNullArguments(Sema &S,
+ const NamedDecl *FDecl,
+ const Expr * const *ExprArgs,
+ SourceLocation CallSiteLoc) {
+ // Check the attributes attached to the method/function itself.
+ for (const auto *NonNull : FDecl->specific_attrs<NonNullAttr>()) {
+ for (NonNullAttr::args_iterator i = NonNull->args_begin(),
+ e = NonNull->args_end();
+ i != e; ++i) {
+ CheckNonNullArgument(S, ExprArgs[*i], CallSiteLoc);
+ }
+ }
+
+ // Check the attributes on the parameters.
+ ArrayRef<ParmVarDecl*> parms;
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FDecl))
+ parms = FD->parameters();
+ else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(FDecl))
+ parms = MD->parameters();
+
+ unsigned argIndex = 0;
+ for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
+ I != E; ++I, ++argIndex) {
+ const ParmVarDecl *PVD = *I;
+ if (PVD->hasAttr<NonNullAttr>())
+ CheckNonNullArgument(S, ExprArgs[argIndex], CallSiteLoc);
+ }
+}
+
/// Handles the checks for format strings, non-POD arguments to vararg
/// functions, and NULL arguments passed to non-NULL parameters.
-void Sema::checkCall(NamedDecl *FDecl,
- ArrayRef<const Expr *> Args,
- unsigned NumProtoArgs,
- bool IsMemberFunction,
- SourceLocation Loc,
- SourceRange Range,
+void Sema::checkCall(NamedDecl *FDecl, ArrayRef<const Expr *> Args,
+ unsigned NumParams, bool IsMemberFunction,
+ SourceLocation Loc, SourceRange Range,
VariadicCallType CallType) {
// FIXME: We should check as much as we can in the template definition.
if (CurContext->isDependentContext())
@@ -725,14 +798,11 @@
// Printf and scanf checking.
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) {
+ for (const auto *I : FDecl->specific_attrs<FormatAttr>()) {
// Only create vector if there are format attributes.
CheckedVarArgs.resize(Args.size());
- CheckFormatArguments(*I, Args, IsMemberFunction, CallType, Loc, Range,
+ CheckFormatArguments(I, Args, IsMemberFunction, CallType, Loc, Range,
CheckedVarArgs);
}
}
@@ -740,7 +810,7 @@
// Refuse POD arguments that weren't caught by the format string
// checks above.
if (CallType != VariadicDoesNotApply) {
- for (unsigned ArgIdx = NumProtoArgs; ArgIdx < Args.size(); ++ArgIdx) {
+ for (unsigned ArgIdx = NumParams; ArgIdx < Args.size(); ++ArgIdx) {
// Args[ArgIdx] can be null in malformed code.
if (const Expr *Arg = Args[ArgIdx]) {
if (CheckedVarArgs.empty() || !CheckedVarArgs[ArgIdx])
@@ -750,18 +820,11 @@
}
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);
+ CheckNonNullArguments(*this, FDecl, 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());
- }
+ for (const auto *I : FDecl->specific_attrs<ArgumentWithTypeTagAttr>())
+ CheckArgumentWithTypeTag(I, Args.data());
}
}
@@ -773,7 +836,7 @@
SourceLocation Loc) {
VariadicCallType CallType =
Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
- checkCall(FDecl, Args, Proto->getNumArgs(),
+ checkCall(FDecl, Args, Proto->getNumParams(),
/*IsMemberFunction=*/true, Loc, SourceRange(), CallType);
}
@@ -787,7 +850,7 @@
IsMemberOperatorCall;
VariadicCallType CallType = getVariadicCallType(FDecl, Proto,
TheCall->getCallee());
- unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0;
+ unsigned NumParams = Proto ? Proto->getNumParams() : 0;
Expr** Args = TheCall->getArgs();
unsigned NumArgs = TheCall->getNumArgs();
if (IsMemberOperatorCall) {
@@ -797,8 +860,7 @@
++Args;
--NumArgs;
}
- checkCall(FDecl, llvm::makeArrayRef<const Expr *>(Args, NumArgs),
- NumProtoArgs,
+ checkCall(FDecl, llvm::makeArrayRef<const Expr *>(Args, NumArgs), NumParams,
IsMemberFunction, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@@ -808,6 +870,8 @@
if (!FnInfo)
return false;
+ CheckAbsoluteValueFunction(TheCall, FDecl, FnInfo);
+
unsigned CMId = FDecl->getMemoryFunctionKind();
if (CMId == 0)
return false;
@@ -853,15 +917,13 @@
} else { // Ty->isFunctionPointerType()
CallType = VariadicFunction;
}
- unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0;
+ unsigned NumParams = Proto ? Proto->getNumParams() : 0;
- checkCall(NDecl,
- llvm::makeArrayRef<const Expr *>(TheCall->getArgs(),
- TheCall->getNumArgs()),
- NumProtoArgs, /*IsMemberFunction=*/false,
- TheCall->getRParenLoc(),
+ checkCall(NDecl, llvm::makeArrayRef<const Expr *>(TheCall->getArgs(),
+ TheCall->getNumArgs()),
+ NumParams, /*IsMemberFunction=*/false, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
-
+
return false;
}
@@ -870,18 +932,43 @@
bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) {
VariadicCallType CallType = getVariadicCallType(/*FDecl=*/0, Proto,
TheCall->getCallee());
- unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0;
+ unsigned NumParams = Proto ? Proto->getNumParams() : 0;
- checkCall(/*FDecl=*/0,
- llvm::makeArrayRef<const Expr *>(TheCall->getArgs(),
- TheCall->getNumArgs()),
- NumProtoArgs, /*IsMemberFunction=*/false,
- TheCall->getRParenLoc(),
+ checkCall(/*FDecl=*/0, llvm::makeArrayRef<const Expr *>(
+ TheCall->getArgs(), TheCall->getNumArgs()),
+ NumParams, /*IsMemberFunction=*/false, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
return false;
}
+static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) {
+ if (Ordering < AtomicExpr::AO_ABI_memory_order_relaxed ||
+ Ordering > AtomicExpr::AO_ABI_memory_order_seq_cst)
+ return false;
+
+ switch (Op) {
+ case AtomicExpr::AO__c11_atomic_init:
+ llvm_unreachable("There is no ordering argument for an init");
+
+ case AtomicExpr::AO__c11_atomic_load:
+ case AtomicExpr::AO__atomic_load_n:
+ case AtomicExpr::AO__atomic_load:
+ return Ordering != AtomicExpr::AO_ABI_memory_order_release &&
+ Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel;
+
+ case AtomicExpr::AO__c11_atomic_store:
+ case AtomicExpr::AO__atomic_store:
+ case AtomicExpr::AO__atomic_store_n:
+ return Ordering != AtomicExpr::AO_ABI_memory_order_consume &&
+ Ordering != AtomicExpr::AO_ABI_memory_order_acquire &&
+ Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel;
+
+ default:
+ return true;
+ }
+}
+
ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
AtomicExpr::AtomicOp Op) {
CallExpr *TheCall = cast<CallExpr>(TheCallResult.get());
@@ -1170,7 +1257,16 @@
SubExprs.push_back(TheCall->getArg(3)); // Weak
break;
}
-
+
+ if (SubExprs.size() >= 2 && Form != Init) {
+ llvm::APSInt Result(32);
+ if (SubExprs[1]->isIntegerConstantExpr(Result, Context) &&
+ !isValidOrderingForOp(Result.getSExtValue(), Op))
+ Diag(SubExprs[1]->getLocStart(),
+ diag::warn_atomic_op_has_invalid_memory_order)
+ << SubExprs[1]->getSourceRange();
+ }
+
AtomicExpr *AE = new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(),
SubExprs, ResultType, Op,
TheCall->getRParenLoc());
@@ -1901,6 +1997,26 @@
return false;
}
+/// SemaBuiltinMMPrefetch - Handle _mm_prefetch.
+// This is declared to take (const char*, int)
+bool Sema::SemaBuiltinMMPrefetch(CallExpr *TheCall) {
+ Expr *Arg = TheCall->getArg(1);
+
+ // We can't check the value of a dependent argument.
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ return false;
+
+ llvm::APSInt Result;
+ if (SemaBuiltinConstantArg(TheCall, 1, Result))
+ return true;
+
+ if (Result.getLimitedValue() > 3)
+ return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+ << "0" << "3" << Arg->getSourceRange();
+
+ return false;
+}
+
/// SemaBuiltinConstantArg - Handle a check if argument ArgNum of CallExpr
/// TheCall is a constant expression.
bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
@@ -2081,10 +2197,7 @@
if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(VD)) {
if (const NamedDecl *ND = dyn_cast<NamedDecl>(PV->getDeclContext())) {
int PVIndex = PV->getFunctionScopeIndex() + 1;
- for (specific_attr_iterator<FormatAttr>
- i = ND->specific_attr_begin<FormatAttr>(),
- e = ND->specific_attr_end<FormatAttr>(); i != e ; ++i) {
- FormatAttr *PVFormat = *i;
+ for (const auto *PVFormat : ND->specific_attrs<FormatAttr>()) {
// adjust for implicit parameter
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
if (MD->isInstance())
@@ -2133,27 +2246,6 @@
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;
@@ -2177,32 +2269,6 @@
}
}
-void
-Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
- const Expr * const *ExprArgs,
- SourceLocation CallSiteLoc) {
- for (NonNullAttr::args_iterator i = NonNull->args_begin(),
- e = NonNull->args_end();
- i != e; ++i) {
- const Expr *ArgExpr = ExprArgs[*i];
-
- // As a special case, transparent unions initialized with zero are
- // considered null for the purposes of the nonnull attribute.
- if (const RecordType *UT = ArgExpr->getType()->getAsUnionType()) {
- if (UT->getDecl()->hasAttr<TransparentUnionAttr>())
- if (const CompoundLiteralExpr *CLE =
- dyn_cast<CompoundLiteralExpr>(ArgExpr))
- if (const InitListExpr *ILE =
- dyn_cast<InitListExpr>(CLE->getInitializer()))
- ArgExpr = ILE->getInit(0);
- }
-
- bool Result;
- if (ArgExpr->EvaluateAsBooleanCondition(Result, Context) && !Result)
- Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
- }
-}
-
Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
return llvm::StringSwitch<FormatStringType>(Format->getType()->getName())
.Case("scanf", FST_Scanf)
@@ -2331,30 +2397,31 @@
void DoneProcessing();
void HandleIncompleteSpecifier(const char *startSpecifier,
- unsigned specifierLen);
+ unsigned specifierLen) override;
void HandleInvalidLengthModifier(
- const analyze_format_string::FormatSpecifier &FS,
- const analyze_format_string::ConversionSpecifier &CS,
- const char *startSpecifier, unsigned specifierLen, unsigned DiagID);
+ const analyze_format_string::FormatSpecifier &FS,
+ const analyze_format_string::ConversionSpecifier &CS,
+ const char *startSpecifier, unsigned specifierLen,
+ unsigned DiagID);
void HandleNonStandardLengthModifier(
- const analyze_format_string::FormatSpecifier &FS,
- const char *startSpecifier, unsigned specifierLen);
+ const analyze_format_string::FormatSpecifier &FS,
+ const char *startSpecifier, unsigned specifierLen);
void HandleNonStandardConversionSpecifier(
- const analyze_format_string::ConversionSpecifier &CS,
- const char *startSpecifier, unsigned specifierLen);
+ const analyze_format_string::ConversionSpecifier &CS,
+ const char *startSpecifier, unsigned specifierLen);
- virtual void HandlePosition(const char *startPos, unsigned posLen);
+ void HandlePosition(const char *startPos, unsigned posLen) override;
- virtual void HandleInvalidPosition(const char *startSpecifier,
- unsigned specifierLen,
- analyze_format_string::PositionContext p);
+ void HandleInvalidPosition(const char *startSpecifier,
+ unsigned specifierLen,
+ analyze_format_string::PositionContext p) override;
- virtual void HandleZeroPosition(const char *startPos, unsigned posLen);
+ void HandleZeroPosition(const char *startPos, unsigned posLen) override;
- void HandleNullChar(const char *nullCharacter);
+ void HandleNullChar(const char *nullCharacter) override;
template <typename Range>
static void EmitFormatDiagnostic(Sema &S, bool inFunctionCall,
@@ -2390,9 +2457,6 @@
void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc,
bool IsStringLocation, Range StringRange,
ArrayRef<FixItHint> Fixit = None);
-
- void CheckPositionalAndNonpositionalArgs(
- const analyze_format_string::FormatSpecifier *FS);
};
}
@@ -2723,15 +2787,15 @@
ObjCContext(isObjC)
{}
-
+
bool HandleInvalidPrintfConversionSpecifier(
const analyze_printf::PrintfSpecifier &FS,
const char *startSpecifier,
- unsigned specifierLen);
-
+ unsigned specifierLen) override;
+
bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
const char *startSpecifier,
- unsigned specifierLen);
+ unsigned specifierLen) override;
bool checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
const char *StartSpecifier,
unsigned SpecifierLen,
@@ -2751,7 +2815,7 @@
const analyze_printf::OptionalFlag &flag,
const char *startSpecifier, unsigned specifierLen);
bool checkForCStrMembers(const analyze_printf::ArgType &AT,
- const Expr *E, const CharSourceRange &CSR);
+ const Expr *E);
};
}
@@ -2885,11 +2949,12 @@
if (!RT)
return Results;
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD)
+ if (!RD || !RD->getDefinition())
return Results;
LookupResult R(S, &S.PP.getIdentifierTable().get(Name), SourceLocation(),
Sema::LookupMemberName);
+ R.suppressDiagnostics();
// We just need to include all members of the right kind turned up by the
// filter, at this point.
@@ -2902,12 +2967,26 @@
return Results;
}
+/// Check if we could call '.c_str()' on an object.
+///
+/// FIXME: This returns the wrong results in some cases (if cv-qualifiers don't
+/// allow the call, or if it would be ambiguous).
+bool Sema::hasCStrMethod(const Expr *E) {
+ typedef llvm::SmallPtrSet<CXXMethodDecl*, 1> MethodSet;
+ MethodSet Results =
+ CXXRecordMembersNamed<CXXMethodDecl>("c_str", *this, E->getType());
+ for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
+ MI != ME; ++MI)
+ if ((*MI)->getMinRequiredArguments() == 0)
+ return true;
+ return false;
+}
+
// Check if a (w)string was passed when a (w)char* was needed, and offer a
// better diagnostic if so. AT is assumed to be valid.
// Returns true when a c_str() conversion method is found.
bool CheckPrintfHandler::checkForCStrMembers(
- const analyze_printf::ArgType &AT, const Expr *E,
- const CharSourceRange &CSR) {
+ const analyze_printf::ArgType &AT, const Expr *E) {
typedef llvm::SmallPtrSet<CXXMethodDecl*, 1> MethodSet;
MethodSet Results =
@@ -2916,8 +2995,8 @@
for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
MI != ME; ++MI) {
const CXXMethodDecl *Method = *MI;
- if (Method->getNumParams() == 0 &&
- AT.matchesType(S.Context, Method->getResultType())) {
+ if (Method->getMinRequiredArguments() == 0 &&
+ AT.matchesType(S.Context, Method->getReturnType())) {
// FIXME: Suggest parens if the expression needs them.
SourceLocation EndLoc =
S.getPreprocessor().getLocForEndOfToken(E->getLocEnd());
@@ -3303,7 +3382,7 @@
<< CSR
<< E->getSourceRange(),
E->getLocStart(), /*IsStringLocation*/false, CSR);
- checkForCStrMembers(AT, E, CSR);
+ checkForCStrMembers(AT, E);
break;
case Sema::VAK_Invalid:
@@ -3355,14 +3434,14 @@
bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
- unsigned specifierLen);
+ unsigned specifierLen) override;
bool HandleInvalidScanfConversionSpecifier(
const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
- unsigned specifierLen);
+ unsigned specifierLen) override;
- void HandleIncompleteScanList(const char *start, const char *end);
+ void HandleIncompleteScanList(const char *start, const char *end) override;
};
}
@@ -3467,8 +3546,9 @@
const analyze_format_string::ArgType &AT = FS.getArgType(S.Context);
if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType())) {
ScanfSpecifier fixedFS = FS;
- bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(),
- S.Context);
+ bool success = fixedFS.fixType(Ex->getType(),
+ Ex->IgnoreImpCasts()->getType(),
+ S.getLangOpts(), S.Context);
if (success) {
// Get the fix string from the fixed format specifier.
@@ -3520,9 +3600,25 @@
// Str - The format string. NOTE: this is NOT null-terminated!
StringRef StrRef = FExpr->getString();
const char *Str = StrRef.data();
- unsigned StrLen = StrRef.size();
+ // Account for cases where the string literal is truncated in a declaration.
+ const ConstantArrayType *T = Context.getAsConstantArrayType(FExpr->getType());
+ assert(T && "String literal not of constant array type!");
+ size_t TypeSize = T->getSize().getZExtValue();
+ size_t StrLen = std::min(std::max(TypeSize, size_t(1)) - 1, StrRef.size());
const unsigned numDataArgs = Args.size() - firstDataArg;
-
+
+ // Emit a warning if the string literal is truncated and does not contain an
+ // embedded null character.
+ if (TypeSize <= StrRef.size() &&
+ StrRef.substr(0, TypeSize).find('\0') == StringRef::npos) {
+ CheckFormatHandler::EmitFormatDiagnostic(
+ *this, inFunctionCall, Args[format_idx],
+ PDiag(diag::warn_printf_format_string_not_null_terminated),
+ FExpr->getLocStart(),
+ /*IsStringLocation=*/true, OrigFormatExpr->getSourceRange());
+ return;
+ }
+
// CHECK: empty format string?
if (StrLen == 0 && numDataArgs > 0) {
CheckFormatHandler::EmitFormatDiagnostic(
@@ -3554,8 +3650,365 @@
} // TODO: handle other formats
}
+//===--- CHECK: Warn on use of wrong absolute value function. -------------===//
+
+// Returns the related absolute value function that is larger, of 0 if one
+// does not exist.
+static unsigned getLargerAbsoluteValueFunction(unsigned AbsFunction) {
+ switch (AbsFunction) {
+ default:
+ return 0;
+
+ case Builtin::BI__builtin_abs:
+ return Builtin::BI__builtin_labs;
+ case Builtin::BI__builtin_labs:
+ return Builtin::BI__builtin_llabs;
+ case Builtin::BI__builtin_llabs:
+ return 0;
+
+ case Builtin::BI__builtin_fabsf:
+ return Builtin::BI__builtin_fabs;
+ case Builtin::BI__builtin_fabs:
+ return Builtin::BI__builtin_fabsl;
+ case Builtin::BI__builtin_fabsl:
+ return 0;
+
+ case Builtin::BI__builtin_cabsf:
+ return Builtin::BI__builtin_cabs;
+ case Builtin::BI__builtin_cabs:
+ return Builtin::BI__builtin_cabsl;
+ case Builtin::BI__builtin_cabsl:
+ return 0;
+
+ case Builtin::BIabs:
+ return Builtin::BIlabs;
+ case Builtin::BIlabs:
+ return Builtin::BIllabs;
+ case Builtin::BIllabs:
+ return 0;
+
+ case Builtin::BIfabsf:
+ return Builtin::BIfabs;
+ case Builtin::BIfabs:
+ return Builtin::BIfabsl;
+ case Builtin::BIfabsl:
+ return 0;
+
+ case Builtin::BIcabsf:
+ return Builtin::BIcabs;
+ case Builtin::BIcabs:
+ return Builtin::BIcabsl;
+ case Builtin::BIcabsl:
+ return 0;
+ }
+}
+
+// Returns the argument type of the absolute value function.
+static QualType getAbsoluteValueArgumentType(ASTContext &Context,
+ unsigned AbsType) {
+ if (AbsType == 0)
+ return QualType();
+
+ ASTContext::GetBuiltinTypeError Error = ASTContext::GE_None;
+ QualType BuiltinType = Context.GetBuiltinType(AbsType, Error);
+ if (Error != ASTContext::GE_None)
+ return QualType();
+
+ const FunctionProtoType *FT = BuiltinType->getAs<FunctionProtoType>();
+ if (!FT)
+ return QualType();
+
+ if (FT->getNumParams() != 1)
+ return QualType();
+
+ return FT->getParamType(0);
+}
+
+// Returns the best absolute value function, or zero, based on type and
+// current absolute value function.
+static unsigned getBestAbsFunction(ASTContext &Context, QualType ArgType,
+ unsigned AbsFunctionKind) {
+ unsigned BestKind = 0;
+ uint64_t ArgSize = Context.getTypeSize(ArgType);
+ for (unsigned Kind = AbsFunctionKind; Kind != 0;
+ Kind = getLargerAbsoluteValueFunction(Kind)) {
+ QualType ParamType = getAbsoluteValueArgumentType(Context, Kind);
+ if (Context.getTypeSize(ParamType) >= ArgSize) {
+ if (BestKind == 0)
+ BestKind = Kind;
+ else if (Context.hasSameType(ParamType, ArgType)) {
+ BestKind = Kind;
+ break;
+ }
+ }
+ }
+ return BestKind;
+}
+
+enum AbsoluteValueKind {
+ AVK_Integer,
+ AVK_Floating,
+ AVK_Complex
+};
+
+static AbsoluteValueKind getAbsoluteValueKind(QualType T) {
+ if (T->isIntegralOrEnumerationType())
+ return AVK_Integer;
+ if (T->isRealFloatingType())
+ return AVK_Floating;
+ if (T->isAnyComplexType())
+ return AVK_Complex;
+
+ llvm_unreachable("Type not integer, floating, or complex");
+}
+
+// Changes the absolute value function to a different type. Preserves whether
+// the function is a builtin.
+static unsigned changeAbsFunction(unsigned AbsKind,
+ AbsoluteValueKind ValueKind) {
+ switch (ValueKind) {
+ case AVK_Integer:
+ switch (AbsKind) {
+ default:
+ return 0;
+ case Builtin::BI__builtin_fabsf:
+ case Builtin::BI__builtin_fabs:
+ case Builtin::BI__builtin_fabsl:
+ case Builtin::BI__builtin_cabsf:
+ case Builtin::BI__builtin_cabs:
+ case Builtin::BI__builtin_cabsl:
+ return Builtin::BI__builtin_abs;
+ case Builtin::BIfabsf:
+ case Builtin::BIfabs:
+ case Builtin::BIfabsl:
+ case Builtin::BIcabsf:
+ case Builtin::BIcabs:
+ case Builtin::BIcabsl:
+ return Builtin::BIabs;
+ }
+ case AVK_Floating:
+ switch (AbsKind) {
+ default:
+ return 0;
+ case Builtin::BI__builtin_abs:
+ case Builtin::BI__builtin_labs:
+ case Builtin::BI__builtin_llabs:
+ case Builtin::BI__builtin_cabsf:
+ case Builtin::BI__builtin_cabs:
+ case Builtin::BI__builtin_cabsl:
+ return Builtin::BI__builtin_fabsf;
+ case Builtin::BIabs:
+ case Builtin::BIlabs:
+ case Builtin::BIllabs:
+ case Builtin::BIcabsf:
+ case Builtin::BIcabs:
+ case Builtin::BIcabsl:
+ return Builtin::BIfabsf;
+ }
+ case AVK_Complex:
+ switch (AbsKind) {
+ default:
+ return 0;
+ case Builtin::BI__builtin_abs:
+ case Builtin::BI__builtin_labs:
+ case Builtin::BI__builtin_llabs:
+ case Builtin::BI__builtin_fabsf:
+ case Builtin::BI__builtin_fabs:
+ case Builtin::BI__builtin_fabsl:
+ return Builtin::BI__builtin_cabsf;
+ case Builtin::BIabs:
+ case Builtin::BIlabs:
+ case Builtin::BIllabs:
+ case Builtin::BIfabsf:
+ case Builtin::BIfabs:
+ case Builtin::BIfabsl:
+ return Builtin::BIcabsf;
+ }
+ }
+ llvm_unreachable("Unable to convert function");
+}
+
+static unsigned getAbsoluteValueFunctionKind(const FunctionDecl *FDecl) {
+ const IdentifierInfo *FnInfo = FDecl->getIdentifier();
+ if (!FnInfo)
+ return 0;
+
+ switch (FDecl->getBuiltinID()) {
+ default:
+ return 0;
+ case Builtin::BI__builtin_abs:
+ case Builtin::BI__builtin_fabs:
+ case Builtin::BI__builtin_fabsf:
+ case Builtin::BI__builtin_fabsl:
+ case Builtin::BI__builtin_labs:
+ case Builtin::BI__builtin_llabs:
+ case Builtin::BI__builtin_cabs:
+ case Builtin::BI__builtin_cabsf:
+ case Builtin::BI__builtin_cabsl:
+ case Builtin::BIabs:
+ case Builtin::BIlabs:
+ case Builtin::BIllabs:
+ case Builtin::BIfabs:
+ case Builtin::BIfabsf:
+ case Builtin::BIfabsl:
+ case Builtin::BIcabs:
+ case Builtin::BIcabsf:
+ case Builtin::BIcabsl:
+ return FDecl->getBuiltinID();
+ }
+ llvm_unreachable("Unknown Builtin type");
+}
+
+// If the replacement is valid, emit a note with replacement function.
+// Additionally, suggest including the proper header if not already included.
+static void emitReplacement(Sema &S, SourceLocation Loc, SourceRange Range,
+ unsigned AbsKind) {
+ std::string AbsName = S.Context.BuiltinInfo.GetName(AbsKind);
+
+ // Look up absolute value function in TU scope.
+ DeclarationName DN(&S.Context.Idents.get(AbsName));
+ LookupResult R(S, DN, Loc, Sema::LookupAnyName);
+ R.suppressDiagnostics();
+ S.LookupName(R, S.TUScope);
+
+ // Skip notes if multiple results found in lookup.
+ if (!R.empty() && !R.isSingleResult())
+ return;
+
+ FunctionDecl *FD = 0;
+ bool FoundFunction = R.isSingleResult();
+ // When one result is found, see if it is the correct function.
+ if (R.isSingleResult()) {
+ FD = dyn_cast<FunctionDecl>(R.getFoundDecl());
+ if (!FD || FD->getBuiltinID() != AbsKind)
+ return;
+ }
+
+ // Look for local name conflict, prepend "::" as necessary.
+ R.clear();
+ S.LookupName(R, S.getCurScope());
+
+ if (!FoundFunction) {
+ if (!R.empty()) {
+ AbsName = "::" + AbsName;
+ }
+ } else { // FoundFunction
+ if (R.isSingleResult()) {
+ if (R.getFoundDecl() != FD) {
+ AbsName = "::" + AbsName;
+ }
+ } else if (!R.empty()) {
+ AbsName = "::" + AbsName;
+ }
+ }
+
+ S.Diag(Loc, diag::note_replace_abs_function)
+ << AbsName << FixItHint::CreateReplacement(Range, AbsName);
+
+ if (!FoundFunction) {
+ S.Diag(Loc, diag::note_please_include_header)
+ << S.Context.BuiltinInfo.getHeaderName(AbsKind)
+ << S.Context.BuiltinInfo.GetName(AbsKind);
+ }
+}
+
+// Warn when using the wrong abs() function.
+void Sema::CheckAbsoluteValueFunction(const CallExpr *Call,
+ const FunctionDecl *FDecl,
+ IdentifierInfo *FnInfo) {
+ if (Call->getNumArgs() != 1)
+ return;
+
+ unsigned AbsKind = getAbsoluteValueFunctionKind(FDecl);
+ if (AbsKind == 0)
+ return;
+
+ QualType ArgType = Call->getArg(0)->IgnoreParenImpCasts()->getType();
+ QualType ParamType = Call->getArg(0)->getType();
+
+ // Unsigned types can not be negative. Suggest to drop the absolute value
+ // function.
+ if (ArgType->isUnsignedIntegerType()) {
+ Diag(Call->getExprLoc(), diag::warn_unsigned_abs) << ArgType << ParamType;
+ Diag(Call->getExprLoc(), diag::note_remove_abs)
+ << FDecl
+ << FixItHint::CreateRemoval(Call->getCallee()->getSourceRange());
+ return;
+ }
+
+ AbsoluteValueKind ArgValueKind = getAbsoluteValueKind(ArgType);
+ AbsoluteValueKind ParamValueKind = getAbsoluteValueKind(ParamType);
+
+ // The argument and parameter are the same kind. Check if they are the right
+ // size.
+ if (ArgValueKind == ParamValueKind) {
+ if (Context.getTypeSize(ArgType) <= Context.getTypeSize(ParamType))
+ return;
+
+ unsigned NewAbsKind = getBestAbsFunction(Context, ArgType, AbsKind);
+ Diag(Call->getExprLoc(), diag::warn_abs_too_small)
+ << FDecl << ArgType << ParamType;
+
+ if (NewAbsKind == 0)
+ return;
+
+ emitReplacement(*this, Call->getExprLoc(),
+ Call->getCallee()->getSourceRange(), NewAbsKind);
+ return;
+ }
+
+ // ArgValueKind != ParamValueKind
+ // The wrong type of absolute value function was used. Attempt to find the
+ // proper one.
+ unsigned NewAbsKind = changeAbsFunction(AbsKind, ArgValueKind);
+ NewAbsKind = getBestAbsFunction(Context, ArgType, NewAbsKind);
+ if (NewAbsKind == 0)
+ return;
+
+ Diag(Call->getExprLoc(), diag::warn_wrong_absolute_value_type)
+ << FDecl << ParamValueKind << ArgValueKind;
+
+ emitReplacement(*this, Call->getExprLoc(),
+ Call->getCallee()->getSourceRange(), NewAbsKind);
+ return;
+}
+
//===--- CHECK: Standard memory functions ---------------------------------===//
+/// \brief Takes the expression passed to the size_t parameter of functions
+/// such as memcmp, strncat, etc and warns if it's a comparison.
+///
+/// This is to catch typos like `if (memcmp(&a, &b, sizeof(a) > 0))`.
+static bool CheckMemorySizeofForComparison(Sema &S, const Expr *E,
+ IdentifierInfo *FnName,
+ SourceLocation FnLoc,
+ SourceLocation RParenLoc) {
+ const BinaryOperator *Size = dyn_cast<BinaryOperator>(E);
+ if (!Size)
+ return false;
+
+ // if E is binop and op is >, <, >=, <=, ==, &&, ||:
+ if (!Size->isComparisonOp() && !Size->isEqualityOp() && !Size->isLogicalOp())
+ return false;
+
+ Preprocessor &PP = S.getPreprocessor();
+ SourceRange SizeRange = Size->getSourceRange();
+ S.Diag(Size->getOperatorLoc(), diag::warn_memsize_comparison)
+ << SizeRange << FnName;
+ S.Diag(FnLoc, diag::warn_memsize_comparison_paren_note)
+ << FnName
+ << FixItHint::CreateInsertion(
+ PP.getLocForEndOfToken(Size->getLHS()->getLocEnd()),
+ ")")
+ << FixItHint::CreateRemoval(RParenLoc);
+ S.Diag(SizeRange.getBegin(), diag::warn_memsize_comparison_cast_note)
+ << FixItHint::CreateInsertion(SizeRange.getBegin(), "(size_t)(")
+ << FixItHint::CreateInsertion(
+ PP.getLocForEndOfToken(SizeRange.getEnd()), ")");
+
+ return true;
+}
+
/// \brief Determine whether the given type is a dynamic class type (e.g.,
/// whether it has a vtable).
static bool isDynamicClassType(QualType T) {
@@ -3611,6 +4064,10 @@
unsigned LenArg = (BId == Builtin::BIstrndup ? 1 : 2);
const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts();
+ if (CheckMemorySizeofForComparison(*this, LenExpr, FnName,
+ Call->getLocStart(), Call->getRParenLoc()))
+ return;
+
// We have special checking when the length is a sizeof expression.
QualType SizeOfArgTy = getSizeOfArgType(LenExpr);
const Expr *SizeOfArg = getSizeOfExprArg(LenExpr);
@@ -3794,6 +4251,10 @@
const Expr *SrcArg = ignoreLiteralAdditions(Call->getArg(1), Context);
const Expr *SizeArg = ignoreLiteralAdditions(Call->getArg(2), Context);
const Expr *CompareWithSrc = NULL;
+
+ if (CheckMemorySizeofForComparison(*this, SizeArg, FnName,
+ Call->getLocStart(), Call->getRParenLoc()))
+ return;
// Look for 'strlcpy(dst, x, sizeof(x))'
if (const Expr *Ex = getSizeOfExprArg(SizeArg))
@@ -3801,8 +4262,8 @@
else {
// Look for 'strlcpy(dst, x, strlen(x))'
if (const CallExpr *SizeCall = dyn_cast<CallExpr>(SizeArg)) {
- if (SizeCall->isBuiltinCall() == Builtin::BIstrlen
- && SizeCall->getNumArgs() == 1)
+ if (SizeCall->getBuiltinCallee() == Builtin::BIstrlen &&
+ SizeCall->getNumArgs() == 1)
CompareWithSrc = ignoreLiteralAdditions(SizeCall->getArg(0), Context);
}
}
@@ -3876,6 +4337,10 @@
const Expr *SrcArg = CE->getArg(1)->IgnoreParenCasts();
const Expr *LenArg = CE->getArg(2)->IgnoreParenCasts();
+ if (CheckMemorySizeofForComparison(*this, LenArg, FnName, CE->getLocStart(),
+ CE->getRParenLoc()))
+ return;
+
// Identify common expressions, which are wrongly used as the size argument
// to strncat and may lead to buffer overflows.
unsigned PatternType = 0;
@@ -3954,9 +4419,9 @@
/// CheckReturnStackAddr - Check if a return statement returns the address
/// of a stack variable.
-void
-Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
- SourceLocation ReturnLoc) {
+static void
+CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
+ SourceLocation ReturnLoc) {
Expr *stackE = 0;
SmallVector<DeclRefExpr *, 8> refVars;
@@ -3964,7 +4429,7 @@
// Perform checking for returned stack addresses, local blocks,
// label addresses or references to temporaries.
if (lhsType->isPointerType() ||
- (!getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) {
+ (!S.getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) {
stackE = EvalAddr(RetValExp, refVars, /*ParentDecl=*/0);
} else if (lhsType->isReferenceType()) {
stackE = EvalVal(RetValExp, refVars, /*ParentDecl=*/0);
@@ -3988,16 +4453,16 @@
}
if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var.
- Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref
+ S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref
: diag::warn_ret_stack_addr)
<< DR->getDecl()->getDeclName() << diagRange;
} else if (isa<BlockExpr>(stackE)) { // local block.
- Diag(diagLoc, diag::err_ret_local_block) << diagRange;
+ S.Diag(diagLoc, diag::err_ret_local_block) << diagRange;
} else if (isa<AddrLabelExpr>(stackE)) { // address of label.
- Diag(diagLoc, diag::warn_ret_addr_label) << diagRange;
+ S.Diag(diagLoc, diag::warn_ret_addr_label) << diagRange;
} else { // local temporary.
- Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref
- : diag::warn_ret_local_temp_addr)
+ S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref
+ : diag::warn_ret_local_temp_addr)
<< diagRange;
}
@@ -4010,8 +4475,8 @@
// show the range of the expression.
SourceRange range = (i < e-1) ? refVars[i+1]->getSourceRange()
: stackE->getSourceRange();
- Diag(VD->getLocation(), diag::note_ref_var_local_bind)
- << VD->getDeclName() << range;
+ S.Diag(VD->getLocation(), diag::note_ref_var_local_bind)
+ << VD->getDeclName() << range;
}
}
@@ -4061,6 +4526,10 @@
case Stmt::DeclRefExprClass: {
DeclRefExpr *DR = cast<DeclRefExpr>(E);
+ // If we leave the immediate function, the lifetime isn't about to end.
+ if (DR->refersToEnclosingLocal())
+ return 0;
+
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
// If this is a reference variable, follow through to the expression that
// it points to.
@@ -4110,20 +4579,21 @@
ConditionalOperator *C = cast<ConditionalOperator>(E);
// Handle the GNU extension for missing LHS.
- if (Expr *lhsExpr = C->getLHS()) {
- // In C++, we can have a throw-expression, which has 'void' type.
- if (!lhsExpr->getType()->isVoidType())
- if (Expr* LHS = EvalAddr(lhsExpr, refVars, ParentDecl))
+ // FIXME: That isn't a ConditionalOperator, so doesn't get here.
+ if (Expr *LHSExpr = C->getLHS()) {
+ // In C++, we can have a throw-expression, which has 'void' type.
+ if (!LHSExpr->getType()->isVoidType())
+ if (Expr *LHS = EvalAddr(LHSExpr, refVars, ParentDecl))
return LHS;
}
// In C++, we can have a throw-expression, which has 'void' type.
if (C->getRHS()->getType()->isVoidType())
- return NULL;
+ return 0;
return EvalAddr(C->getRHS(), refVars, ParentDecl);
}
-
+
case Stmt::BlockExprClass:
if (cast<BlockExpr>(E)->getBlockDecl()->hasCaptures())
return E; // local block.
@@ -4216,6 +4686,10 @@
// local storage within the function, and if so, return the expression.
DeclRefExpr *DR = cast<DeclRefExpr>(E);
+ // If we leave the immediate function, the lifetime isn't about to end.
+ if (DR->refersToEnclosingLocal())
+ return 0;
+
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) {
// Check if it refers to itself, e.g. "int& i = i;".
if (V == ParentDecl)
@@ -4263,9 +4737,16 @@
ConditionalOperator *C = cast<ConditionalOperator>(E);
// Handle the GNU extension for missing LHS.
- if (Expr *lhsExpr = C->getLHS())
- if (Expr *LHS = EvalVal(lhsExpr, refVars, ParentDecl))
- return LHS;
+ if (Expr *LHSExpr = C->getLHS()) {
+ // In C++, we can have a throw-expression, which has 'void' type.
+ if (!LHSExpr->getType()->isVoidType())
+ if (Expr *LHS = EvalVal(LHSExpr, refVars, ParentDecl))
+ return LHS;
+ }
+
+ // In C++, we can have a throw-expression, which has 'void' type.
+ if (C->getRHS()->getType()->isVoidType())
+ return 0;
return EvalVal(C->getRHS(), refVars, ParentDecl);
}
@@ -4306,6 +4787,38 @@
} while (true);
}
+void
+Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
+ SourceLocation ReturnLoc,
+ bool isObjCMethod,
+ const AttrVec *Attrs,
+ const FunctionDecl *FD) {
+ CheckReturnStackAddr(*this, RetValExp, lhsType, ReturnLoc);
+
+ // Check if the return value is null but should not be.
+ if (Attrs && hasSpecificAttr<ReturnsNonNullAttr>(*Attrs) &&
+ CheckNonNullExpr(*this, RetValExp))
+ Diag(ReturnLoc, diag::warn_null_ret)
+ << (isObjCMethod ? 1 : 0) << RetValExp->getSourceRange();
+
+ // C++11 [basic.stc.dynamic.allocation]p4:
+ // If an allocation function declared with a non-throwing
+ // exception-specification fails to allocate storage, it shall return
+ // a null pointer. Any other allocation function that fails to allocate
+ // storage shall indicate failure only by throwing an exception [...]
+ if (FD) {
+ OverloadedOperatorKind Op = FD->getOverloadedOperator();
+ if (Op == OO_New || Op == OO_Array_New) {
+ const FunctionProtoType *Proto
+ = FD->getType()->castAs<FunctionProtoType>();
+ if (!Proto->isNothrow(Context, /*ResultIfDependent*/true) &&
+ CheckNonNullExpr(*this, RetValExp))
+ Diag(ReturnLoc, diag::warn_operator_new_returns_null)
+ << FD << getLangOpts().CPlusPlus11;
+ }
+ }
+}
+
//===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===//
/// Check for comparisons of floating point operands using != and ==.
@@ -4338,11 +4851,11 @@
// Check for comparisons with builtin types.
if (CallExpr* CL = dyn_cast<CallExpr>(LeftExprSansParen))
- if (CL->isBuiltinCall())
+ if (CL->getBuiltinCallee())
return;
if (CallExpr* CR = dyn_cast<CallExpr>(RightExprSansParen))
- if (CR->isBuiltinCall())
+ if (CR->getBuiltinCallee())
return;
// Emit the diagnostic.
@@ -4920,9 +5433,11 @@
else
OS << Value;
- S.Diag(E->getOperatorLoc(), diag::warn_out_of_range_compare)
- << OS.str() << OtherT << IsTrue
- << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ S.DiagRuntimeBehavior(E->getOperatorLoc(), E,
+ S.PDiag(diag::warn_out_of_range_compare)
+ << OS.str() << OtherT << IsTrue
+ << E->getLHS()->getSourceRange()
+ << E->getRHS()->getSourceRange());
}
/// Analyze the operands of the given comparison. Implements the
@@ -5231,39 +5746,21 @@
if (Target->isSpecificBuiltinType(BuiltinType::Bool)) {
if (isa<StringLiteral>(E))
// Warn on string literal to bool. Checks for string literals in logical
- // expressions, for instances, assert(0 && "error here"), is prevented
- // by a check in AnalyzeImplicitConversions().
+ // and expressions, for instance, assert(0 && "error here"), are
+ // prevented by a check in AnalyzeImplicitConversions().
return DiagnoseImpCast(S, E, T, CC,
diag::warn_impcast_string_literal_to_bool);
- if (Source->isFunctionType()) {
- // Warn on function to bool. Checks free functions and static member
- // functions. Weakly imported functions are excluded from the check,
- // since it's common to test their value to check whether the linker
- // found a definition for them.
- ValueDecl *D = 0;
- if (DeclRefExpr* R = dyn_cast<DeclRefExpr>(E)) {
- D = R->getDecl();
- } else if (MemberExpr *M = dyn_cast<MemberExpr>(E)) {
- D = M->getMemberDecl();
- }
-
- if (D && !D->isWeak()) {
- if (FunctionDecl* F = dyn_cast<FunctionDecl>(D)) {
- S.Diag(E->getExprLoc(), diag::warn_impcast_function_to_bool)
- << F << E->getSourceRange() << SourceRange(CC);
- S.Diag(E->getExprLoc(), diag::note_function_to_bool_silence)
- << FixItHint::CreateInsertion(E->getExprLoc(), "&");
- QualType ReturnType;
- UnresolvedSet<4> NonTemplateOverloads;
- S.tryExprAsCall(*E, ReturnType, NonTemplateOverloads);
- if (!ReturnType.isNull()
- && ReturnType->isSpecificBuiltinType(BuiltinType::Bool))
- S.Diag(E->getExprLoc(), diag::note_function_to_bool_call)
- << FixItHint::CreateInsertion(
- S.getPreprocessor().getLocForEndOfToken(E->getLocEnd()), "()");
- return;
- }
- }
+ if (isa<ObjCStringLiteral>(E) || isa<ObjCArrayLiteral>(E) ||
+ isa<ObjCDictionaryLiteral>(E) || isa<ObjCBoxedExpr>(E)) {
+ // This covers the literal expressions that evaluate to Objective-C
+ // objects.
+ return DiagnoseImpCast(S, E, T, CC,
+ diag::warn_impcast_objective_c_literal_to_bool);
+ }
+ if (Source->isPointerType() || Source->canDecayToPointerType()) {
+ // Warn on pointer to bool conversion that is always true.
+ S.DiagnoseAlwaysNonNullPointer(E, Expr::NPCK_NotNull, /*IsEqual*/ false,
+ SourceRange(CC));
}
}
@@ -5283,6 +5780,8 @@
Source = cast<VectorType>(Source)->getElementType().getTypePtr();
Target = cast<VectorType>(Target)->getElementType().getTypePtr();
}
+ if (auto VecTy = dyn_cast<VectorType>(Target))
+ Target = VecTy->getElementType().getTypePtr();
// Strip complex types.
if (isa<ComplexType>(Source)) {
@@ -5583,15 +6082,16 @@
// Now just recurse over the expression's children.
CC = E->getExprLoc();
BinaryOperator *BO = dyn_cast<BinaryOperator>(E);
- bool IsLogicalOperator = BO && BO->isLogicalOp();
+ bool IsLogicalAndOperator = BO && BO->getOpcode() == BO_LAnd;
for (Stmt::child_range I = E->children(); I; ++I) {
Expr *ChildExpr = dyn_cast_or_null<Expr>(*I);
if (!ChildExpr)
continue;
- if (IsLogicalOperator &&
+ if (IsLogicalAndOperator &&
isa<StringLiteral>(ChildExpr->IgnoreParenImpCasts()))
- // Ignore checking string literals that are in logical operators.
+ // Ignore checking string literals that are in logical and operators.
+ // This is a common pattern for asserts.
continue;
AnalyzeImplicitConversions(S, ChildExpr, CC);
}
@@ -5599,6 +6099,125 @@
} // end anonymous namespace
+enum {
+ AddressOf,
+ FunctionPointer,
+ ArrayPointer
+};
+
+/// \brief Diagnose pointers that are always non-null.
+/// \param E the expression containing the pointer
+/// \param NullKind NPCK_NotNull if E is a cast to bool, otherwise, E is
+/// compared to a null pointer
+/// \param IsEqual True when the comparison is equal to a null pointer
+/// \param Range Extra SourceRange to highlight in the diagnostic
+void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
+ Expr::NullPointerConstantKind NullKind,
+ bool IsEqual, SourceRange Range) {
+
+ // Don't warn inside macros.
+ if (E->getExprLoc().isMacroID())
+ return;
+ E = E->IgnoreImpCasts();
+
+ const bool IsCompare = NullKind != Expr::NPCK_NotNull;
+
+ bool IsAddressOf = false;
+
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+ if (UO->getOpcode() != UO_AddrOf)
+ return;
+ IsAddressOf = true;
+ E = UO->getSubExpr();
+ }
+
+ // Expect to find a single Decl. Skip anything more complicated.
+ ValueDecl *D = 0;
+ if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) {
+ D = R->getDecl();
+ } else if (MemberExpr *M = dyn_cast<MemberExpr>(E)) {
+ D = M->getMemberDecl();
+ }
+
+ // Weak Decls can be null.
+ if (!D || D->isWeak())
+ return;
+
+ QualType T = D->getType();
+ const bool IsArray = T->isArrayType();
+ const bool IsFunction = T->isFunctionType();
+
+ if (IsAddressOf) {
+ // Address of function is used to silence the function warning.
+ if (IsFunction)
+ return;
+ // Address of reference can be null.
+ if (T->isReferenceType())
+ return;
+ }
+
+ // Found nothing.
+ if (!IsAddressOf && !IsFunction && !IsArray)
+ return;
+
+ // Pretty print the expression for the diagnostic.
+ std::string Str;
+ llvm::raw_string_ostream S(Str);
+ E->printPretty(S, 0, getPrintingPolicy());
+
+ unsigned DiagID = IsCompare ? diag::warn_null_pointer_compare
+ : diag::warn_impcast_pointer_to_bool;
+ unsigned DiagType;
+ if (IsAddressOf)
+ DiagType = AddressOf;
+ else if (IsFunction)
+ DiagType = FunctionPointer;
+ else if (IsArray)
+ DiagType = ArrayPointer;
+ else
+ llvm_unreachable("Could not determine diagnostic.");
+ Diag(E->getExprLoc(), DiagID) << DiagType << S.str() << E->getSourceRange()
+ << Range << IsEqual;
+
+ if (!IsFunction)
+ return;
+
+ // Suggest '&' to silence the function warning.
+ Diag(E->getExprLoc(), diag::note_function_warning_silence)
+ << FixItHint::CreateInsertion(E->getLocStart(), "&");
+
+ // Check to see if '()' fixit should be emitted.
+ QualType ReturnType;
+ UnresolvedSet<4> NonTemplateOverloads;
+ tryExprAsCall(*E, ReturnType, NonTemplateOverloads);
+ if (ReturnType.isNull())
+ return;
+
+ if (IsCompare) {
+ // There are two cases here. If there is null constant, the only suggest
+ // for a pointer return type. If the null is 0, then suggest if the return
+ // type is a pointer or an integer type.
+ if (!ReturnType->isPointerType()) {
+ if (NullKind == Expr::NPCK_ZeroExpression ||
+ NullKind == Expr::NPCK_ZeroLiteral) {
+ if (!ReturnType->isIntegerType())
+ return;
+ } else {
+ return;
+ }
+ }
+ } else { // !IsCompare
+ // For function to bool, only suggest if the function pointer has bool
+ // return type.
+ if (!ReturnType->isSpecificBuiltinType(BuiltinType::Bool))
+ return;
+ }
+ Diag(E->getExprLoc(), diag::note_function_to_function_call)
+ << FixItHint::CreateInsertion(
+ getPreprocessor().getLocForEndOfToken(E->getLocEnd()), "()");
+}
+
+
/// Diagnoses "dangerous" implicit conversions within the given
/// expression (which is a full expression). Implements -Wconversion
/// and -Wsign-compare.
@@ -6189,11 +6808,23 @@
// 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);
+ // object's destructor. However, we don't perform any direct access check
+ // on the dtor.
+ if (getLangOpts().CPlusPlus && Context.getTargetInfo()
+ .getCXXABI()
+ .areArgsDestroyedLeftToRightInCallee()) {
+ if (!Param->isInvalidDecl()) {
+ if (const RecordType *RT = Param->getType()->getAs<RecordType>()) {
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (!ClassDecl->isInvalidDecl() &&
+ !ClassDecl->hasIrrelevantDestructor() &&
+ !ClassDecl->isDependentContext()) {
+ CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
+ MarkFunctionReferenced(Param->getLocation(), Destructor);
+ DiagnoseUseOfDecl(Destructor, Param->getLocation());
+ }
+ }
+ }
}
}
@@ -6784,7 +7415,7 @@
Expr *LHS, Expr *RHS) {
QualType LHSType;
// PropertyRef on LHS type need be directly obtained from
- // its declaration as it has a PsuedoType.
+ // its declaration as it has a PseudoType.
ObjCPropertyRefExpr *PRE
= dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens());
if (PRE && !PRE->isImplicitProperty()) {
@@ -7057,21 +7688,16 @@
RecordDecl *RD1,
RecordDecl *RD2) {
llvm::SmallPtrSet<FieldDecl *, 8> UnmatchedFields;
- for (RecordDecl::field_iterator Field2 = RD2->field_begin(),
- Field2End = RD2->field_end();
- Field2 != Field2End; ++Field2) {
- UnmatchedFields.insert(*Field2);
- }
+ for (auto *Field2 : RD2->fields())
+ UnmatchedFields.insert(Field2);
- for (RecordDecl::field_iterator Field1 = RD1->field_begin(),
- Field1End = RD1->field_end();
- Field1 != Field1End; ++Field1) {
+ for (auto *Field1 : RD1->fields()) {
llvm::SmallPtrSet<FieldDecl *, 8>::iterator
I = UnmatchedFields.begin(),
E = UnmatchedFields.end();
for ( ; I != E; ++I) {
- if (isLayoutCompatible(C, *Field1, *I)) {
+ if (isLayoutCompatible(C, Field1, *I)) {
bool Result = UnmatchedFields.erase(*I);
(void) Result;
assert(Result);
@@ -7236,10 +7862,7 @@
return false;
if (VD) {
- for (specific_attr_iterator<TypeTagForDatatypeAttr>
- I = VD->specific_attr_begin<TypeTagForDatatypeAttr>(),
- E = VD->specific_attr_end<TypeTagForDatatypeAttr>();
- I != E; ++I) {
+ if (TypeTagForDatatypeAttr *I = VD->getAttr<TypeTagForDatatypeAttr>()) {
if (I->getArgumentKind() != ArgumentKind) {
FoundWrongKind = true;
return false;
@@ -7372,8 +7995,9 @@
if (mismatch)
Diag(ArgumentExpr->getExprLoc(), diag::warn_type_safety_type_mismatch)
- << ArgumentType << ArgumentKind->getName()
+ << ArgumentType << ArgumentKind
<< TypeInfo.LayoutCompatible << RequiredType
<< ArgumentExpr->getSourceRange()
<< TypeTagExpr->getSourceRange();
}
+
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 7a1b36b..d44c04b 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -660,13 +660,10 @@
return C.getObjCInterfaceType(Iface);
QualType T;
- if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+ if (const FunctionDecl *Function = ND->getAsFunction())
T = Function->getCallResultType();
else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
T = Method->getSendResultType();
- else if (const FunctionTemplateDecl *FunTmpl =
- dyn_cast<FunctionTemplateDecl>(ND))
- T = FunTmpl->getTemplatedDecl()->getCallResultType();
else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
@@ -700,7 +697,7 @@
}
if (const FunctionType *Function = T->getAs<FunctionType>()) {
- T = Function->getResultType();
+ T = Function->getReturnType();
continue;
}
@@ -1256,9 +1253,9 @@
public:
CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
: Results(Results), CurContext(CurContext) { }
-
- virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
- bool InBaseClass) {
+
+ void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+ bool InBaseClass) override {
bool Accessible = true;
if (Ctx)
Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
@@ -1784,10 +1781,10 @@
// know the function is void or not.
bool isVoid = false;
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
- isVoid = Function->getResultType()->isVoidType();
+ isVoid = Function->getReturnType()->isVoidType();
else if (ObjCMethodDecl *Method
= dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
- isVoid = Method->getResultType()->isVoidType();
+ isVoid = Method->getReturnType()->isVoidType();
else if (SemaRef.getCurBlock() &&
!SemaRef.getCurBlock()->ReturnType.isNull())
isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
@@ -2066,14 +2063,11 @@
return;
// Determine the type of the declaration (if it has a type).
- QualType T;
- if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
- T = Function->getResultType();
+ QualType T;
+ if (const FunctionDecl *Function = ND->getAsFunction())
+ T = Function->getReturnType();
else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
- T = Method->getResultType();
- else if (const FunctionTemplateDecl *FunTmpl =
- dyn_cast<FunctionTemplateDecl>(ND))
- T = FunTmpl->getTemplatedDecl()->getResultType();
+ T = Method->getReturnType();
else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
else if (isa<UnresolvedUsingValueDecl>(ND)) {
@@ -2206,26 +2200,26 @@
// We have the function prototype behind the block pointer type, as it was
// written in the source.
std::string Result;
- QualType ResultType = Block.getTypePtr()->getResultType();
+ QualType ResultType = Block.getTypePtr()->getReturnType();
if (!ResultType->isVoidType() || SuppressBlock)
ResultType.getAsStringInternal(Result, Policy);
// Format the parameter list.
std::string Params;
- if (!BlockProto || Block.getNumArgs() == 0) {
+ if (!BlockProto || Block.getNumParams() == 0) {
if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Params = "(...)";
else
Params = "(void)";
} else {
Params += "(";
- for (unsigned I = 0, N = Block.getNumArgs(); I != N; ++I) {
+ for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
if (I)
Params += ", ";
- Params += FormatFunctionParameter(Context, Policy, Block.getArg(I),
- /*SuppressName=*/false,
+ Params += FormatFunctionParameter(Context, Policy, Block.getParam(I),
+ /*SuppressName=*/false,
/*SuppressBlock=*/true);
-
+
if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Params += ", ...";
}
@@ -2297,7 +2291,7 @@
if (const FunctionProtoType *Proto
= Function->getType()->getAs<FunctionProtoType>())
if (Proto->isVariadic()) {
- if (Proto->getNumArgs() == 0)
+ if (Proto->getNumParams() == 0)
Result.AddPlaceholderChunk("...");
MaybeAddSentinel(Context, Function, Result);
@@ -2644,12 +2638,9 @@
return Result.TakeString();
}
- for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
- if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
- Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
- }
- }
-
+ for (const auto *I : ND->specific_attrs<AnnotateAttr>())
+ Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
+
AddResultTypeChunk(Ctx, Policy, ND, Result);
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
@@ -2836,9 +2827,8 @@
// Function without a prototype. Just give the return type and a
// highlighted ellipsis.
const FunctionType *FT = getFunctionType();
- Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
- S.Context, Policy,
- Result.getAllocator()));
+ Result.AddTextChunk(GetCompletionTypeString(FT->getReturnType(), S.Context,
+ Policy, Result.getAllocator()));
Result.AddChunk(CodeCompletionString::CK_LeftParen);
Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Result.AddChunk(CodeCompletionString::CK_RightParen);
@@ -2849,12 +2839,11 @@
Result.AddTextChunk(
Result.getAllocator().CopyString(FDecl->getNameAsString()));
else
- Result.AddTextChunk(
- Result.getAllocator().CopyString(
- Proto->getResultType().getAsString(Policy)));
-
+ Result.AddTextChunk(Result.getAllocator().CopyString(
+ Proto->getReturnType().getAsString(Policy)));
+
Result.AddChunk(CodeCompletionString::CK_LeftParen);
- unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
+ unsigned NumParams = FDecl ? FDecl->getNumParams() : Proto->getNumParams();
for (unsigned I = 0; I != NumParams; ++I) {
if (I)
Result.AddChunk(CodeCompletionString::CK_Comma);
@@ -2866,7 +2855,7 @@
ArgString = FDecl->getParamDecl(I)->getNameAsString();
ArgType = FDecl->getParamDecl(I)->getOriginalType();
} else {
- ArgType = Proto->getArgType(I);
+ ArgType = Proto->getParamType(I);
}
ArgType.getAsStringInternal(ArgString, Policy);
@@ -3109,13 +3098,9 @@
// We need to have names for all of the parameters, if we're going to
// generate a forwarding call.
- for (CXXMethodDecl::param_iterator P = Method->param_begin(),
- PEnd = Method->param_end();
- P != PEnd;
- ++P) {
- if (!(*P)->getDeclName())
+ for (auto P : Method->params())
+ if (!P->getDeclName())
return;
- }
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
@@ -3145,16 +3130,14 @@
Overridden->getNameAsString()));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
bool FirstParam = true;
- for (CXXMethodDecl::param_iterator P = Method->param_begin(),
- PEnd = Method->param_end();
- P != PEnd; ++P) {
+ for (auto P : Method->params()) {
if (FirstParam)
FirstParam = false;
else
Builder.AddChunk(CodeCompletionString::CK_Comma);
- Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
- (*P)->getIdentifier()->getName()));
+ Builder.AddPlaceholderChunk(
+ Results.getAllocator().CopyString(P->getIdentifier()->getName()));
}
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(CodeCompletionResult(Builder.TakeString(),
@@ -3475,32 +3458,26 @@
Container = getContainerDef(Container);
// Add properties in this container.
- for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
- PEnd = Container->prop_end();
- P != PEnd;
- ++P) {
+ for (const auto *P : Container->properties())
if (AddedProperties.insert(P->getIdentifier()))
- Results.MaybeAddResult(Result(*P, Results.getBasePriority(*P), 0),
+ Results.MaybeAddResult(Result(P, Results.getBasePriority(P), 0),
CurContext);
- }
// Add nullary methods
if (AllowNullaryMethods) {
ASTContext &Context = Container->getASTContext();
PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
- for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
- MEnd = Container->meth_end();
- M != MEnd; ++M) {
+ for (auto *M : Container->methods()) {
if (M->getSelector().isUnarySelector())
if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
if (AddedProperties.insert(Name)) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
- AddResultTypeChunk(Context, Policy, *M, Builder);
+ AddResultTypeChunk(Context, Policy, M, Builder);
Builder.AddTypedTextChunk(
Results.getAllocator().CopyString(Name->getName()));
- Results.MaybeAddResult(Result(Builder.TakeString(), *M,
+ Results.MaybeAddResult(Result(Builder.TakeString(), M,
CCP_MemberDeclaration + CCD_MethodAsProperty),
CurContext);
}
@@ -3510,27 +3487,20 @@
// Add properties in referenced protocols.
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
- for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
- PEnd = Protocol->protocol_end();
- P != PEnd; ++P)
- AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
+ for (auto *P : Protocol->protocols())
+ AddObjCProperties(P, AllowCategories, AllowNullaryMethods, CurContext,
AddedProperties, Results);
} else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
if (AllowCategories) {
// Look through categories.
- for (ObjCInterfaceDecl::known_categories_iterator
- Cat = IFace->known_categories_begin(),
- CatEnd = IFace->known_categories_end();
- Cat != CatEnd; ++Cat)
- AddObjCProperties(*Cat, AllowCategories, AllowNullaryMethods,
- CurContext, AddedProperties, Results);
+ for (auto *Cat : IFace->known_categories())
+ AddObjCProperties(Cat, AllowCategories, AllowNullaryMethods, CurContext,
+ AddedProperties, Results);
}
-
+
// Look through protocols.
- for (ObjCInterfaceDecl::all_protocol_iterator
- I = IFace->all_referenced_protocol_begin(),
- E = IFace->all_referenced_protocol_end(); I != E; ++I)
- AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
+ for (auto *I : IFace->all_referenced_protocols())
+ AddObjCProperties(I, AllowCategories, AllowNullaryMethods, CurContext,
AddedProperties, Results);
// Look in the superclass.
@@ -3541,10 +3511,8 @@
} else if (const ObjCCategoryDecl *Category
= dyn_cast<ObjCCategoryDecl>(Container)) {
// Look through protocols.
- for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
- PEnd = Category->protocol_end();
- P != PEnd; ++P)
- AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
+ for (auto *P : Category->protocols())
+ AddObjCProperties(P, AllowCategories, AllowNullaryMethods, CurContext,
AddedProperties, Results);
}
}
@@ -3636,10 +3604,8 @@
AddedProperties, Results);
// Add properties from the protocols in a qualified interface.
- for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
- E = ObjCPtr->qual_end();
- I != E; ++I)
- AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
+ for (auto *I : ObjCPtr->quals())
+ AddObjCProperties(I, true, /*AllowNullaryMethods=*/true, CurContext,
AddedProperties, Results);
} else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
(!IsArrow && BaseType->isObjCObjectType())) {
@@ -3809,13 +3775,11 @@
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Expression);
Results.EnterNewScope();
- for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
- EEnd = Enum->enumerator_end();
- E != EEnd; ++E) {
- if (EnumeratorsSeen.count(*E))
+ for (auto *E : Enum->enumerators()) {
+ if (EnumeratorsSeen.count(E))
continue;
- CodeCompletionResult R(*E, CCP_EnumInCase, Qualifier);
+ CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Results.AddResult(R, CurContext, 0, false);
}
Results.ExitScope();
@@ -3833,22 +3797,6 @@
Results.data(),Results.size());
}
-namespace {
- struct IsBetterOverloadCandidate {
- Sema &S;
- SourceLocation Loc;
-
- public:
- explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
- : S(S), Loc(Loc) { }
-
- bool
- operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
- return isBetterOverloadCandidate(S, X, Y, Loc);
- }
- };
-}
-
static bool anyNullArguments(ArrayRef<Expr *> Args) {
if (Args.size() && !Args.data())
return true;
@@ -3910,9 +3858,12 @@
if (!CandidateSet.empty()) {
// Sort the overload candidate set by placing the best overloads first.
- std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
- IsBetterOverloadCandidate(*this, Loc));
-
+ std::stable_sort(
+ CandidateSet.begin(), CandidateSet.end(),
+ [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
+ return isBetterOverloadCandidate(*this, X, Y, Loc);
+ });
+
// Add the remaining viable overload candidates as code-completion reslults.
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
CandEnd = CandidateSet.end();
@@ -3925,12 +3876,13 @@
for (unsigned I = 0, N = Results.size(); I != N; ++I) {
if (const FunctionType *FType = Results[I].getFunctionType())
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
- if (Args.size() < Proto->getNumArgs()) {
+ if (Args.size() < Proto->getNumParams()) {
if (ParamType.isNull())
- ParamType = Proto->getArgType(Args.size());
+ ParamType = Proto->getParamType(Args.size());
else if (!Context.hasSameUnqualifiedType(
- ParamType.getNonReferenceType(),
- Proto->getArgType(Args.size()).getNonReferenceType())) {
+ ParamType.getNonReferenceType(),
+ Proto->getParamType(Args.size())
+ .getNonReferenceType())) {
ParamType = QualType();
break;
}
@@ -3951,8 +3903,8 @@
if (const FunctionProtoType *Proto
= FunctionType->getAs<FunctionProtoType>()) {
- if (Args.size() < Proto->getNumArgs())
- ParamType = Proto->getArgType(Args.size());
+ if (Args.size() < Proto->getNumParams())
+ ParamType = Proto->getParamType(Args.size());
}
}
@@ -3982,10 +3934,10 @@
if (BlockScopeInfo *BSI = getCurBlock())
ResultType = BSI->ReturnType;
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
- ResultType = Function->getResultType();
+ ResultType = Function->getReturnType();
else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
- ResultType = Method->getResultType();
-
+ ResultType = Method->getReturnType();
+
if (ResultType.isNull())
CodeCompleteOrdinaryName(S, PCC_Expression);
else
@@ -4080,7 +4032,7 @@
// The "template" keyword can follow "::" in the grammar, but only
// put it into the grammar if the nested-name-specifier is dependent.
- NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+ NestedNameSpecifier *NNS = SS.getScopeRep();
if (!Results.empty() && NNS->isDependent())
Results.AddResult("template");
@@ -4274,21 +4226,19 @@
Results.getCodeCompletionTUInfo());
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()))) {
+ for (const auto &Base : ClassDecl->bases()) {
+ if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))) {
SawLastInitializer
= !Initializers.empty() &&
Initializers.back()->isBaseInitializer() &&
- Context.hasSameUnqualifiedType(Base->getType(),
+ Context.hasSameUnqualifiedType(Base.getType(),
QualType(Initializers.back()->getBaseClass(), 0));
continue;
}
Builder.AddTypedTextChunk(
Results.getAllocator().CopyString(
- Base->getType().getAsString(Policy)));
+ Base.getType().getAsString(Policy)));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("args");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
@@ -4299,21 +4249,19 @@
}
// Add completions for virtual base classes.
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd; ++Base) {
- if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
+ for (const auto &Base : ClassDecl->vbases()) {
+ if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))) {
SawLastInitializer
= !Initializers.empty() &&
Initializers.back()->isBaseInitializer() &&
- Context.hasSameUnqualifiedType(Base->getType(),
+ Context.hasSameUnqualifiedType(Base.getType(),
QualType(Initializers.back()->getBaseClass(), 0));
continue;
}
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(
- Base->getType().getAsString(Policy)));
+ Base.getType().getAsString(Policy)));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("args");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
@@ -4324,14 +4272,12 @@
}
// Add completions for members.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
+ for (auto *Field : ClassDecl->fields()) {
if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
SawLastInitializer
= !Initializers.empty() &&
Initializers.back()->isAnyMemberInitializer() &&
- Initializers.back()->getAnyMember() == *Field;
+ Initializers.back()->getAnyMember() == Field;
continue;
}
@@ -4348,7 +4294,7 @@
: CCP_MemberDeclaration,
CXCursor_MemberRef,
CXAvailability_Available,
- *Field));
+ Field));
SawLastInitializer = false;
}
Results.ExitScope();
@@ -4389,9 +4335,8 @@
// Look for other capturable variables.
for (; S && !isNamespaceScope(S); S = S->getParent()) {
- for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
- D != DEnd; ++D) {
- VarDecl *Var = dyn_cast<VarDecl>(*D);
+ for (const auto *D : S->decls()) {
+ const auto *Var = dyn_cast<VarDecl>(D);
if (!Var ||
!Var->hasLocalStorage() ||
Var->hasAttr<BlocksAttr>())
@@ -4759,7 +4704,7 @@
CodeCompletionBuilder Setter(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Setter.AddTypedTextChunk("setter");
- Setter.AddTextChunk(" = ");
+ Setter.AddTextChunk("=");
Setter.AddPlaceholderChunk("method");
Results.AddResult(CodeCompletionResult(Setter.TakeString()));
}
@@ -4767,7 +4712,7 @@
CodeCompletionBuilder Getter(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Getter.AddTypedTextChunk("getter");
- Getter.AddTextChunk(" = ");
+ Getter.AddTextChunk("=");
Getter.AddPlaceholderChunk("method");
Results.AddResult(CodeCompletionResult(Getter.TakeString()));
}
@@ -4856,22 +4801,20 @@
Container = getContainerDef(Container);
ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
bool isRootClass = IFace && !IFace->getSuperClass();
- for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
- MEnd = Container->meth_end();
- M != MEnd; ++M) {
+ for (auto *M : Container->methods()) {
// The instance methods on the root class can be messaged via the
// metaclass.
if (M->isInstanceMethod() == WantInstanceMethods ||
(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, AllowSameLength))
+ if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
continue;
if (!Selectors.insert(M->getSelector()))
continue;
- Result R = Result(*M, Results.getBasePriority(*M), 0);
+ Result R = Result(M, Results.getBasePriority(M), 0);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = (WantKind != MK_Any);
if (!InOriginalClass)
@@ -4897,19 +4840,12 @@
return;
// Add methods in protocols.
- for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
- E = IFace->protocol_end();
- I != E; ++I)
- AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
+ for (auto *I : IFace->protocols())
+ AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents,
CurContext, Selectors, AllowSameLength, Results, false);
// Add methods in categories.
- for (ObjCInterfaceDecl::known_categories_iterator
- Cat = IFace->known_categories_begin(),
- CatEnd = IFace->known_categories_end();
- Cat != CatEnd; ++Cat) {
- ObjCCategoryDecl *CatDecl = *Cat;
-
+ for (auto *CatDecl : IFace->known_categories()) {
AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
CurContext, Selectors, AllowSameLength,
Results, InOriginalClass);
@@ -5181,10 +5117,7 @@
// Check in categories or class extensions.
if (!SuperMethod) {
- for (ObjCInterfaceDecl::known_categories_iterator
- Cat = Class->known_categories_begin(),
- CatEnd = Class->known_categories_end();
- Cat != CatEnd; ++Cat) {
+ for (const auto *Cat : Class->known_categories()) {
if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
CurMethod->isInstanceMethod())))
break;
@@ -5536,7 +5469,7 @@
// If we're messaging an expression with type "id" or "Class", check
// whether we know something special about the receiver that allows
// us to assume a more-specific receiver type.
- if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
+ if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
if (ReceiverType->isObjCClassType())
return CodeCompleteObjCClassMessage(S,
@@ -5547,6 +5480,13 @@
ReceiverType = Context.getObjCObjectPointerType(
Context.getObjCInterfaceType(IFace));
}
+ } else if (RecExpr && getLangOpts().CPlusPlus) {
+ ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
+ if (Conv.isUsable()) {
+ RecExpr = Conv.take();
+ ReceiverType = RecExpr->getType();
+ }
+ }
// Build the set of methods we can see.
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
@@ -5587,10 +5527,8 @@
else if (const ObjCObjectPointerType *QualID
= ReceiverType->getAsObjCQualifiedIdType()) {
// Search protocols for instance methods.
- for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
- E = QualID->qual_end();
- I != E; ++I)
- AddObjCMethods(*I, true, MK_Any, SelIdents, CurContext,
+ for (auto *I : QualID->quals())
+ AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Selectors, AtArgumentExpression, Results);
}
// Handle messages to a pointer to interface type.
@@ -5602,10 +5540,8 @@
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, CurContext,
+ for (auto *I : IFacePtr->quals())
+ AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Selectors, AtArgumentExpression, Results);
}
// Handle messages to "id".
@@ -5750,11 +5686,9 @@
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
- for (DeclContext::decl_iterator D = Ctx->decls_begin(),
- DEnd = Ctx->decls_end();
- D != DEnd; ++D) {
+ for (const auto *D : Ctx->decls()) {
// Record any protocols we find.
- if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
+ if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Results.AddResult(Result(Proto, Results.getBasePriority(Proto), 0),
CurContext, 0, false);
@@ -5818,11 +5752,9 @@
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
- for (DeclContext::decl_iterator D = Ctx->decls_begin(),
- DEnd = Ctx->decls_end();
- D != DEnd; ++D) {
+ for (const auto *D : Ctx->decls()) {
// Record any interfaces we find.
- if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
+ if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
(!OnlyUnimplemented || !Class->getImplementation()))
Results.AddResult(Result(Class, Results.getBasePriority(Class), 0),
@@ -5909,21 +5841,15 @@
NamedDecl *CurClass
= LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
- for (ObjCInterfaceDecl::visible_categories_iterator
- Cat = Class->visible_categories_begin(),
- CatEnd = Class->visible_categories_end();
- Cat != CatEnd; ++Cat) {
+ for (const auto *Cat : Class->visible_categories())
CategoryNames.insert(Cat->getIdentifier());
- }
}
// Add all of the categories we know about.
Results.EnterNewScope();
TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
- for (DeclContext::decl_iterator D = TU->decls_begin(),
- DEnd = TU->decls_end();
- D != DEnd; ++D)
- if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
+ for (const auto *D : TU->decls())
+ if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
if (CategoryNames.insert(Category->getIdentifier()))
Results.AddResult(Result(Category, Results.getBasePriority(Category),0),
CurContext, 0, false);
@@ -5959,13 +5885,10 @@
Results.EnterNewScope();
bool IgnoreImplemented = true;
while (Class) {
- for (ObjCInterfaceDecl::visible_categories_iterator
- Cat = Class->visible_categories_begin(),
- CatEnd = Class->visible_categories_end();
- Cat != CatEnd; ++Cat) {
+ for (const auto *Cat : Class->visible_categories()) {
if ((!IgnoreImplemented || !Cat->getImplementation()) &&
CategoryNames.insert(Cat->getIdentifier()))
- Results.AddResult(Result(*Cat, Results.getBasePriority(*Cat), 0),
+ Results.AddResult(Result(Cat, Results.getBasePriority(Cat), 0),
CurContext, 0, false);
}
@@ -5994,10 +5917,8 @@
// Ignore any properties that have already been implemented.
Container = getContainerDef(Container);
- for (DeclContext::decl_iterator D = Container->decls_begin(),
- DEnd = Container->decls_end();
- D != DEnd; ++D)
- if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
+ for (const auto *D : Container->decls())
+ if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Results.Ignore(PropertyImpl->getPropertyDecl());
// Add any properties that we find.
@@ -6144,11 +6065,8 @@
KnownMethods, InOriginalClass);
// Add methods from any class extensions and categories.
- for (ObjCInterfaceDecl::visible_categories_iterator
- Cat = IFace->visible_categories_begin(),
- CatEnd = IFace->visible_categories_end();
- Cat != CatEnd; ++Cat) {
- FindImplementableMethods(Context, *Cat, WantInstanceMethods, ReturnType,
+ for (auto *Cat : IFace->visible_categories()) {
+ FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
KnownMethods, false);
}
@@ -6196,16 +6114,14 @@
// Add methods in this container. This operation occurs last because
// we want the methods from this container to override any methods
// we've previously seen with the same selector.
- for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
- MEnd = Container->meth_end();
- M != MEnd; ++M) {
+ for (auto *M : Container->methods()) {
if (M->isInstanceMethod() == WantInstanceMethods) {
if (!ReturnType.isNull() &&
- !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
+ !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
continue;
KnownMethods[M->getSelector()] =
- KnownMethodsMap::mapped_type(*M, InOriginalClass);
+ KnownMethodsMap::mapped_type(M, InOriginalClass);
}
}
}
@@ -6926,10 +6842,9 @@
// If the result type was not already provided, add it to the
// pattern as (type).
if (ReturnType.isNull())
- AddObjCPassingTypeChunk(Method->getResultType(),
- Method->getObjCDeclQualifier(),
- Context, Policy,
- Builder);
+ AddObjCPassingTypeChunk(Method->getReturnType(),
+ Method->getObjCDeclQualifier(), Context, Policy,
+ Builder);
Selector Sel = Method->getSelector();
@@ -6973,7 +6888,7 @@
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
- if (!Method->getResultType()->isVoidType()) {
+ if (!Method->getReturnType()->isVoidType()) {
// If the result type is not void, add a return clause.
Builder.AddTextChunk("return");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
@@ -7011,23 +6926,14 @@
if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
IFace = Category->getClassInterface();
- if (IFace) {
- for (ObjCInterfaceDecl::visible_categories_iterator
- Cat = IFace->visible_categories_begin(),
- CatEnd = IFace->visible_categories_end();
- Cat != CatEnd; ++Cat) {
- Containers.push_back(*Cat);
- }
- }
+ if (IFace)
+ for (auto *Cat : IFace->visible_categories())
+ Containers.push_back(Cat);
- for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
- for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
- PEnd = Containers[I]->prop_end();
- P != PEnd; ++P) {
- AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
+ for (unsigned I = 0, N = Containers.size(); I != N; ++I)
+ for (auto *P : Containers[I]->properties())
+ AddObjCKeyValueCompletions(P, IsInstanceMethod, ReturnType, Context,
KnownSelectors, Results);
- }
- }
}
Results.ExitScope();
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 328ce70..43d855c 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -62,24 +62,29 @@
class TypeNameValidatorCCC : public CorrectionCandidateCallback {
public:
- TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false)
- : AllowInvalidDecl(AllowInvalid), WantClassName(WantClass) {
+ TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false,
+ bool AllowTemplates=false)
+ : AllowInvalidDecl(AllowInvalid), WantClassName(WantClass),
+ AllowClassTemplates(AllowTemplates) {
WantExpressionKeywords = false;
WantCXXNamedCasts = false;
WantRemainingKeywords = false;
}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
- if (NamedDecl *ND = candidate.getCorrectionDecl())
- return (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
- (AllowInvalidDecl || !ND->isInvalidDecl());
- else
- return !WantClassName && candidate.isKeyword();
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
+ if (NamedDecl *ND = candidate.getCorrectionDecl()) {
+ bool IsType = isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
+ bool AllowedTemplate = AllowClassTemplates && isa<ClassTemplateDecl>(ND);
+ return (IsType || AllowedTemplate) &&
+ (AllowInvalidDecl || !ND->isInvalidDecl());
+ }
+ return !WantClassName && candidate.isKeyword();
}
private:
bool AllowInvalidDecl;
bool WantClassName;
+ bool AllowClassTemplates;
};
}
@@ -381,9 +386,8 @@
const Type *Ty = SS->getScopeRep()->getAsType();
CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext);
- for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(),
- BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base)
- if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base->getType()))
+ for (const auto &Base : RD->bases())
+ if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base.getType()))
return true;
return S->isFunctionPrototypeScope();
}
@@ -394,13 +398,14 @@
SourceLocation IILoc,
Scope *S,
CXXScopeSpec *SS,
- ParsedType &SuggestedType) {
+ ParsedType &SuggestedType,
+ bool AllowClassTemplates) {
// We don't have anything to suggest (yet).
SuggestedType = ParsedType();
// There may have been a typo in the name of the type. Look up typo
// results, in case we have something that we can suggest.
- TypeNameValidatorCCC Validator(false);
+ TypeNameValidatorCCC Validator(false, false, AllowClassTemplates);
if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(II, IILoc),
LookupOrdinaryName, S, SS,
Validator)) {
@@ -467,11 +472,11 @@
<< II << DC << SS->getRange();
else if (isDependentScopeSpecifier(*SS)) {
unsigned DiagID = diag::err_typename_missing;
- if (getLangOpts().MicrosoftMode && isMicrosoftMissingTypename(SS, S))
+ if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S))
DiagID = diag::warn_typename_missing;
Diag(SS->getRange().getBegin(), DiagID)
- << (NestedNameSpecifier *)SS->getScopeRep() << II->getName()
+ << SS->getScopeRep() << II->getName()
<< SourceRange(SS->getRange().getBegin(), IILoc)
<< FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename ");
SuggestedType = ActOnTypenameType(S, SourceLocation(),
@@ -845,7 +850,8 @@
// seems likely a type is wanted instead of the non-type that was found.
bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star);
if ((NextToken.is(tok::identifier) ||
- (NextIsOp && FirstDecl->isFunctionOrFunctionTemplate())) &&
+ (NextIsOp &&
+ FirstDecl->getUnderlyingDecl()->isFunctionOrFunctionTemplate())) &&
isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) {
TypeDecl *Type = Result.getAsSingle<TypeDecl>();
DiagnoseUseOfDecl(Type, NameLoc);
@@ -962,12 +968,9 @@
void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) {
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (FunctionTemplateDecl *TFD = dyn_cast_or_null<FunctionTemplateDecl>(D)) {
- // We assume that the caller has already called
- // ActOnReenterTemplateScope
- FD = TFD->getTemplatedDecl();
- }
+ // We assume that the caller has already called
+ // ActOnReenterTemplateScope so getTemplatedDecl() works.
+ FunctionDecl *FD = D->getAsFunction();
if (!FD)
return;
@@ -1086,9 +1089,8 @@
}
bool Sema::isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S,
- bool ExplicitInstantiationOrSpecialization) {
- return IdResolver.isDeclInScope(D, Ctx, S,
- ExplicitInstantiationOrSpecialization);
+ bool AllowInlineNamespace) {
+ return IdResolver.isDeclInScope(D, Ctx, S, AllowInlineNamespace);
}
Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) {
@@ -1108,21 +1110,19 @@
/// Filters out lookup results that don't fall within the given scope
/// as determined by isDeclInScope.
-void Sema::FilterLookupForScope(LookupResult &R,
- DeclContext *Ctx, Scope *S,
+void Sema::FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
bool ConsiderLinkage,
- bool ExplicitInstantiationOrSpecialization) {
+ bool AllowInlineNamespace) {
LookupResult::Filter F = R.makeFilter();
while (F.hasNext()) {
NamedDecl *D = F.next();
- if (isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization))
+ if (isDeclInScope(D, Ctx, S, AllowInlineNamespace))
continue;
- if (ConsiderLinkage &&
- isOutOfScopePreviousDeclaration(D, Ctx, Context))
+ if (ConsiderLinkage && isOutOfScopePreviousDeclaration(D, Ctx, Context))
continue;
-
+
F.erase();
}
@@ -1173,8 +1173,8 @@
//
// When we see foo we don't know if after the typedef we will get 'A' or '*A'
// for example. If 'A', foo will have external linkage. If we have '*A',
-// foo will have no linkage. Since we can't know untill we get to the end
-// of the typedef, this function finds out if D might have non external linkage.
+// foo will have no linkage. Since we can't know until we get to the end
+// of the typedef, this function finds out if D might have non-external linkage.
// Callers should verify at the end of the TU if it D has external linkage or
// not.
bool Sema::mightHaveNonExternalLinkage(const DeclaratorDecl *D) {
@@ -1204,7 +1204,8 @@
if (D->isInvalidDecl() || D->isUsed() || D->hasAttr<UnusedAttr>())
return false;
- // Ignore class templates.
+ // Ignore all entities declared within templates, and out-of-line definitions
+ // of members of class templates.
if (D->getDeclContext()->isDependentContext() ||
D->getLexicalDeclContext()->isDependentContext())
return false;
@@ -1271,7 +1272,8 @@
if (D->isInvalidDecl())
return false;
- if (D->isReferenced() || D->isUsed() || D->hasAttr<UnusedAttr>())
+ if (D->isReferenced() || D->isUsed() || D->hasAttr<UnusedAttr>() ||
+ D->hasAttr<ObjCPreciseLifetimeAttr>())
return false;
if (isa<LabelDecl>(D))
@@ -1374,9 +1376,7 @@
assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
"Scope shouldn't contain decls!");
- for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
- I != E; ++I) {
- Decl *TmpD = (*I);
+ for (auto *TmpD : S->decls()) {
assert(TmpD && "This decl didn't get pushed??");
assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?");
@@ -1395,16 +1395,6 @@
// Remove this name from our lexical scope.
IdResolver.RemoveDecl(D);
}
- DiagnoseUnusedBackingIvarInAccessor(S);
-}
-
-void Sema::ActOnStartFunctionDeclarator() {
- ++InFunctionDeclarator;
-}
-
-void Sema::ActOnEndFunctionDeclarator() {
- assert(InFunctionDeclarator);
- --InFunctionDeclarator;
}
/// \brief Look for an Objective-C class in the translation unit.
@@ -1549,6 +1539,7 @@
LinkageSpecDecl *CLinkageDecl =
LinkageSpecDecl::Create(Context, Parent, Loc, Loc,
LinkageSpecDecl::lang_c, false);
+ CLinkageDecl->setImplicit();
Parent->addDecl(CLinkageDecl);
Parent = CLinkageDecl;
}
@@ -1565,12 +1556,10 @@
// FunctionDecl.
if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) {
SmallVector<ParmVarDecl*, 16> Params;
- for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
+ for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
ParmVarDecl *parm =
- ParmVarDecl::Create(Context, New, SourceLocation(),
- SourceLocation(), 0,
- FT->getArgType(i), /*TInfo=*/0,
- SC_None, 0);
+ ParmVarDecl::Create(Context, New, SourceLocation(), SourceLocation(),
+ 0, FT->getParamType(i), /*TInfo=*/0, SC_None, 0);
parm->setScopeInfo(0, i);
Params.push_back(parm);
}
@@ -1797,46 +1786,19 @@
/// DeclhasAttr - returns true if decl Declaration already has the target
/// attribute.
-static bool
-DeclHasAttr(const Decl *D, const Attr *A) {
- // There can be multiple AvailabilityAttr in a Decl. Make sure we copy
- // all of them. It is mergeAvailabilityAttr in SemaDeclAttr.cpp that is
- // responsible for making sure they are consistent.
- const AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(A);
- if (AA)
- return false;
-
- // The following thread safety attributes can also be duplicated.
- switch (A->getKind()) {
- case attr::ExclusiveLocksRequired:
- case attr::SharedLocksRequired:
- case attr::LocksExcluded:
- case attr::ExclusiveLockFunction:
- case attr::SharedLockFunction:
- case attr::UnlockFunction:
- case attr::ExclusiveTrylockFunction:
- case attr::SharedTrylockFunction:
- case attr::GuardedBy:
- case attr::PtGuardedBy:
- case attr::AcquiredBefore:
- case attr::AcquiredAfter:
- return false;
- default:
- ;
- }
-
+static bool DeclHasAttr(const Decl *D, const Attr *A) {
const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A);
const AnnotateAttr *Ann = dyn_cast<AnnotateAttr>(A);
- for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i)
- if ((*i)->getKind() == A->getKind()) {
+ for (const auto *i : D->attrs())
+ if (i->getKind() == A->getKind()) {
if (Ann) {
- if (Ann->getAnnotation() == cast<AnnotateAttr>(*i)->getAnnotation())
+ if (Ann->getAnnotation() == cast<AnnotateAttr>(i)->getAnnotation())
return true;
continue;
}
// FIXME: Don't hardcode this check
- if (OA && isa<OwnershipAttr>(*i))
- return OA->getOwnKind() == cast<OwnershipAttr>(*i)->getOwnKind();
+ if (OA && isa<OwnershipAttr>(i))
+ return OA->getOwnKind() == cast<OwnershipAttr>(i)->getOwnKind();
return true;
}
@@ -1861,9 +1823,7 @@
AlignedAttr *OldAlignasAttr = 0;
AlignedAttr *OldStrictestAlignAttr = 0;
unsigned OldAlign = 0;
- for (specific_attr_iterator<AlignedAttr>
- I = Old->specific_attr_begin<AlignedAttr>(),
- E = Old->specific_attr_end<AlignedAttr>(); I != E; ++I) {
+ for (auto *I : Old->specific_attrs<AlignedAttr>()) {
// FIXME: We have no way of representing inherited dependent alignments
// in a case like:
// template<int A, int B> struct alignas(A) X;
@@ -1874,26 +1834,24 @@
return false;
if (I->isAlignas())
- OldAlignasAttr = *I;
+ OldAlignasAttr = I;
unsigned Align = I->getAlignment(S.Context);
if (Align > OldAlign) {
OldAlign = Align;
- OldStrictestAlignAttr = *I;
+ OldStrictestAlignAttr = I;
}
}
// Look for alignas attributes on New.
AlignedAttr *NewAlignasAttr = 0;
unsigned NewAlign = 0;
- for (specific_attr_iterator<AlignedAttr>
- I = New->specific_attr_begin<AlignedAttr>(),
- E = New->specific_attr_end<AlignedAttr>(); I != E; ++I) {
+ for (auto *I : New->specific_attrs<AlignedAttr>()) {
if (I->isAlignmentDependent())
return false;
if (I->isAlignas())
- NewAlignasAttr = *I;
+ NewAlignasAttr = I;
unsigned Align = I->getAlignment(S.Context);
if (Align > NewAlign)
@@ -1939,9 +1897,9 @@
// specifier, any other declaration of that object shall also
// have no alignment specifier.
S.Diag(New->getLocation(), diag::err_alignas_missing_on_definition)
- << OldAlignasAttr->isC11();
+ << OldAlignasAttr;
S.Diag(OldAlignasAttr->getLocation(), diag::note_alignas_on_declaration)
- << OldAlignasAttr->isC11();
+ << OldAlignasAttr;
}
bool AnyAdded = false;
@@ -1995,11 +1953,15 @@
else if (SectionAttr *SA = dyn_cast<SectionAttr>(Attr))
NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(),
AttrSpellingListIndex);
+ else if (MSInheritanceAttr *IA = dyn_cast<MSInheritanceAttr>(Attr))
+ NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), IA->getBestCase(),
+ AttrSpellingListIndex,
+ IA->getSemanticSpelling());
else if (isa<AlignedAttr>(Attr))
// AlignedAttrs are handled separately, because we need to handle all
// such attributes on a declaration at the same time.
NewAttr = 0;
- else if (!DeclHasAttr(D, Attr))
+ else if (Attr->duplicatesAllowed() || !DeclHasAttr(D, Attr))
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
if (NewAttr) {
@@ -2029,12 +1991,9 @@
}
static bool hasAttribute(const Decl *D, attr::Kind Kind) {
- for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end();
- I != E; ++I) {
- Attr *Attribute = *I;
+ for (const auto *Attribute : D->attrs())
if (Attribute->getKind() == Kind)
return true;
- }
return false;
}
@@ -2097,9 +2056,9 @@
// specifier, any other declaration of that object shall also
// have no alignment specifier.
S.Diag(Def->getLocation(), diag::err_alignas_missing_on_definition)
- << AA->isC11();
+ << AA;
S.Diag(NewAttribute->getLocation(), diag::note_alignas_on_declaration)
- << AA->isC11();
+ << AA;
NewAttributes.erase(NewAttributes.begin() + I);
--E;
continue;
@@ -2138,15 +2097,12 @@
// we process them.
if (!foundAny) New->setAttrs(AttrVec());
- for (specific_attr_iterator<InheritableAttr>
- i = Old->specific_attr_begin<InheritableAttr>(),
- e = Old->specific_attr_end<InheritableAttr>();
- i != e; ++i) {
+ for (auto *I : Old->specific_attrs<InheritableAttr>()) {
bool Override = false;
// Ignore deprecated/unavailable/availability attributes if requested.
- if (isa<DeprecatedAttr>(*i) ||
- isa<UnavailableAttr>(*i) ||
- isa<AvailabilityAttr>(*i)) {
+ if (isa<DeprecatedAttr>(I) ||
+ isa<UnavailableAttr>(I) ||
+ isa<AvailabilityAttr>(I)) {
switch (AMK) {
case AMK_None:
continue;
@@ -2161,10 +2117,10 @@
}
// Already handled.
- if (isa<UsedAttr>(*i))
+ if (isa<UsedAttr>(I))
continue;
- if (mergeDeclAttribute(*this, New, *i, Override))
+ if (mergeDeclAttribute(*this, New, I, Override))
foundAny = true;
}
@@ -2183,9 +2139,9 @@
// The first declaration of a function shall specify the
// carries_dependency attribute for its declarator-id if any declaration
// of the function specifies the carries_dependency attribute.
- if (newDecl->hasAttr<CarriesDependencyAttr>() &&
- !oldDecl->hasAttr<CarriesDependencyAttr>()) {
- S.Diag(newDecl->getAttr<CarriesDependencyAttr>()->getLocation(),
+ const CarriesDependencyAttr *CDA = newDecl->getAttr<CarriesDependencyAttr>();
+ if (CDA && !oldDecl->hasAttr<CarriesDependencyAttr>()) {
+ S.Diag(CDA->getLocation(),
diag::err_carries_dependency_missing_on_first_decl) << 1/*Param*/;
// Find the first declaration of the parameter.
// FIXME: Should we build redeclaration chains for function parameters?
@@ -2206,12 +2162,10 @@
// done before we process them.
if (!foundAny) newDecl->setAttrs(AttrVec());
- for (specific_attr_iterator<InheritableParamAttr>
- i = oldDecl->specific_attr_begin<InheritableParamAttr>(),
- e = oldDecl->specific_attr_end<InheritableParamAttr>(); i != e; ++i) {
- if (!DeclHasAttr(newDecl, *i)) {
+ for (const auto *I : oldDecl->specific_attrs<InheritableParamAttr>()) {
+ if (!DeclHasAttr(newDecl, I)) {
InheritableAttr *newAttr =
- cast<InheritableParamAttr>((*i)->clone(S.Context));
+ cast<InheritableParamAttr>(I->clone(S.Context));
newAttr->setInherited(true);
newDecl->addAttr(newAttr);
foundAny = true;
@@ -2298,15 +2252,10 @@
/// merged with.
///
/// Returns true if there was an error, false otherwise.
-bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
- bool MergeTypeWithOld) {
+bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
+ Scope *S, bool MergeTypeWithOld) {
// Verify the old decl was also a function.
- FunctionDecl *Old = 0;
- if (FunctionTemplateDecl *OldFunctionTemplate
- = dyn_cast<FunctionTemplateDecl>(OldD))
- Old = OldFunctionTemplate->getTemplatedDecl();
- else
- Old = dyn_cast<FunctionDecl>(OldD);
+ FunctionDecl *Old = OldD->getAsFunction();
if (!Old) {
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) {
if (New->getFriendObjectKind()) {
@@ -2318,18 +2267,34 @@
return true;
}
- Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
- Diag(Shadow->getTargetDecl()->getLocation(),
- diag::note_using_decl_target);
- Diag(Shadow->getUsingDecl()->getLocation(),
- diag::note_using_decl) << 0;
+ // C++11 [namespace.udecl]p14:
+ // If a function declaration in namespace scope or block scope has the
+ // same name and the same parameter-type-list as a function introduced
+ // by a using-declaration, and the declarations do not declare the same
+ // function, the program is ill-formed.
+
+ // Check whether the two declarations might declare the same function.
+ Old = dyn_cast<FunctionDecl>(Shadow->getTargetDecl());
+ if (Old &&
+ !Old->getDeclContext()->getRedeclContext()->Equals(
+ New->getDeclContext()->getRedeclContext()) &&
+ !(Old->isExternC() && New->isExternC()))
+ Old = 0;
+
+ if (!Old) {
+ Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
+ Diag(Shadow->getTargetDecl()->getLocation(),
+ diag::note_using_decl_target);
+ Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
+ return true;
+ }
+ OldD = Old;
+ } else {
+ Diag(New->getLocation(), diag::err_redefinition_different_kind)
+ << New->getDeclName();
+ Diag(OldD->getLocation(), diag::note_previous_definition);
return true;
}
-
- Diag(New->getLocation(), diag::err_redefinition_different_kind)
- << New->getDeclName();
- Diag(OldD->getLocation(), diag::note_previous_definition);
- return true;
}
// If the old declaration is invalid, just give up here.
@@ -2339,11 +2304,14 @@
// Determine whether the previous declaration was a definition,
// implicit declaration, or a declaration.
diag::kind PrevDiag;
+ SourceLocation OldLocation = Old->getLocation();
if (Old->isThisDeclarationADefinition())
PrevDiag = diag::note_previous_definition;
- else if (Old->isImplicit())
+ else if (Old->isImplicit()) {
PrevDiag = diag::note_previous_implicit_declaration;
- else
+ if (OldLocation.isInvalid())
+ OldLocation = New->getLocation();
+ } else
PrevDiag = diag::note_previous_declaration;
// Don't complain about this if we're in GNU89 mode and the old function
@@ -2357,10 +2325,10 @@
!canRedefineFunction(Old, getLangOpts())) {
if (getLangOpts().MicrosoftExt) {
Diag(New->getLocation(), diag::warn_static_non_static) << New;
- Diag(Old->getLocation(), PrevDiag);
+ Diag(OldLocation, PrevDiag);
} else {
Diag(New->getLocation(), diag::err_static_non_static) << New;
- Diag(Old->getLocation(), PrevDiag);
+ Diag(OldLocation, PrevDiag);
return true;
}
}
@@ -2426,7 +2394,7 @@
Diag(New->getLocation(), diag::err_regparm_mismatch)
<< NewType->getRegParmType()
<< OldType->getRegParmType();
- Diag(Old->getLocation(), diag::note_previous_declaration);
+ Diag(OldLocation, diag::note_previous_declaration);
return true;
}
@@ -2438,7 +2406,7 @@
if (OldTypeInfo.getProducesResult() != NewTypeInfo.getProducesResult()) {
if (NewTypeInfo.getProducesResult()) {
Diag(New->getLocation(), diag::err_returns_retained_mismatch);
- Diag(Old->getLocation(), diag::note_previous_declaration);
+ Diag(OldLocation, diag::note_previous_declaration);
return true;
}
@@ -2482,12 +2450,14 @@
// 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.
- QualType OldDeclaredReturnType = (Old->getTypeSourceInfo()
- ? Old->getTypeSourceInfo()->getType()->castAs<FunctionType>()
- : OldType)->getResultType();
- QualType NewDeclaredReturnType = (New->getTypeSourceInfo()
- ? New->getTypeSourceInfo()->getType()->castAs<FunctionType>()
- : NewType)->getResultType();
+ QualType OldDeclaredReturnType =
+ (Old->getTypeSourceInfo()
+ ? Old->getTypeSourceInfo()->getType()->castAs<FunctionType>()
+ : OldType)->getReturnType();
+ QualType NewDeclaredReturnType =
+ (New->getTypeSourceInfo()
+ ? New->getTypeSourceInfo()->getType()->castAs<FunctionType>()
+ : NewType)->getReturnType();
QualType ResQT;
if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType) &&
!((NewQType->isDependentType() || OldQType->isDependentType()) &&
@@ -2501,19 +2471,19 @@
diag::err_member_def_does_not_match_ret_type) << New;
else
Diag(New->getLocation(), diag::err_ovl_diff_return_type);
- Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+ Diag(OldLocation, PrevDiag) << Old << Old->getType();
return true;
}
else
NewQType = ResQT;
}
- QualType OldReturnType = OldType->getResultType();
- QualType NewReturnType = cast<FunctionType>(NewQType)->getResultType();
+ QualType OldReturnType = OldType->getReturnType();
+ QualType NewReturnType = cast<FunctionType>(NewQType)->getReturnType();
if (OldReturnType != NewReturnType) {
// If this function has a deduced return type and has already been
// defined, copy the deduced value from the old declaration.
- AutoType *OldAT = Old->getResultType()->getContainedAutoType();
+ AutoType *OldAT = Old->getReturnType()->getContainedAutoType();
if (OldAT && OldAT->isDeduced()) {
New->setType(
SubstAutoType(New->getType(),
@@ -2533,8 +2503,8 @@
NewMethod->setTrivial(OldMethod->isTrivial());
// MSVC allows explicit template specialization at class scope:
- // 2 CXMethodDecls referring to the same function will be injected.
- // We don't want a redeclartion error.
+ // 2 CXXMethodDecls referring to the same function will be injected.
+ // We don't want a redeclaration error.
bool IsClassScopeExplicitSpecialization =
OldMethod->isFunctionTemplateSpecialization() &&
NewMethod->isFunctionTemplateSpecialization();
@@ -2547,7 +2517,7 @@
// is a static member function declaration.
if (OldMethod->isStatic() != NewMethod->isStatic()) {
Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
- Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+ Diag(OldLocation, PrevDiag) << Old << Old->getType();
return true;
}
@@ -2571,7 +2541,7 @@
Diag(New->getLocation(), diag::err_member_redeclared_in_instantiation)
<< New << New->getType();
}
- Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+ Diag(OldLocation, PrevDiag) << Old << Old->getType();
// Complain if this is an explicit declaration of a special
// member that was initially declared implicitly.
@@ -2599,10 +2569,9 @@
// The first declaration of a function shall specify the noreturn
// attribute if any declaration of that function specifies the noreturn
// attribute.
- if (New->hasAttr<CXX11NoReturnAttr>() &&
- !Old->hasAttr<CXX11NoReturnAttr>()) {
- Diag(New->getAttr<CXX11NoReturnAttr>()->getLocation(),
- diag::err_noreturn_missing_on_first_decl);
+ const CXX11NoReturnAttr *NRA = New->getAttr<CXX11NoReturnAttr>();
+ if (NRA && !Old->hasAttr<CXX11NoReturnAttr>()) {
+ Diag(NRA->getLocation(), diag::err_noreturn_missing_on_first_decl);
Diag(Old->getFirstDecl()->getLocation(),
diag::note_noreturn_missing_first_decl);
}
@@ -2611,9 +2580,9 @@
// The first declaration of a function shall specify the
// carries_dependency attribute for its declarator-id if any declaration
// of the function specifies the carries_dependency attribute.
- if (New->hasAttr<CarriesDependencyAttr>() &&
- !Old->hasAttr<CarriesDependencyAttr>()) {
- Diag(New->getAttr<CarriesDependencyAttr>()->getLocation(),
+ const CarriesDependencyAttr *CDA = New->getAttr<CarriesDependencyAttr>();
+ if (CDA && !Old->hasAttr<CarriesDependencyAttr>()) {
+ Diag(CDA->getLocation(),
diag::err_carries_dependency_missing_on_first_decl) << 0/*Function*/;
Diag(Old->getFirstDecl()->getLocation(),
diag::note_carries_dependency_missing_first_decl) << 0/*Function*/;
@@ -2645,10 +2614,10 @@
// 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);
+ Diag(OldLocation, PrevDiag);
} else {
Diag(New->getLocation(), diag::err_different_language_linkage) << New;
- Diag(Old->getLocation(), PrevDiag);
+ Diag(OldLocation, PrevDiag);
return true;
}
}
@@ -2679,26 +2648,19 @@
// The old declaration provided a function prototype, but the
// new declaration does not. Merge in the prototype.
assert(!OldProto->hasExceptionSpec() && "Exception spec in C");
- SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(),
- OldProto->arg_type_end());
- NewQType = Context.getFunctionType(NewFuncType->getResultType(),
- ParamTypes,
- OldProto->getExtProtoInfo());
+ SmallVector<QualType, 16> ParamTypes(OldProto->param_types());
+ NewQType =
+ Context.getFunctionType(NewFuncType->getReturnType(), ParamTypes,
+ OldProto->getExtProtoInfo());
New->setType(NewQType);
New->setHasInheritedPrototype();
// Synthesize a parameter for each argument type.
SmallVector<ParmVarDecl*, 16> Params;
- for (FunctionProtoType::arg_type_iterator
- ParamType = OldProto->arg_type_begin(),
- ParamEnd = OldProto->arg_type_end();
- ParamType != ParamEnd; ++ParamType) {
- ParmVarDecl *Param = ParmVarDecl::Create(Context, New,
- SourceLocation(),
- SourceLocation(), 0,
- *ParamType, /*TInfo=*/0,
- SC_None,
- 0);
+ for (const auto &ParamType : OldProto->param_types()) {
+ ParmVarDecl *Param = ParmVarDecl::Create(Context, New, SourceLocation(),
+ SourceLocation(), 0, ParamType,
+ /*TInfo=*/0, SC_None, 0);
Param->setScopeInfo(0, Params.size());
Param->setImplicit();
Params.push_back(Param);
@@ -2733,21 +2695,21 @@
= New->getType()->getAs<FunctionProtoType>();
// Determine whether this is the GNU C extension.
- QualType MergedReturn = Context.mergeTypes(OldProto->getResultType(),
- NewProto->getResultType());
+ QualType MergedReturn = Context.mergeTypes(OldProto->getReturnType(),
+ NewProto->getReturnType());
bool LooseCompatible = !MergedReturn.isNull();
for (unsigned Idx = 0, End = Old->getNumParams();
LooseCompatible && Idx != End; ++Idx) {
ParmVarDecl *OldParm = Old->getParamDecl(Idx);
ParmVarDecl *NewParm = New->getParamDecl(Idx);
if (Context.typesAreCompatible(OldParm->getType(),
- NewProto->getArgType(Idx))) {
+ NewProto->getParamType(Idx))) {
ArgTypes.push_back(NewParm->getType());
} else if (Context.typesAreCompatible(OldParm->getType(),
NewParm->getType(),
/*CompareUnqualified=*/true)) {
- GNUCompatibleParamWarning Warn
- = { OldParm, NewParm, NewProto->getArgType(Idx) };
+ GNUCompatibleParamWarning Warn = { OldParm, NewParm,
+ NewProto->getParamType(Idx) };
Warnings.push_back(Warn);
ArgTypes.push_back(NewParm->getType());
} else
@@ -2785,7 +2747,7 @@
// or 'printf', just warn about the incompatible redeclaration.
if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New;
- Diag(Old->getLocation(), diag::note_previous_builtin_declaration)
+ Diag(OldLocation, diag::note_previous_builtin_declaration)
<< Old << Old->getType();
// If this is a global redeclaration, just forget hereafter
@@ -2806,7 +2768,7 @@
}
Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName();
- Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+ Diag(OldLocation, PrevDiag) << Old << Old->getType();
return true;
}
@@ -3003,14 +2965,17 @@
if (New->isInvalidDecl())
return;
+ VarTemplateDecl *NewTemplate = New->getDescribedVarTemplate();
+
// Verify the old decl was also a variable or variable template.
VarDecl *Old = 0;
- if (Previous.isSingleResult() &&
- (Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
- if (New->getDescribedVarTemplate())
- Old = Old->getDescribedVarTemplate() ? Old : 0;
- else
- Old = Old->getDescribedVarTemplate() ? 0 : Old;
+ VarTemplateDecl *OldTemplate = 0;
+ if (Previous.isSingleResult()) {
+ if (NewTemplate) {
+ OldTemplate = dyn_cast<VarTemplateDecl>(Previous.getFoundDecl());
+ Old = OldTemplate ? OldTemplate->getTemplatedDecl() : 0;
+ } else
+ Old = dyn_cast<VarDecl>(Previous.getFoundDecl());
}
if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
@@ -3023,6 +2988,13 @@
if (!shouldLinkPossiblyHiddenDecl(Old, New))
return;
+ // Ensure the template parameters are compatible.
+ if (NewTemplate &&
+ !TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
+ OldTemplate->getTemplateParameters(),
+ /*Complain=*/true, TPL_TemplateMatch))
+ return;
+
// C++ [class.mem]p1:
// A member shall not be declared twice in the member-specification [...]
//
@@ -3037,9 +3009,9 @@
mergeDeclAttributes(New, Old);
// Warn if an already-declared variable is made a weak_import in a subsequent
// declaration
- if (New->getAttr<WeakImportAttr>() &&
+ if (New->hasAttr<WeakImportAttr>() &&
Old->getStorageClass() == SC_None &&
- !Old->getAttr<WeakImportAttr>()) {
+ !Old->hasAttr<WeakImportAttr>()) {
Diag(New->getLocation(), diag::warn_weak_import) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
// Remove weak_import attribute on new declaration.
@@ -3148,14 +3120,13 @@
// Keep a chain of previous declarations.
New->setPreviousDecl(Old);
+ if (NewTemplate)
+ NewTemplate->setPreviousDecl(OldTemplate);
// Inherit access appropriately.
New->setAccess(Old->getAccess());
-
- if (VarTemplateDecl *VTD = New->getDescribedVarTemplate()) {
- if (New->isStaticDataMember() && New->isOutOfLine())
- VTD->setAccess(New->getAccess());
- }
+ if (NewTemplate)
+ NewTemplate->setAccess(New->getAccess());
}
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
@@ -3165,7 +3136,7 @@
return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg());
}
-static void HandleTagNumbering(Sema &S, const TagDecl *Tag) {
+static void HandleTagNumbering(Sema &S, const TagDecl *Tag, Scope *TagScope) {
if (!S.Context.getLangOpts().CPlusPlus)
return;
@@ -3176,7 +3147,8 @@
return;
MangleNumberingContext &MCtx =
S.Context.getManglingNumberContext(Tag->getParent());
- S.Context.setManglingNumber(Tag, MCtx.getManglingNumber(Tag));
+ S.Context.setManglingNumber(
+ Tag, MCtx.getManglingNumber(Tag, TagScope->getMSLocalManglingNumber()));
return;
}
@@ -3185,7 +3157,9 @@
if (MangleNumberingContext *MCtx =
S.getCurrentMangleNumberContext(Tag->getDeclContext(),
ManglingContextDecl)) {
- S.Context.setManglingNumber(Tag, MCtx->getManglingNumber(Tag));
+ S.Context.setManglingNumber(
+ Tag,
+ MCtx->getManglingNumber(Tag, TagScope->getMSLocalManglingNumber()));
}
}
@@ -3218,7 +3192,7 @@
}
if (Tag) {
- HandleTagNumbering(*this, Tag);
+ HandleTagNumbering(*this, Tag, S);
Tag->setFreeStanding();
if (Tag->isInvalidDecl())
return Tag;
@@ -3285,7 +3259,7 @@
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
if (getLangOpts().CPlusPlus ||
Record->getDeclContext()->isRecord())
- return BuildAnonymousStructOrUnion(S, DS, AS, Record);
+ return BuildAnonymousStructOrUnion(S, DS, AS, Record, Context.getPrintingPolicy());
DeclaresAnything = false;
}
@@ -3471,12 +3445,10 @@
bool Invalid = false;
// Look every FieldDecl and IndirectFieldDecl with a name.
- for (RecordDecl::decl_iterator D = AnonRecord->decls_begin(),
- DEnd = AnonRecord->decls_end();
- D != DEnd; ++D) {
- if ((isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) &&
- cast<NamedDecl>(*D)->getDeclName()) {
- ValueDecl *VD = cast<ValueDecl>(*D);
+ for (auto *D : AnonRecord->decls()) {
+ if ((isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) &&
+ cast<NamedDecl>(D)->getDeclName()) {
+ ValueDecl *VD = cast<ValueDecl>(D);
if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, VD->getDeclName(),
VD->getLocation(), diagKind)) {
// C++ [class.union]p2:
@@ -3492,9 +3464,8 @@
// anonymous union is declared.
unsigned OldChainingSize = Chaining.size();
if (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(VD))
- for (IndirectFieldDecl::chain_iterator PI = IF->chain_begin(),
- PE = IF->chain_end(); PI != PE; ++PI)
- Chaining.push_back(*PI);
+ for (auto *PI : IF->chain())
+ Chaining.push_back(PI);
else
Chaining.push_back(VD);
@@ -3549,13 +3520,45 @@
llvm_unreachable("unknown storage class specifier");
}
+static SourceLocation findDefaultInitializer(const CXXRecordDecl *Record) {
+ assert(Record->hasInClassInitializer());
+
+ for (const auto *I : Record->decls()) {
+ const auto *FD = dyn_cast<FieldDecl>(I);
+ if (const auto *IFD = dyn_cast<IndirectFieldDecl>(I))
+ FD = IFD->getAnonField();
+ if (FD && FD->hasInClassInitializer())
+ return FD->getLocation();
+ }
+
+ llvm_unreachable("couldn't find in-class initializer");
+}
+
+static void checkDuplicateDefaultInit(Sema &S, CXXRecordDecl *Parent,
+ SourceLocation DefaultInitLoc) {
+ if (!Parent->isUnion() || !Parent->hasInClassInitializer())
+ return;
+
+ S.Diag(DefaultInitLoc, diag::err_multiple_mem_union_initialization);
+ S.Diag(findDefaultInitializer(Parent), diag::note_previous_initializer) << 0;
+}
+
+static void checkDuplicateDefaultInit(Sema &S, CXXRecordDecl *Parent,
+ CXXRecordDecl *AnonUnion) {
+ if (!Parent->isUnion() || !Parent->hasInClassInitializer())
+ return;
+
+ checkDuplicateDefaultInit(S, Parent, findDefaultInitializer(AnonUnion));
+}
+
/// BuildAnonymousStructOrUnion - Handle the declaration of an
/// anonymous structure or union. Anonymous unions are a C++ feature
/// (C++ [class.union]) and a C11 feature; anonymous structures
/// are a C11 feature and GNU C++ extension.
Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
- AccessSpecifier AS,
- RecordDecl *Record) {
+ AccessSpecifier AS,
+ RecordDecl *Record,
+ const PrintingPolicy &Policy) {
DeclContext *Owner = Record->getDeclContext();
// Diagnose whether this anonymous struct/union is an extension.
@@ -3585,7 +3588,7 @@
// Recover by adding 'static'.
DS.SetStorageClassSpec(*this, DeclSpec::SCS_static, SourceLocation(),
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Policy);
}
// C++ [class.union]p6:
// A storage class is not allowed in a declaration of an
@@ -3599,7 +3602,7 @@
// Recover by removing the storage specifier.
DS.SetStorageClassSpec(*this, DeclSpec::SCS_unspecified,
SourceLocation(),
- PrevSpec, DiagID);
+ PrevSpec, DiagID, Context.getPrintingPolicy());
}
}
@@ -3632,10 +3635,8 @@
// The member-specification of an anonymous union shall only
// define non-static data members. [Note: nested types and
// functions cannot be declared within an anonymous union. ]
- for (DeclContext::decl_iterator Mem = Record->decls_begin(),
- MemEnd = Record->decls_end();
- Mem != MemEnd; ++Mem) {
- if (FieldDecl *FD = dyn_cast<FieldDecl>(*Mem)) {
+ for (auto *Mem : Record->decls()) {
+ if (auto *FD = dyn_cast<FieldDecl>(Mem)) {
// C++ [class.union]p3:
// An anonymous union shall not have private or protected
// members (clause 11).
@@ -3653,14 +3654,14 @@
// array of such objects.
if (CheckNontrivialField(FD))
Invalid = true;
- } else if ((*Mem)->isImplicit()) {
+ } else if (Mem->isImplicit()) {
// Any implicit members are fine.
- } else if (isa<TagDecl>(*Mem) && (*Mem)->getDeclContext() != Record) {
+ } else if (isa<TagDecl>(Mem) && Mem->getDeclContext() != Record) {
// This is a type that showed up in an
// elaborated-type-specifier inside the anonymous struct or
// union, but which actually declares a type outside of the
// anonymous struct or union. It's okay.
- } else if (RecordDecl *MemRecord = dyn_cast<RecordDecl>(*Mem)) {
+ } else if (auto *MemRecord = dyn_cast<RecordDecl>(Mem)) {
if (!MemRecord->isAnonymousStructOrUnion() &&
MemRecord->getDeclName()) {
// Visual C++ allows type definition in anonymous struct or union.
@@ -3681,31 +3682,39 @@
diag::ext_anonymous_record_with_anonymous_type)
<< (int)Record->isUnion();
}
- } else if (isa<AccessSpecDecl>(*Mem)) {
+ } else if (isa<AccessSpecDecl>(Mem)) {
// Any access specifier is fine.
} else {
// We have something that isn't a non-static data
// member. Complain about it.
unsigned DK = diag::err_anonymous_record_bad_member;
- if (isa<TypeDecl>(*Mem))
+ if (isa<TypeDecl>(Mem))
DK = diag::err_anonymous_record_with_type;
- else if (isa<FunctionDecl>(*Mem))
+ else if (isa<FunctionDecl>(Mem))
DK = diag::err_anonymous_record_with_function;
- else if (isa<VarDecl>(*Mem))
+ else if (isa<VarDecl>(Mem))
DK = diag::err_anonymous_record_with_static;
// Visual C++ allows type definition in anonymous struct or union.
if (getLangOpts().MicrosoftExt &&
DK == diag::err_anonymous_record_with_type)
- Diag((*Mem)->getLocation(), diag::ext_anonymous_record_with_type)
+ Diag(Mem->getLocation(), diag::ext_anonymous_record_with_type)
<< (int)Record->isUnion();
else {
- Diag((*Mem)->getLocation(), DK)
+ Diag(Mem->getLocation(), DK)
<< (int)Record->isUnion();
Invalid = true;
}
}
}
+
+ // C++11 [class.union]p8 (DR1460):
+ // At most one variant member of a union may have a
+ // brace-or-equal-initializer.
+ if (cast<CXXRecordDecl>(Record)->hasInClassInitializer() &&
+ Owner->isRecord())
+ checkDuplicateDefaultInit(*this, cast<CXXRecordDecl>(Owner),
+ cast<CXXRecordDecl>(Record));
}
if (!Record->isUnion() && !Owner->isRecord()) {
@@ -3758,11 +3767,14 @@
}
Anon->setImplicit();
+ // Mark this as an anonymous struct/union type.
+ Record->setAnonymousStructOrUnion(true);
+
// Add the anonymous struct/union object to the current
// context. We'll be referencing this object when we refer to one of
// its members.
Owner->addDecl(Anon);
-
+
// Inject the members of the anonymous struct/union into the owning
// context and into the identifier resolver chain for name lookup
// purposes.
@@ -3773,13 +3785,17 @@
Chain, false))
Invalid = true;
- // Mark this as an anonymous struct/union type. Note that we do not
- // do this until after we have already checked and injected the
- // members of this anonymous struct/union type, because otherwise
- // the members could be injected twice: once by DeclContext when it
- // builds its lookup table, and once by
- // InjectAnonymousStructOrUnionMembers.
- Record->setAnonymousStructOrUnion(true);
+ if (VarDecl *NewVD = dyn_cast<VarDecl>(Anon)) {
+ if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) {
+ Decl *ManglingContextDecl;
+ if (MangleNumberingContext *MCtx =
+ getCurrentMangleNumberContext(NewVD->getDeclContext(),
+ ManglingContextDecl)) {
+ Context.setManglingNumber(NewVD, MCtx->getManglingNumber(NewVD, S->getMSLocalManglingNumber()));
+ Context.setStaticLocalNumber(NewVD, MCtx->getStaticLocalNumber(NewVD));
+ }
+ }
+ }
if (Invalid)
Anon->setInvalidDecl();
@@ -4117,33 +4133,31 @@
/// \returns true if we cannot safely recover from this error, false otherwise.
bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
DeclarationName Name,
- SourceLocation Loc) {
+ SourceLocation Loc) {
DeclContext *Cur = CurContext;
while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur))
Cur = Cur->getParent();
-
- // C++ [dcl.meaning]p1:
- // A declarator-id shall not be qualified except for the definition
- // of a member function (9.3) or static data member (9.4) outside of
- // its class, the definition or explicit instantiation of a function
- // or variable member of a namespace outside of its namespace, or the
- // definition of an explicit specialization outside of its namespace,
- // or the declaration of a friend function that is a member of
- // another class or namespace (11.3). [...]
-
- // The user provided a superfluous scope specifier that refers back to the
- // class or namespaces in which the entity is already declared.
+
+ // If the user provided a superfluous scope specifier that refers back to the
+ // class in which the entity is already declared, diagnose and ignore it.
//
// class X {
// void X::f();
// };
+ //
+ // Note, it was once ill-formed to give redundant qualification in all
+ // contexts, but that rule was removed by DR482.
if (Cur->Equals(DC)) {
- Diag(Loc, LangOpts.MicrosoftExt? diag::warn_member_extra_qualification
- : diag::err_member_extra_qualification)
- << Name << FixItHint::CreateRemoval(SS.getRange());
- SS.clear();
+ if (Cur->isRecord()) {
+ Diag(Loc, LangOpts.MicrosoftExt ? diag::warn_member_extra_qualification
+ : diag::err_member_extra_qualification)
+ << Name << FixItHint::CreateRemoval(SS.getRange());
+ SS.clear();
+ } else {
+ Diag(Loc, diag::warn_namespace_member_extra_qualification) << Name;
+ }
return false;
- }
+ }
// Check whether the qualifying scope encloses the scope of the original
// declaration.
@@ -4239,7 +4253,7 @@
// and return early, to avoid the coming semantic disaster.
Diag(D.getIdentifierLoc(),
diag::err_template_qualified_declarator_no_match)
- << (NestedNameSpecifier*)D.getCXXScopeSpec().getScopeRep()
+ << D.getCXXScopeSpec().getScopeRep()
<< D.getCXXScopeSpec().getRange();
return 0;
}
@@ -4670,8 +4684,8 @@
LookupResult &Previous, bool &Redeclaration) {
// Merge the decl with the existing one if appropriate. If the decl is
// in an outer scope, it isn't the same thing.
- FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/ false,
- /*ExplicitInstantiationOrSpecialization=*/false);
+ FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/false,
+ /*AllowInlineNamespace*/false);
filterNonConflictingPreviousDecls(Context, NewTD, Previous);
if (!Previous.empty()) {
Redeclaration = true;
@@ -4804,6 +4818,10 @@
}
static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
+ // Ensure that an auto decl is deduced otherwise the checks below might cache
+ // the wrong linkage.
+ assert(S.ParsingInitForAutoVars.count(&ND) == 0);
+
// 'weak' only applies to declarations with external linkage.
if (WeakAttr *Attr = ND.getAttr<WeakAttr>()) {
if (!ND.isExternallyVisible()) {
@@ -4826,6 +4844,72 @@
ND.dropAttr<SelectAnyAttr>();
}
}
+
+ // dll attributes require external linkage.
+ if (const DLLImportAttr *Attr = ND.getAttr<DLLImportAttr>()) {
+ if (!ND.isExternallyVisible()) {
+ S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern)
+ << &ND << Attr;
+ ND.setInvalidDecl();
+ }
+ }
+ if (const DLLExportAttr *Attr = ND.getAttr<DLLExportAttr>()) {
+ if (!ND.isExternallyVisible()) {
+ S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern)
+ << &ND << Attr;
+ ND.setInvalidDecl();
+ }
+ }
+}
+
+static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
+ NamedDecl *NewDecl,
+ bool IsSpecialization) {
+ if (TemplateDecl *OldTD = dyn_cast<TemplateDecl>(OldDecl))
+ OldDecl = OldTD->getTemplatedDecl();
+ if (TemplateDecl *NewTD = dyn_cast<TemplateDecl>(NewDecl))
+ NewDecl = NewTD->getTemplatedDecl();
+
+ if (!OldDecl || !NewDecl)
+ return;
+
+ const DLLImportAttr *OldImportAttr = OldDecl->getAttr<DLLImportAttr>();
+ const DLLExportAttr *OldExportAttr = OldDecl->getAttr<DLLExportAttr>();
+ const DLLImportAttr *NewImportAttr = NewDecl->getAttr<DLLImportAttr>();
+ const DLLExportAttr *NewExportAttr = NewDecl->getAttr<DLLExportAttr>();
+
+ // dllimport and dllexport are inheritable attributes so we have to exclude
+ // inherited attribute instances.
+ bool HasNewAttr = (NewImportAttr && !NewImportAttr->isInherited()) ||
+ (NewExportAttr && !NewExportAttr->isInherited());
+
+ // A redeclaration is not allowed to add a dllimport or dllexport attribute,
+ // the only exception being explicit specializations.
+ // Implicitly generated declarations are also excluded for now because there
+ // is no other way to switch these to use dllimport or dllexport.
+ bool AddsAttr = !(OldImportAttr || OldExportAttr) && HasNewAttr;
+ if (AddsAttr && !IsSpecialization && !OldDecl->isImplicit()) {
+ S.Diag(NewDecl->getLocation(), diag::err_attribute_dll_redeclaration)
+ << NewDecl
+ << (NewImportAttr ? (const Attr *)NewImportAttr : NewExportAttr);
+ S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+ NewDecl->setInvalidDecl();
+ return;
+ }
+
+ // A redeclaration is not allowed to drop a dllimport attribute, the only
+ // exception being inline function definitions.
+ // FIXME: Handle inline functions.
+ // NB: MSVC converts such a declaration to dllexport.
+ if (OldImportAttr && !HasNewAttr) {
+ S.Diag(NewDecl->getLocation(),
+ diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
+ << NewDecl << OldImportAttr;
+ S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+ S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute);
+ OldDecl->dropAttr<DLLImportAttr>();
+ NewDecl->dropAttr<DLLImportAttr>();
+ }
}
/// Given that we are within the definition of the given function,
@@ -4906,6 +4990,31 @@
llvm_unreachable("Unexpected context");
}
+static bool hasParsedAttr(Scope *S, const AttributeList *AttrList,
+ AttributeList::Kind Kind) {
+ for (const AttributeList *L = AttrList; L; L = L->getNext())
+ if (L->getKind() == Kind)
+ return true;
+ return false;
+}
+
+static bool hasParsedAttr(Scope *S, const Declarator &PD,
+ AttributeList::Kind Kind) {
+ // Check decl attributes on the DeclSpec.
+ if (hasParsedAttr(S, PD.getDeclSpec().getAttributes().getList(), Kind))
+ return true;
+
+ // Walk the declarator structure, checking decl attributes that were in a type
+ // position to the decl itself.
+ for (unsigned I = 0, E = PD.getNumTypeObjects(); I != E; ++I) {
+ if (hasParsedAttr(S, PD.getTypeObject(I).getAttrs(), Kind))
+ return true;
+ }
+
+ // Finally, check attributes on the decl itself.
+ return hasParsedAttr(S, PD.getAttributes(), Kind);
+}
+
/// Adjust the \c DeclContext for a function or variable that might be a
/// function-local external declaration.
bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) {
@@ -4942,16 +5051,35 @@
VarDecl::StorageClass SC =
StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
+ // dllimport globals without explicit storage class are treated as extern. We
+ // have to change the storage class this early to get the right DeclContext.
+ if (SC == SC_None && !DC->isRecord() &&
+ hasParsedAttr(S, D, AttributeList::AT_DLLImport))
+ SC = SC_Extern;
+
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).
- if (Context.getBaseElementType(R)->isHalfType()) {
- Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R;
- D.setInvalidType();
+ if (getLangOpts().OpenCL) {
+ // OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
+ QualType NR = R;
+ while (NR->isPointerType()) {
+ if (NR->isFunctionPointerType()) {
+ Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer_variable);
+ D.setInvalidType();
+ break;
+ }
+ NR = NR->getPointeeType();
+ }
+
+ if (!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).
+ if (Context.getBaseElementType(R)->isHalfType()) {
+ Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R;
+ D.setInvalidType();
+ }
}
}
@@ -5033,9 +5161,9 @@
bool IsVariableTemplateSpecialization = false;
bool IsPartialSpecialization = false;
bool IsVariableTemplate = false;
- VarTemplateDecl *PrevVarTemplate = 0;
VarDecl *NewVD = 0;
VarTemplateDecl *NewTemplate = 0;
+ TemplateParameterList *TemplateParams = 0;
if (!getLangOpts().CPlusPlus) {
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II,
@@ -5097,104 +5225,15 @@
}
}
- 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.
- 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(),
- diag::err_template_variable_noparams)
- << 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);
+ TemplateParams = MatchTemplateParametersToScopeSpecifier(
+ D.getDeclSpec().getLocStart(), D.getIdentifierLoc(),
+ D.getCXXScopeSpec(), TemplateParamLists,
+ /*never a friend*/ false, IsExplicitSpecialization, Invalid);
- 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) {
+ if (D.getName().getKind() == UnqualifiedId::IK_TemplateId &&
+ !TemplateParams) {
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
// We have encountered something that the user meant to be a
@@ -5207,22 +5246,53 @@
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
<< FixItHint::CreateInsertion(D.getDeclSpec().getLocStart(),
"template<> ");
- IsVariableTemplateSpecialization = true;
+ IsExplicitSpecialization = true;
+ TemplateParams = TemplateParameterList::Create(Context, SourceLocation(),
+ SourceLocation(), 0, 0,
+ SourceLocation());
+ }
+
+ 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(),
+ diag::err_template_variable_noparams)
+ << II
+ << SourceRange(TemplateParams->getTemplateLoc(),
+ TemplateParams->getRAngleLoc());
+ TemplateParams = 0;
+ } 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.
+ // FIXME: 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 (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,
+ S, D, TInfo, TemplateKWLoc, TemplateParams, SC,
IsPartialSpecialization);
if (Res.isInvalid())
return 0;
@@ -5236,7 +5306,7 @@
if (IsVariableTemplate) {
NewTemplate =
VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name,
- TemplateParams, NewVD, PrevVarTemplate);
+ TemplateParams, NewVD);
NewVD->setDescribedVarTemplate(NewTemplate);
}
@@ -5253,18 +5323,13 @@
SetNestedNameSpecifier(NewVD, D);
- // FIXME: Do we need D.getCXXScopeSpec().isSet()?
- if (TemplateParams && TemplateParamLists.size() > 1 &&
- (!IsVariableTemplateSpecialization || D.getCXXScopeSpec().isSet())) {
+ // If we have any template parameter lists that don't directly belong to
+ // the variable (matching the scope specifier), store them.
+ unsigned VDTemplateParamLists = TemplateParams ? 1 : 0;
+ if (TemplateParamLists.size() > VDTemplateParamLists)
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());
- }
+ Context, TemplateParamLists.size() - VDTemplateParamLists,
+ TemplateParamLists.data());
if (D.getDeclSpec().isConstexprSpecified())
NewVD->setConstexpr(true);
@@ -5346,9 +5411,6 @@
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewVD, D);
- if (NewVD->hasAttrs())
- CheckAlignasUnderalignment(NewVD);
-
if (getLangOpts().CUDA) {
// CUDA B.2.5: "__shared__ and __constant__ variables have implied static
// storage [duration]."
@@ -5359,6 +5421,13 @@
}
}
+ // Ensure that dllimport globals without explicit storage class are treated as
+ // extern. The storage class is set above using parsed attributes. Now we can
+ // check the VarDecl itself.
+ assert(!NewVD->hasAttr<DLLImportAttr>() ||
+ NewVD->getAttr<DLLImportAttr>()->isInherited() ||
+ NewVD->isStaticDataMember() || NewVD->getStorageClass() != SC_None);
+
// In auto-retain/release, infer strong retension for variables of
// retainable type.
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewVD))
@@ -5388,7 +5457,7 @@
}
NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
- Context, Label));
+ Context, Label, 0));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
@@ -5399,15 +5468,16 @@
}
// Diagnose shadowed variables before filtering for scope.
- if (!D.getCXXScopeSpec().isSet())
+ if (D.getCXXScopeSpec().isEmpty())
CheckShadow(S, NewVD, Previous);
// 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, OriginalDC, S, shouldConsiderLinkage(NewVD),
- IsExplicitSpecialization || IsVariableTemplateSpecialization);
+ FilterLookupForScope(Previous, OriginalDC, S, shouldConsiderLinkage(NewVD),
+ D.getCXXScopeSpec().isNotEmpty() ||
+ 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.
@@ -5420,6 +5490,11 @@
if (!getLangOpts().CPlusPlus) {
D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
} else {
+ // If this is an explicit specialization of a static data member, check it.
+ if (IsExplicitSpecialization && !NewVD->isInvalidDecl() &&
+ CheckMemberSpecialization(NewVD, Previous))
+ NewVD->setInvalidDecl();
+
// Merge the decl with the existing one if appropriate.
if (!Previous.empty()) {
if (Previous.isSingleResult() &&
@@ -5440,24 +5515,37 @@
NewVD->setInvalidDecl();
}
- 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));
- }
+ if (!IsVariableTemplateSpecialization)
+ D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
- // This is an explicit specialization of a static data member. Check it.
- if (IsExplicitSpecialization && !NewVD->isInvalidDecl() &&
- CheckMemberSpecialization(NewVD, Previous))
- NewVD->setInvalidDecl();
+ if (NewTemplate) {
+ VarTemplateDecl *PrevVarTemplate =
+ NewVD->getPreviousDecl()
+ ? NewVD->getPreviousDecl()->getDescribedVarTemplate()
+ : 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))
+ NewVD->setInvalidDecl();
+
+ // If we are providing an explicit specialization of a static variable
+ // template, make a note of that.
+ if (PrevVarTemplate &&
+ PrevVarTemplate->getInstantiatedFromMemberTemplate())
+ PrevVarTemplate->setMemberSpecialization();
+ }
}
ProcessPragmaWeak(S, NewVD);
- checkAttributesAfterMerging(*this, *NewVD);
// If this is the first declaration of an extern C variable, update
// the map of such variables.
@@ -5470,16 +5558,21 @@
if (MangleNumberingContext *MCtx =
getCurrentMangleNumberContext(NewVD->getDeclContext(),
ManglingContextDecl)) {
- Context.setManglingNumber(NewVD, MCtx->getManglingNumber(NewVD));
+ Context.setManglingNumber(
+ NewVD, MCtx->getManglingNumber(NewVD, S->getMSLocalManglingNumber()));
+ Context.setStaticLocalNumber(NewVD, MCtx->getStaticLocalNumber(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 (D.isRedeclaration() && !Previous.empty()) {
+ checkDLLAttributeRedeclaration(
+ *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD,
+ IsExplicitSpecialization);
+ }
if (NewTemplate) {
+ if (NewVD->isInvalidDecl())
+ NewTemplate->setInvalidDecl();
ActOnDocumentableDecl(NewTemplate);
return NewTemplate;
}
@@ -5526,11 +5619,9 @@
if (shadowedVar->isExternC()) {
// For shadowing external vars, make sure that we point to the global
// declaration, not a locally scoped extern declaration.
- for (VarDecl::redecl_iterator
- I = shadowedVar->redecls_begin(), E = shadowedVar->redecls_end();
- I != E; ++I)
+ for (auto I : shadowedVar->redecls())
if (I->isFileVarDecl()) {
- ShadowedDecl = *I;
+ ShadowedDecl = I;
break;
}
}
@@ -5566,6 +5657,8 @@
DeclarationName Name = R.getLookupName();
// Emit warning and note.
+ if (getSourceManager().isInSystemMacro(R.getNameLoc()))
+ return;
Diag(R.getNameLoc(), diag::warn_decl_shadow) << Name << Kind << OldDC;
Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration);
}
@@ -5711,6 +5804,9 @@
if (T->isUndeducedType())
return;
+ if (NewVD->hasAttrs())
+ CheckAlignasUnderalignment(NewVD);
+
if (T->isObjCObjectType()) {
Diag(NewVD->getLocation(), diag::err_statically_allocated_object)
<< FixItHint::CreateInsertion(NewVD->getLocation(), "*");
@@ -5828,7 +5924,6 @@
if (NewVD->isConstexpr() && !T->isDependentType() &&
RequireLiteralType(NewVD->getLocation(), T,
diag::err_constexpr_var_non_literal)) {
- // Can't perform this check until the type is deduced.
NewVD->setInvalidDecl();
return;
}
@@ -5947,9 +6042,8 @@
bool hasNonDeletedOverridenMethods = false;
bool AddedAny = false;
if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) {
- for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(),
- E = Paths.found_decls_end(); I != E; ++I) {
- if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
+ for (auto *I : Paths.found_decls()) {
+ if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(I)) {
MD->addOverriddenMethod(OldMD->getCanonicalDecl());
if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
!CheckOverridingFunctionAttributes(MD, OldMD) &&
@@ -5995,7 +6089,7 @@
: Context(Context), OriginalFD(TypoFD),
ExpectedParent(Parent ? Parent->getCanonicalDecl() : 0) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
if (candidate.getEditDistance() == 0)
return false;
@@ -6254,10 +6348,9 @@
// For record types, this is done by the AbstractClassUsageDiagnoser once
// the class has been completely parsed.
if (!DC->isRecord() &&
- SemaRef.RequireNonAbstractType(D.getIdentifierLoc(),
- R->getAs<FunctionType>()->getResultType(),
- diag::err_abstract_type_in_decl,
- SemaRef.AbstractReturnType))
+ SemaRef.RequireNonAbstractType(
+ D.getIdentifierLoc(), R->getAs<FunctionType>()->getReturnType(),
+ diag::err_abstract_type_in_decl, SemaRef.AbstractReturnType))
D.setInvalidType();
if (Name.getNameKind() == DeclarationName::CXXConstructorName) {
@@ -6292,15 +6385,6 @@
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;
@@ -6363,26 +6447,11 @@
}
}
-void Sema::checkVoidParamDecl(ParmVarDecl *Param) {
- // In C++, the empty parameter-type-list must be spelled "void"; a
- // typedef of void is not permitted.
- if (getLangOpts().CPlusPlus &&
- Param->getType().getUnqualifiedType() != Context.VoidTy) {
- bool IsTypeAlias = false;
- if (const TypedefType *TT = Param->getType()->getAs<TypedefType>())
- IsTypeAlias = isa<TypeAliasDecl>(TT->getDecl());
- else if (const TemplateSpecializationType *TST =
- Param->getType()->getAs<TemplateSpecializationType>())
- IsTypeAlias = TST->isTypeAlias();
- Diag(Param->getLocation(), diag::err_param_typedef_of_void)
- << IsTypeAlias;
- }
-}
-
enum OpenCLParamType {
ValidKernelParam,
PtrPtrKernelParam,
PtrKernelParam,
+ PrivatePtrKernelParam,
InvalidKernelParam,
RecordKernelParam
};
@@ -6390,7 +6459,10 @@
static OpenCLParamType getOpenCLKernelParameterType(QualType PT) {
if (PT->isPointerType()) {
QualType PointeeType = PT->getPointeeType();
- return PointeeType->isPointerType() ? PtrPtrKernelParam : PtrKernelParam;
+ if (PointeeType->isPointerType())
+ return PtrPtrKernelParam;
+ return PointeeType.getAddressSpace() == 0 ? PrivatePtrKernelParam
+ : PtrKernelParam;
}
// TODO: Forbid the other integer types (size_t, ptrdiff_t...) when they can
@@ -6435,6 +6507,14 @@
D.setInvalidType();
return;
+ case PrivatePtrKernelParam:
+ // OpenCL v1.2 s6.9.a:
+ // A kernel function argument cannot be declared as a
+ // pointer to the private address space.
+ S.Diag(Param->getLocation(), diag::err_opencl_private_ptr_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
@@ -6495,9 +6575,7 @@
// 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;
+ for (const auto *FD : RD->fields()) {
QualType QT = FD->getType();
if (ValidTypes.count(QT.getTypePtr()))
@@ -6516,7 +6594,8 @@
// 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) {
+ if (ParamType == PtrKernelParam || ParamType == PtrPtrKernelParam ||
+ ParamType == PrivatePtrKernelParam) {
S.Diag(Param->getLocation(),
diag::err_record_with_pointers_kernel_param)
<< PT->isUnionType()
@@ -6742,14 +6821,14 @@
}
if (getLangOpts().CPlusPlus1y &&
- NewFD->getResultType()->isUndeducedType())
+ NewFD->getReturnType()->isUndeducedType())
Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual);
}
if (getLangOpts().CPlusPlus1y &&
(NewFD->isDependentContext() ||
(isFriend && CurContext->isDependentContext())) &&
- NewFD->getResultType()->isUndeducedType()) {
+ NewFD->getReturnType()->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
@@ -6758,9 +6837,9 @@
// 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(),
+ QualType Result =
+ SubstAutoType(FPT->getReturnType(), Context.DependentTy);
+ NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(),
FPT->getExtProtoInfo()));
}
@@ -6833,6 +6912,8 @@
}
// If a function is defined as defaulted or deleted, mark it as such now.
+ // FIXME: Does this ever happen? ActOnStartOfFunctionDef forces the function
+ // definition kind to FDK_Definition.
switch (D.getFunctionDefinitionKind()) {
case FDK_Declaration:
case FDK_Definition:
@@ -6878,13 +6959,14 @@
getLangOpts().CPlusPlus11 && FPT && !FPT->hasExceptionSpec()) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.ExceptionSpecType = EST_BasicNoexcept;
- NewFD->setType(Context.getFunctionType(FPT->getResultType(),
- FPT->getArgTypes(), EPI));
+ NewFD->setType(Context.getFunctionType(FPT->getReturnType(),
+ FPT->getParamTypes(), EPI));
}
}
// Filter out previous declarations that don't match the scope.
FilterLookupForScope(Previous, OriginalDC, S, shouldConsiderLinkage(NewFD),
+ D.getCXXScopeSpec().isNotEmpty() ||
isExplicitSpecialization ||
isFunctionTemplateSpecialization);
@@ -6893,7 +6975,7 @@
// The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E);
NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
- SE->getString()));
+ SE->getString(), 0));
} else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
@@ -6914,14 +6996,13 @@
// single void argument.
// We let through "const void" here because Sema::GetTypeForDeclarator
// already checks for that case.
- if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
- FTI.ArgInfo[0].Param &&
- cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
+ if (FTI.NumParams == 1 && !FTI.isVariadic && FTI.Params[0].Ident == 0 &&
+ FTI.Params[0].Param &&
+ cast<ParmVarDecl>(FTI.Params[0].Param)->getType()->isVoidType()) {
// Empty arg list, don't push any params.
- checkVoidParamDecl(cast<ParmVarDecl>(FTI.ArgInfo[0].Param));
- } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
- for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
- ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
+ } else if (FTI.NumParams > 0 && FTI.Params[0].Param != 0) {
+ for (unsigned i = 0, e = FTI.NumParams; i != e; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
assert(Param->getDeclContext() != NewFD && "Was set before ?");
Param->setDeclContext(NewFD);
Params.push_back(Param);
@@ -6942,10 +7023,9 @@
// @endcode
// Synthesize a parameter for each argument type.
- for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
- AE = FT->arg_type_end(); AI != AE; ++AI) {
+ for (const auto &AI : FT->param_types()) {
ParmVarDecl *Param =
- BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI);
+ BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), AI);
Param->setScopeInfo(0, Params.size());
Params.push_back(Param);
}
@@ -6969,12 +7049,12 @@
if (D.getDeclSpec().isNoreturnSpecified())
NewFD->addAttr(
::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(),
- Context));
+ Context, 0));
// Functions returning a variably modified type violate C99 6.7.5.2p2
// because all functions have linkage.
if (!NewFD->isInvalidDecl() &&
- NewFD->getResultType()->isVariablyModifiedType()) {
+ NewFD->getReturnType()->isVariablyModifiedType()) {
Diag(NewFD->getLocation(), diag::err_vm_func_decl);
NewFD->setInvalidDecl();
}
@@ -6982,17 +7062,29 @@
// Handle attributes.
ProcessDeclAttributes(S, NewFD, D);
- QualType RetType = NewFD->getResultType();
+ QualType RetType = NewFD->getReturnType();
const CXXRecordDecl *Ret = RetType->isRecordType() ?
RetType->getAsCXXRecordDecl() : RetType->getPointeeCXXRecordDecl();
if (!NewFD->isInvalidDecl() && !NewFD->hasAttr<WarnUnusedResultAttr>() &&
Ret && Ret->hasAttr<WarnUnusedResultAttr>()) {
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
- // 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));
+ // Attach WarnUnusedResult to functions returning types with that attribute.
+ // Don't apply the attribute to that type's own non-static member functions
+ // (to avoid warning on things like assignment operators)
+ if (!MD || MD->getParent() != Ret)
+ NewFD->addAttr(WarnUnusedResultAttr::CreateImplicit(Context));
+ }
+
+ if (getLangOpts().OpenCL) {
+ // OpenCL v1.1 s6.5: Using an address space qualifier in a function return
+ // type declaration will generate a compilation error.
+ unsigned AddressSpace = RetType.getAddressSpace();
+ if (AddressSpace == LangAS::opencl_local ||
+ AddressSpace == LangAS::opencl_global ||
+ AddressSpace == LangAS::opencl_constant) {
+ Diag(NewFD->getLocation(),
+ diag::err_opencl_return_value_with_address_space);
+ NewFD->setInvalidDecl();
}
}
@@ -7141,12 +7233,7 @@
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->isInvalidDecl())
D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
isExplicitSpecialization));
}
@@ -7248,11 +7335,12 @@
}
}
- } else if (!D.isFunctionDefinition() && D.getCXXScopeSpec().isSet() &&
+ } else if (!D.isFunctionDefinition() &&
+ isa<CXXMethodDecl>(NewFD) && NewFD->isOutOfLine() &&
!isFriend && !isFunctionTemplateSpecialization &&
!isExplicitSpecialization) {
// An out-of-line member function declaration must also be a
- // definition (C++ [dcl.meaning]p1).
+ // definition (C++ [class.mfct]p2).
// Note that this is not the case for explicit specializations of
// function templates or member functions of class templates, per
// C++ [temp.expl.spec]p2. We also allow these declarations as an
@@ -7281,7 +7369,7 @@
EPI.Variadic = true;
EPI.ExtInfo = FT->getExtInfo();
- QualType R = Context.getFunctionType(FT->getResultType(), None, EPI);
+ QualType R = Context.getFunctionType(FT->getReturnType(), None, EPI);
NewFD->setType(R);
}
@@ -7303,6 +7391,12 @@
// Set this FunctionDecl's range up to the right paren.
NewFD->setRangeEnd(D.getSourceRange().getEnd());
+ if (D.isRedeclaration() && !Previous.empty()) {
+ checkDLLAttributeRedeclaration(
+ *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewFD,
+ isExplicitSpecialization || isFunctionTemplateSpecialization);
+ }
+
if (getLangOpts().CPlusPlus) {
if (FunctionTemplate) {
if (NewFD->isInvalidDecl())
@@ -7320,18 +7414,15 @@
}
// OpenCL v1.2, s6.9 -- Kernels can only have return type void.
- if (!NewFD->getResultType()->isVoidType()) {
+ if (!NewFD->getReturnType()->isVoidType()) {
Diag(D.getIdentifierLoc(),
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;
+ for (auto Param : NewFD->params())
checkIsValidOpenCLKernelParameter(*this, D, Param, ValidTypes);
- }
}
MarkUnusedFileScopedDecl(NewFD);
@@ -7341,7 +7432,7 @@
if (!NewFD->isInvalidDecl() &&
NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
if (II->isStr("cudaConfigureCall")) {
- if (!R->getAs<FunctionType>()->getResultType()->isScalarType())
+ if (!R->getAs<FunctionType>()->getReturnType()->isScalarType())
Diag(NewFD->getLocation(), diag::err_config_scalar_return);
Context.setcudaConfigureCallDecl(NewFD);
@@ -7383,8 +7474,8 @@
bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
LookupResult &Previous,
bool IsExplicitSpecialization) {
- assert(!NewFD->getResultType()->isVariablyModifiedType()
- && "Variably modified return types are not handled here");
+ assert(!NewFD->getReturnType()->isVariablyModifiedType() &&
+ "Variably modified return types are not handled here");
// Determine whether the type of this function should be merged with
// a previous visible declaration. This never happens for functions in C++,
@@ -7440,8 +7531,7 @@
if (OverloadedDecl)
Diag(OverloadedDecl->getLocation(),
diag::note_attribute_overloadable_prev_overload);
- NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(),
- Context));
+ NewFD->addAttr(OverloadableAttr::CreateImplicit(Context));
}
}
}
@@ -7464,8 +7554,7 @@
<< Redeclaration << NewFD;
Diag(Previous.getFoundDecl()->getLocation(),
diag::note_attribute_overloadable_prev_overload);
- NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(),
- Context));
+ NewFD->addAttr(OverloadableAttr::CreateImplicit(Context));
}
if (IsOverload(NewFD, cast<FunctionDecl>(OldDecl), false)) {
Redeclaration = false;
@@ -7488,17 +7577,16 @@
if (!getLangOpts().CPlusPlus1y && MD && MD->isConstexpr() &&
!MD->isStatic() && !isa<CXXConstructorDecl>(MD) &&
(MD->getTypeQualifiers() & Qualifiers::Const) == 0) {
- CXXMethodDecl *OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl);
- if (FunctionTemplateDecl *OldTD =
- dyn_cast_or_null<FunctionTemplateDecl>(OldDecl))
- OldMD = dyn_cast<CXXMethodDecl>(OldTD->getTemplatedDecl());
+ CXXMethodDecl *OldMD = 0;
+ if (OldDecl)
+ OldMD = dyn_cast<CXXMethodDecl>(OldDecl->getAsFunction());
if (!OldMD || !OldMD->isStatic()) {
const FunctionProtoType *FPT =
MD->getType()->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals |= Qualifiers::Const;
- MD->setType(Context.getFunctionType(FPT->getResultType(),
- FPT->getArgTypes(), EPI));
+ MD->setType(Context.getFunctionType(FPT->getReturnType(),
+ FPT->getParamTypes(), 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.
@@ -7656,7 +7744,7 @@
// compatible, and if it does, warn the user.
// But, issue any diagnostic on the first declaration only.
if (NewFD->isExternC() && Previous.empty()) {
- QualType R = NewFD->getResultType();
+ QualType R = NewFD->getReturnType();
if (R->isIncompleteType() && !R->isVoidType())
Diag(NewFD->getLocation(), diag::warn_return_value_udt_incomplete)
<< NewFD << R;
@@ -7678,7 +7766,7 @@
if (!FunctionTL)
return SourceRange();
- TypeLoc ResultTL = FunctionTL.getResultLoc();
+ TypeLoc ResultTL = FunctionTL.getReturnLoc();
if (ResultTL.getUnqualifiedLoc().getAs<BuiltinTypeLoc>())
return ResultTL.getSourceRange();
@@ -7686,8 +7774,9 @@
}
void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
- // C++11 [basic.start.main]p3: A program that declares main to be inline,
- // static or constexpr is ill-formed.
+ // C++11 [basic.start.main]p3:
+ // A program that [...] declares main to be inline, static or
+ // constexpr is ill-formed.
// C11 6.7.4p4: In a hosted environment, no function specifier(s) shall
// appear in a declaration of main.
// static main is not an error under C99, but we should warn about it.
@@ -7725,7 +7814,7 @@
const FunctionType* FT = T->castAs<FunctionType>();
// All the standards say that main() should should return 'int'.
- if (Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) {
+ if (Context.hasSameUnqualifiedType(FT->getReturnType(), Context.IntTy)) {
// In C and C++, main magically returns 0 if you fall off the end;
// set the flag which tells us that.
// This is C++ [basic.start.main]p5 and C99 5.1.2.2.3.
@@ -7758,7 +7847,7 @@
if (isa<FunctionNoProtoType>(FT)) return;
const FunctionProtoType* FTP = cast<const FunctionProtoType>(FT);
- unsigned nparams = FTP->getNumArgs();
+ unsigned nparams = FTP->getNumParams();
assert(FD->getNumParams() == nparams);
bool HasExtraParameters = (nparams > 3);
@@ -7783,7 +7872,7 @@
QualType Expected[] = { Context.IntTy, CharPP, CharPP, CharPP };
for (unsigned i = 0; i < nparams; ++i) {
- QualType AT = FTP->getArgType(i);
+ QualType AT = FTP->getParamType(i);
bool mismatch = true;
@@ -7818,7 +7907,7 @@
}
if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) {
- Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD->getName();
+ Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD;
FD->setInvalidDecl();
}
}
@@ -7830,15 +7919,15 @@
// 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())
+ if (FT->getReturnType()->isIntegralOrEnumerationType() ||
+ FT->getReturnType()->isAnyPointerType() ||
+ FT->getReturnType()->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();
+ Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD;
FD->setInvalidDecl();
}
}
@@ -8084,6 +8173,11 @@
return;
} else {
DeduceInit = CXXDirectInit->getExpr(0);
+ if (isa<InitListExpr>(DeduceInit))
+ Diag(CXXDirectInit->getLocStart(),
+ diag::err_auto_var_init_paren_braces)
+ << VDecl->getDeclName() << VDecl->getType()
+ << VDecl->getSourceRange();
}
}
@@ -8141,6 +8235,13 @@
return;
}
+ // dllimport cannot be used on variable definitions.
+ if (VDecl->hasAttr<DLLImportAttr>() && !VDecl->isStaticDataMember()) {
+ Diag(VDecl->getLocation(), diag::err_attribute_dllimport_data_definition);
+ VDecl->setInvalidDecl();
+ return;
+ }
+
if (VDecl->isLocalVarDecl() && VDecl->hasExternalStorage()) {
// C99 6.7.8p5. C++ has no such restriction, but that is a defect.
Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
@@ -8192,9 +8293,9 @@
// data members we also need to check whether there was an in-class
// declaration with an initializer.
if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) {
- Diag(VDecl->getLocation(), diag::err_redefinition)
- << VDecl->getDeclName();
- Diag(PrevInit->getLocation(), diag::note_previous_definition);
+ Diag(Init->getExprLoc(), diag::err_static_data_member_reinitialization)
+ << VDecl->getDeclName();
+ Diag(PrevInit->getInit()->getExprLoc(), diag::note_previous_initializer) << 0;
return;
}
@@ -8558,6 +8659,16 @@
return;
}
+ // OpenCL v1.1 s6.5.3: variables declared in the constant address space must
+ // be initialized.
+ if (!Var->isInvalidDecl() &&
+ Var->getType().getAddressSpace() == LangAS::opencl_constant &&
+ Var->getStorageClass() != SC_Extern && !Var->getInit()) {
+ Diag(Var->getLocation(), diag::err_opencl_constant_no_init);
+ Var->setInvalidDecl();
+ return;
+ }
+
switch (Var->isThisDeclarationADefinition()) {
case VarDecl::Definition:
if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
@@ -8788,7 +8899,13 @@
}
}
+ // Warn about externally-visible variables being defined without a
+ // prior declaration. We only want to do this for global
+ // declarations, but we also specifically need to avoid doing it for
+ // class members because the linkage of an anonymous class can
+ // change if it's later given a typedef name.
if (var->isThisDeclarationADefinition() &&
+ var->getDeclContext()->getRedeclContext()->isFileContext() &&
var->isExternallyVisible() && var->hasLinkage() &&
getDiagnostics().getDiagnosticLevel(
diag::warn_missing_variable_declarations,
@@ -8901,9 +9018,11 @@
if (!VD)
return;
+ checkAttributesAfterMerging(*this, *VD);
+
if (UsedAttr *Attr = VD->getAttr<UsedAttr>()) {
if (!Attr->isInherited() && !VD->isThisDeclarationADefinition()) {
- Diag(Attr->getLocation(), diag::warn_attribute_ignored) << "used";
+ Diag(Attr->getLocation(), diag::warn_attribute_ignored) << Attr;
VD->dropAttr<UsedAttr>();
}
}
@@ -8923,10 +9042,11 @@
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->isExternallyVisible())
+ if (DC->getRedeclContext()->isFileContext() && VD->isExternallyVisible())
AddPushedVisibilityAttribute(VD);
- if (VD->isFileVarDecl())
+ // FIXME: Warn on unused templates.
+ if (VD->isFileVarDecl() && !VD->getDescribedVarTemplate())
MarkUnusedFileScopedDecl(VD);
// Now we have parsed the initializer and can update the table of magic
@@ -8935,10 +9055,7 @@
!VD->getType()->isIntegralOrEnumerationType())
return;
- for (specific_attr_iterator<TypeTagForDatatypeAttr>
- I = ThisDecl->specific_attr_begin<TypeTagForDatatypeAttr>(),
- E = ThisDecl->specific_attr_end<TypeTagForDatatypeAttr>();
- I != E; ++I) {
+ for (const auto *I : ThisDecl->specific_attrs<TypeTagForDatatypeAttr>()) {
const Expr *MagicValueExpr = VD->getInit();
if (!MagicValueExpr) {
continue;
@@ -8983,7 +9100,7 @@
if (DeclSpec::isDeclRep(DS.getTypeSpecType())) {
if (TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) {
- HandleTagNumbering(*this, Tag);
+ HandleTagNumbering(*this, Tag, S);
if (!Tag->hasNameForLinkage() && !Tag->hasDeclaratorForAnonDecl())
Tag->setDeclaratorForAnonDecl(FirstDeclaratorInGroup);
}
@@ -9138,7 +9255,7 @@
II = D.getIdentifier();
if (!II) {
Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name)
- << GetNameForDeclarator(D).getName().getAsString();
+ << GetNameForDeclarator(D).getName();
D.setInvalidType(true);
}
}
@@ -9333,16 +9450,15 @@
// Verify 6.9.1p6: 'every identifier in the identifier list shall be declared'
// for a K&R function.
if (!FTI.hasPrototype) {
- for (int i = FTI.NumArgs; i != 0; /* decrement in loop */) {
+ for (int i = FTI.NumParams; i != 0; /* decrement in loop */) {
--i;
- if (FTI.ArgInfo[i].Param == 0) {
+ if (FTI.Params[i].Param == 0) {
SmallString<256> Code;
- llvm::raw_svector_ostream(Code) << " int "
- << FTI.ArgInfo[i].Ident->getName()
- << ";\n";
- Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared)
- << FTI.ArgInfo[i].Ident
- << FixItHint::CreateInsertion(LocAfterDecls, Code.str());
+ llvm::raw_svector_ostream(Code)
+ << " int " << FTI.Params[i].Ident->getName() << ";\n";
+ Diag(FTI.Params[i].IdentLoc, diag::ext_param_not_declared)
+ << FTI.Params[i].Ident
+ << FixItHint::CreateInsertion(LocAfterDecls, Code.str());
// Implicitly declare the argument as type 'int' for lack of a better
// type.
@@ -9350,14 +9466,14 @@
DeclSpec DS(attrs);
const char* PrevSpec; // unused
unsigned DiagID; // unused
- DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc,
- PrevSpec, DiagID);
+ DS.SetTypeSpecType(DeclSpec::TST_int, FTI.Params[i].IdentLoc, PrevSpec,
+ DiagID, Context.getPrintingPolicy());
// Use the identifier location for the type source range.
- DS.SetRangeStart(FTI.ArgInfo[i].IdentLoc);
- DS.SetRangeEnd(FTI.ArgInfo[i].IdentLoc);
+ DS.SetRangeStart(FTI.Params[i].IdentLoc);
+ DS.SetRangeEnd(FTI.Params[i].IdentLoc);
Declarator ParamD(DS, Declarator::KNRTypeListContext);
- ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc);
- FTI.ArgInfo[i].Param = ActOnParamDeclarator(S, ParamD);
+ ParamD.SetIdentifier(FTI.Params[i].Ident, FTI.Params[i].IdentLoc);
+ FTI.Params[i].Param = ActOnParamDeclarator(S, ParamD);
}
}
}
@@ -9456,7 +9572,7 @@
LambdaScopeInfo *LSI = S.PushLambdaScope();
LSI->CallOperator = CallOperator;
LSI->Lambda = LambdaClass;
- LSI->ReturnType = CallOperator->getResultType();
+ LSI->ReturnType = CallOperator->getReturnType();
const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault();
if (LCD == LCD_None)
@@ -9472,22 +9588,21 @@
// 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();
+ for (const auto &C : LambdaClass->captures()) {
+ 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;
+ const bool ByRef = C.getCaptureKind() == LCK_ByRef;
LSI->addCapture(VD, /*IsBlock*/false, ByRef,
- /*RefersToEnclosingLocal*/true, C->getLocation(),
- /*EllipsisLoc*/C->isPackExpansion()
- ? C->getEllipsisLoc() : SourceLocation(),
+ /*RefersToEnclosingLocal*/true, C.getLocation(),
+ /*EllipsisLoc*/C.isPackExpansion()
+ ? C.getEllipsisLoc() : SourceLocation(),
CaptureType, /*Expr*/ 0);
- } else if (C->capturesThis()) {
- LSI->addThisCapture(/*Nested*/ false, C->getLocation(),
+ } else if (C.capturesThis()) {
+ LSI->addThisCapture(/*Nested*/ false, C.getLocation(),
S.getCurrentThisType(), /*Expr*/ 0);
}
}
@@ -9539,7 +9654,7 @@
// The return type of a function definition must be complete
// (C99 6.9.1p3, C++ [dcl.fct]p6).
- QualType ResultType = FD->getResultType();
+ QualType ResultType = FD->getReturnType();
if (!ResultType->isDependentType() && !ResultType->isVoidType() &&
!FD->isInvalidDecl() &&
RequireCompleteType(FD->getLocation(), ResultType,
@@ -9578,8 +9693,7 @@
/*CheckParameterNames=*/true);
// Introduce our parameters into the function scope
- for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
- ParmVarDecl *Param = FD->getParamDecl(p);
+ for (auto Param : FD->params()) {
Param->setOwningFunction(FD);
// If this has an identifier, add it to the scope stack.
@@ -9604,9 +9718,8 @@
// and reattach to the current context.
if (D->getLexicalDeclContext() == Context.getTranslationUnitDecl()) {
// Is the decl actually in the context?
- for (DeclContext::decl_iterator DI = Context.getTranslationUnitDecl()->decls_begin(),
- DE = Context.getTranslationUnitDecl()->decls_end(); DI != DE; ++DI) {
- if (*DI == D) {
+ for (const auto *DI : Context.getTranslationUnitDecl()->decls()) {
+ if (DI == D) {
Context.getTranslationUnitDecl()->removeDecl(D);
break;
}
@@ -9621,10 +9734,9 @@
// Similarly, dive into enums and fish their constants out, making them
// accessible in this scope.
- if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
- for (EnumDecl::enumerator_iterator EI = ED->enumerator_begin(),
- EE = ED->enumerator_end(); EI != EE; ++EI)
- PushOnScopeChains(*EI, FnBodyScope, /*AddToContext=*/false);
+ if (auto *ED = dyn_cast<EnumDecl>(D)) {
+ for (auto *EI : ED->enumerators())
+ PushOnScopeChains(EI, FnBodyScope, /*AddToContext=*/false);
}
}
}
@@ -9636,28 +9748,17 @@
// Checking attributes of current function definition
// dllimport attribute.
DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
- if (DA && (!FD->getAttr<DLLExportAttr>())) {
+ if (DA && (!FD->hasAttr<DLLExportAttr>())) {
// dllimport attribute cannot be directly applied to definition.
// Microsoft accepts dllimport for functions defined within class scope.
if (!DA->isInherited() &&
!(LangOpts.MicrosoftExt && FD->getLexicalDeclContext()->isRecord())) {
Diag(FD->getLocation(),
diag::err_attribute_can_be_applied_only_to_symbol_declaration)
- << "dllimport";
+ << DA;
FD->setInvalidDecl();
return D;
}
-
- // Visual C++ appears to not think this is an issue, so only issue
- // a warning when Microsoft extensions are disabled.
- if (!LangOpts.MicrosoftExt) {
- // If a symbol previously declared dllimport is later defined, the
- // attribute is ignored in subsequent references, and a warning is
- // emitted.
- Diag(FD->getLocation(),
- diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
- << FD->getName() << "dllimport";
- }
}
// We want to attach documentation to original Decl (which might be
// a function template).
@@ -9699,25 +9800,40 @@
const_cast<VarDecl*>(NRVOCandidate)->setNRVOVariable(true);
}
-bool Sema::canSkipFunctionBody(Decl *D) {
- if (!Consumer.shouldSkipFunctionBody(D))
+bool Sema::canDelayFunctionBody(const Declarator &D) {
+ // We can't delay parsing the body of a constexpr function template (yet).
+ if (D.getDeclSpec().isConstexprSpecified())
return false;
- if (isa<ObjCMethodDecl>(D))
- return true;
+ // We can't delay parsing the body of a function template with a deduced
+ // return type (yet).
+ if (D.getDeclSpec().containsPlaceholderType()) {
+ // If the placeholder introduces a non-deduced trailing return type,
+ // we can still delay parsing it.
+ if (D.getNumTypeObjects()) {
+ const auto &Outer = D.getTypeObject(D.getNumTypeObjects() - 1);
+ if (Outer.Kind == DeclaratorChunk::Function &&
+ Outer.Fun.hasTrailingReturnType()) {
+ QualType Ty = GetTypeFromParser(Outer.Fun.getTrailingReturnType());
+ return Ty.isNull() || !Ty->isUndeducedType();
+ }
+ }
+ return false;
+ }
- FunctionDecl *FD = 0;
- if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
- FD = FTD->getTemplatedDecl();
- else
- FD = cast<FunctionDecl>(D);
+ return true;
+}
+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.
// 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();
+ if (const FunctionDecl *FD = D->getAsFunction())
+ if (FD->isConstexpr() || FD->getReturnType()->isUndeducedType())
+ return false;
+ return Consumer.shouldSkipFunctionBody(D);
}
Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) {
@@ -9734,12 +9850,7 @@
Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
bool IsInstantiation) {
- FunctionDecl *FD = 0;
- FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(dcl);
- if (FunTmpl)
- FD = FunTmpl->getTemplatedDecl();
- else
- FD = dyn_cast_or_null<FunctionDecl>(dcl);
+ FunctionDecl *FD = dcl ? dcl->getAsFunction() : 0;
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
sema::AnalysisBasedWarnings::Policy *ActivePolicy = 0;
@@ -9748,18 +9859,18 @@
FD->setBody(Body);
if (getLangOpts().CPlusPlus1y && !FD->isInvalidDecl() && Body &&
- !FD->isDependentContext() && FD->getResultType()->isUndeducedType()) {
+ !FD->isDependentContext() && FD->getReturnType()->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>()) {
+ if (!FD->getReturnType()->getAs<AutoType>()) {
Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto)
- << FD->getResultType();
+ << FD->getReturnType();
FD->setInvalidDecl();
} else {
// Substitute 'void' for the 'auto' in the type.
TypeLoc ResultType = FD->getTypeSourceInfo()->getTypeLoc().
- IgnoreParens().castAs<FunctionProtoTypeLoc>().getResultLoc();
+ IgnoreParens().castAs<FunctionProtoTypeLoc>().getReturnLoc();
Context.adjustDeducedFunctionResultType(
FD, SubstAutoType(ResultType.getType(), Context.VoidTy));
}
@@ -9783,15 +9894,15 @@
WP.disableCheckFallThrough();
// MSVC permits the use of pure specifier (=0) on function definition,
- // defined at class scope, warn about this non standard construct.
+ // defined at class scope, warn about this non-standard construct.
if (getLangOpts().MicrosoftExt && FD->isPure() && FD->isCanonicalDecl())
Diag(FD->getLocation(), diag::warn_pure_function_definition);
if (!FD->isInvalidDecl()) {
DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(),
- FD->getResultType(), FD);
-
+ FD->getReturnType(), FD);
+
// If this is a constructor, we need a vtable.
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD))
MarkVTableUsed(FD->getLocation(), Constructor->getParent());
@@ -9799,7 +9910,7 @@
// Try to apply the named return value optimization. We have to check
// if we can do this here because lambdas keep return statements around
// to deduce an implicit return type.
- if (getLangOpts().CPlusPlus && FD->getResultType()->isRecordType() &&
+ if (getLangOpts().CPlusPlus && FD->getReturnType()->isRecordType() &&
!FD->isDependentContext())
computeNRVO(Body, getCurFunction());
}
@@ -9812,8 +9923,8 @@
if (!MD->isInvalidDecl()) {
DiagnoseUnusedParameters(MD->param_begin(), MD->param_end());
DiagnoseSizeOfParametersAndReturnValue(MD->param_begin(), MD->param_end(),
- MD->getResultType(), MD);
-
+ MD->getReturnType(), MD);
+
if (Body)
computeNRVO(Body, getCurFunction());
}
@@ -9822,6 +9933,27 @@
<< MD->getSelector().getAsString();
getCurFunction()->ObjCShouldCallSuper = false;
}
+ if (getCurFunction()->ObjCWarnForNoDesignatedInitChain) {
+ const ObjCMethodDecl *InitMethod = 0;
+ bool isDesignated =
+ MD->isDesignatedInitializerForTheInterface(&InitMethod);
+ assert(isDesignated && InitMethod);
+ (void)isDesignated;
+ // Don't issue this warning for unavaialable inits.
+ if (!MD->isUnavailable()) {
+ Diag(MD->getLocation(),
+ diag::warn_objc_designated_init_missing_super_call);
+ Diag(InitMethod->getLocation(),
+ diag::note_objc_designated_init_marked_here);
+ }
+ getCurFunction()->ObjCWarnForNoDesignatedInitChain = false;
+ }
+ if (getCurFunction()->ObjCWarnForNoInitDelegation) {
+ // Don't issue this warning for unavaialable inits.
+ if (!MD->isUnavailable())
+ Diag(MD->getLocation(), diag::warn_objc_secondary_init_missing_init_call);
+ getCurFunction()->ObjCWarnForNoInitDelegation = false;
+ }
} else {
return 0;
}
@@ -9948,7 +10080,8 @@
AttributeFactory attrFactory;
DeclSpec DS(attrFactory);
unsigned DiagID;
- bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID);
+ bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID,
+ Context.getPrintingPolicy());
(void)Error; // Silence warning.
assert(!Error && "Error setting up implicit decl!");
SourceLocation NoLoc;
@@ -10012,25 +10145,27 @@
unsigned FormatIdx;
bool HasVAListArg;
if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
- if (!FD->getAttr<FormatAttr>()) {
+ if (!FD->hasAttr<FormatAttr>()) {
const char *fmt = "printf";
unsigned int NumParams = FD->getNumParams();
if (FormatIdx < NumParams && // NumParams may be 0 (e.g. vfprintf)
FD->getParamDecl(FormatIdx)->getType()->isObjCObjectPointerType())
fmt = "NSString";
- FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ FD->addAttr(FormatAttr::CreateImplicit(Context,
&Context.Idents.get(fmt),
FormatIdx+1,
- HasVAListArg ? 0 : FormatIdx+2));
+ HasVAListArg ? 0 : FormatIdx+2,
+ FD->getLocation()));
}
}
if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx,
HasVAListArg)) {
- if (!FD->getAttr<FormatAttr>())
- FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ if (!FD->hasAttr<FormatAttr>())
+ FD->addAttr(FormatAttr::CreateImplicit(Context,
&Context.Idents.get("scanf"),
FormatIdx+1,
- HasVAListArg ? 0 : FormatIdx+2));
+ HasVAListArg ? 0 : FormatIdx+2,
+ FD->getLocation()));
}
// Mark const if we don't care about errno and that is the only
@@ -10038,17 +10173,18 @@
// IRgen to use LLVM intrinsics for such functions.
if (!getLangOpts().MathErrno &&
Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
- if (!FD->getAttr<ConstAttr>())
- FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
+ if (!FD->hasAttr<ConstAttr>())
+ FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
}
if (Context.BuiltinInfo.isReturnsTwice(BuiltinID) &&
- !FD->getAttr<ReturnsTwiceAttr>())
- FD->addAttr(::new (Context) ReturnsTwiceAttr(FD->getLocation(), Context));
- if (Context.BuiltinInfo.isNoThrow(BuiltinID) && !FD->getAttr<NoThrowAttr>())
- FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context));
- if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->getAttr<ConstAttr>())
- FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
+ !FD->hasAttr<ReturnsTwiceAttr>())
+ FD->addAttr(ReturnsTwiceAttr::CreateImplicit(Context,
+ FD->getLocation()));
+ if (Context.BuiltinInfo.isNoThrow(BuiltinID) && !FD->hasAttr<NoThrowAttr>())
+ FD->addAttr(NoThrowAttr::CreateImplicit(Context, FD->getLocation()));
+ if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->hasAttr<ConstAttr>())
+ FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
}
IdentifierInfo *Name = FD->getIdentifier();
@@ -10067,17 +10203,19 @@
if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
// FIXME: asprintf and vasprintf aren't C99 functions. Should they be
// target-specific builtins, perhaps?
- if (!FD->getAttr<FormatAttr>())
- FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ if (!FD->hasAttr<FormatAttr>())
+ FD->addAttr(FormatAttr::CreateImplicit(Context,
&Context.Idents.get("printf"), 2,
- Name->isStr("vasprintf") ? 0 : 3));
+ Name->isStr("vasprintf") ? 0 : 3,
+ FD->getLocation()));
}
if (Name->isStr("__CFStringMakeConstantString")) {
// We already have a __builtin___CFStringMakeConstantString,
// but builds that use -fno-constant-cfstrings don't go through that.
- if (!FD->getAttr<FormatArgAttr>())
- FD->addAttr(::new (Context) FormatArgAttr(FD->getLocation(), Context, 1));
+ if (!FD->hasAttr<FormatArgAttr>())
+ FD->addAttr(FormatArgAttr::CreateImplicit(Context, 1,
+ FD->getLocation()));
}
}
@@ -10140,6 +10278,27 @@
if (!Context.hasSameType(T, Context.getTagDeclType(tagFromDeclSpec)))
break;
+ // If we've already computed linkage for the anonymous tag, then
+ // adding a typedef name for the anonymous decl can change that
+ // linkage, which might be a serious problem. Diagnose this as
+ // unsupported and ignore the typedef name. TODO: we should
+ // pursue this as a language defect and establish a formal rule
+ // for how to handle it.
+ if (tagFromDeclSpec->hasLinkageBeenComputed()) {
+ Diag(D.getIdentifierLoc(), diag::err_typedef_changes_linkage);
+
+ SourceLocation tagLoc = D.getDeclSpec().getTypeSpecTypeLoc();
+ tagLoc = Lexer::getLocForEndOfToken(tagLoc, 0, getSourceManager(),
+ getLangOpts());
+
+ llvm::SmallString<40> textToInsert;
+ textToInsert += ' ';
+ textToInsert += D.getIdentifier()->getName();
+ Diag(tagLoc, diag::note_typedef_changes_linkage)
+ << FixItHint::CreateInsertion(tagLoc, textToInsert);
+ break;
+ }
+
// Otherwise, set this is the anon-decl typedef for the tag.
tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD);
break;
@@ -10179,7 +10338,7 @@
if (IsScoped != Prev->isScoped()) {
Diag(EnumLoc, diag::err_enum_redeclare_scoped_mismatch)
<< Prev->isScoped();
- Diag(Prev->getLocation(), diag::note_previous_use);
+ Diag(Prev->getLocation(), diag::note_previous_declaration);
return true;
}
@@ -10188,15 +10347,17 @@
!Prev->getIntegerType()->isDependentType() &&
!Context.hasSameUnqualifiedType(EnumUnderlyingTy,
Prev->getIntegerType())) {
+ // TODO: Highlight the underlying type of the redeclaration.
Diag(EnumLoc, diag::err_enum_redeclare_type_mismatch)
<< EnumUnderlyingTy << Prev->getIntegerType();
- Diag(Prev->getLocation(), diag::note_previous_use);
+ Diag(Prev->getLocation(), diag::note_previous_declaration)
+ << Prev->getIntegerTypeRange();
return true;
}
} else if (IsFixed != Prev->isFixed()) {
Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch)
<< Prev->isFixed();
- Diag(Prev->getLocation(), diag::note_previous_use);
+ Diag(Prev->getLocation(), diag::note_previous_declaration);
return true;
}
@@ -10276,8 +10437,7 @@
}
bool previousMismatch = false;
- for (TagDecl::redecl_iterator I(Previous->redecls_begin()),
- E(Previous->redecls_end()); I != E; ++I) {
+ for (auto I : Previous->redecls()) {
if (I->getTagKind() != NewTag) {
if (!previousMismatch) {
previousMismatch = true;
@@ -10308,7 +10468,7 @@
<< getRedeclDiagFromTagKind(OldTag);
Diag(Redecl->getLocation(), diag::note_previous_use);
- // If there is a previous defintion, suggest a fix-it.
+ // If there is a previous definition, suggest a fix-it.
if (Previous->getDefinition()) {
Diag(NewTagLoc, diag::note_struct_class_suggestion)
<< getRedeclDiagFromTagKind(Redecl->getTagKind())
@@ -10325,6 +10485,9 @@
/// former case, Name will be non-null. In the later case, Name will be null.
/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a
/// reference/declaration/definition of a tag.
+///
+/// IsTypeSpecifier is true if this is a type-specifier (or
+/// trailing-type-specifier) other than one in an alias-declaration.
Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
@@ -10334,7 +10497,8 @@
bool &OwnedDecl, bool &IsDependent,
SourceLocation ScopedEnumKWLoc,
bool ScopedEnumUsesClassTag,
- TypeResult UnderlyingType) {
+ TypeResult UnderlyingType,
+ bool IsTypeSpecifier) {
// If this is not a definition, it must have a name.
IdentifierInfo *OrigName = Name;
assert((Name != 0 || TUK == TUK_Definition) &&
@@ -10412,7 +10576,7 @@
UPPC_FixedUnderlyingType))
EnumUnderlying = Context.IntTy.getTypePtr();
- } else if (getLangOpts().MicrosoftMode)
+ } else if (getLangOpts().MSVCCompat)
// Microsoft enums are always of int type.
EnumUnderlying = Context.IntTy.getTypePtr();
}
@@ -10634,7 +10798,9 @@
}
if (!Previous.empty()) {
- NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl();
+ NamedDecl *PrevDecl = Previous.getFoundDecl();
+ NamedDecl *DirectPrevDecl =
+ getLangOpts().MSVCCompat ? *Previous.begin() : PrevDecl;
// It's okay to have a tag decl in the same scope as a typedef
// which hides a tag decl in the same scope. Finding this
@@ -10666,7 +10832,8 @@
// in the same scope (so that the definition/declaration completes or
// rementions the tag), reuse the decl.
if (TUK == TUK_Reference || TUK == TUK_Friend ||
- isDeclInScope(PrevDecl, SearchDC, S, isExplicitSpecialization)) {
+ isDeclInScope(DirectPrevDecl, SearchDC, S,
+ SS.isNotEmpty() || isExplicitSpecialization)) {
// Make sure that this wasn't declared as an enum and now used as a
// struct or something similar.
if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind,
@@ -10709,7 +10876,7 @@
QualType EnumUnderlyingTy;
if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>())
- EnumUnderlyingTy = TI->getType();
+ EnumUnderlyingTy = TI->getType().getUnqualifiedType();
else if (const Type *T = EnumUnderlying.dyn_cast<const Type*>())
EnumUnderlyingTy = QualType(T, 0);
@@ -10827,8 +10994,8 @@
Invalid = true;
// Otherwise, only diagnose if the declaration is in scope.
- } else if (!isDeclInScope(PrevDecl, SearchDC, S,
- isExplicitSpecialization)) {
+ } else if (!isDeclInScope(PrevDecl, SearchDC, S,
+ SS.isNotEmpty() || isExplicitSpecialization)) {
// do nothing
// Diagnose implicit declarations introduced by elaborated types.
@@ -10904,7 +11071,7 @@
Diag(Def->getLocation(), diag::note_previous_definition);
} else {
unsigned DiagID = diag::ext_forward_ref_enum;
- if (getLangOpts().MicrosoftMode)
+ if (getLangOpts().MSVCCompat)
DiagID = diag::ext_ms_forward_ref_enum;
else if (getLangOpts().CPlusPlus)
DiagID = diag::err_forward_ref_enum;
@@ -10944,6 +11111,14 @@
cast_or_null<RecordDecl>(PrevDecl));
}
+ // C++11 [dcl.type]p3:
+ // A type-specifier-seq shall not define a class or enumeration [...].
+ if (getLangOpts().CPlusPlus && IsTypeSpecifier && TUK == TUK_Definition) {
+ Diag(New->getLocation(), diag::err_type_defined_in_type_specifier)
+ << Context.getTagDeclType(New);
+ Invalid = true;
+ }
+
// Maybe add qualifier info.
if (SS.isNotEmpty()) {
if (SS.isSet()) {
@@ -11007,10 +11182,14 @@
if (Attr)
ProcessDeclAttributeList(S, New, Attr);
- // If we're declaring or defining a tag in function prototype scope
- // in C, note that this type can only be used within the function.
- if (Name && S->isFunctionPrototypeScope() && !getLangOpts().CPlusPlus)
+ // If we're declaring or defining a tag in function prototype scope in C,
+ // note that this type can only be used within the function and add it to
+ // the list of decls to inject into the function definition scope.
+ if (!getLangOpts().CPlusPlus && (Name || Kind == TTK_Enum) &&
+ getNonFieldDeclScope(S)->isFunctionPrototypeScope()) {
Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
+ DeclsInPrototypeScope.push_back(New);
+ }
// Set the lexical context. If the tag has a C++ scope specifier, the
// lexical context will be different from the semantic context.
@@ -11060,12 +11239,6 @@
II->isStr("FILE"))
Context.setFILEDecl(New);
- // If we were in function prototype scope (and not in C++ mode), add this
- // tag to the list of decls to inject into the function definition scope.
- if (S->isFunctionPrototypeScope() && !getLangOpts().CPlusPlus &&
- InFunctionDeclarator && Name)
- DeclsInPrototypeScope.push_back(New);
-
if (PrevDecl)
mergeDeclAttributes(New, PrevDecl);
@@ -11255,7 +11428,8 @@
if (!FieldTy->isDependentType()) {
uint64_t TypeSize = Context.getTypeSize(FieldTy);
if (Value.getZExtValue() > TypeSize) {
- if (!getLangOpts().CPlusPlus || IsMsStruct) {
+ if (!getLangOpts().CPlusPlus || IsMsStruct ||
+ Context.getTargetInfo().getCXXABI().isMicrosoft()) {
if (FieldName)
return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size)
<< FieldName << (unsigned)Value.getZExtValue()
@@ -11500,6 +11674,12 @@
}
}
+ // C++11 [class.union]p8 (DR1460):
+ // At most one variant member of a union may have a
+ // brace-or-equal-initializer.
+ if (InitStyle != ICIS_NoInit)
+ checkDuplicateDefaultInit(*this, cast<CXXRecordDecl>(Record), Loc);
+
FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo,
BitWidth, Mutable, InitStyle);
if (InvalidDecl)
@@ -11603,8 +11783,9 @@
SourceLocation Loc = FD->getLocation();
if (getSourceManager().isInSystemHeader(Loc)) {
if (!FD->hasAttr<UnavailableAttr>())
- FD->addAttr(new (Context) UnavailableAttr(Loc, Context,
- "this system field has retaining ownership"));
+ FD->addAttr(UnavailableAttr::CreateImplicit(Context,
+ "this system field has retaining ownership",
+ Loc));
return false;
}
}
@@ -11813,9 +11994,8 @@
// members of anonymous structs and unions in the total.
unsigned NumNamedMembers = 0;
if (Record) {
- for (RecordDecl::decl_iterator i = Record->decls_begin(),
- e = Record->decls_end(); i != e; i++) {
- if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(*i))
+ for (const auto *I : Record->decls()) {
+ if (const auto *IFD = dyn_cast<IndirectFieldDecl>(I))
if (IFD->getDeclName())
++NumNamedMembers;
}
@@ -11902,9 +12082,14 @@
Diag(FD->getLocation(), diag::ext_c99_flexible_array_member)
<< FD->getDeclName() << Record->getTagKind();
- if (!FD->getType()->isDependentType() &&
- !Context.getBaseElementType(FD->getType()).isPODType(Context)) {
- Diag(FD->getLocation(), diag::err_flexible_array_has_nonpod_type)
+ // If the element type has a non-trivial destructor, we would not
+ // implicitly destroy the elements, so disallow it for now.
+ //
+ // FIXME: GCC allows this. We should probably either implicitly delete
+ // the destructor of the containing class, or just allow this.
+ QualType BaseElem = Context.getBaseElementType(FD->getType());
+ if (!BaseElem->isDependentType() && BaseElem.isDestructedType()) {
+ Diag(FD->getLocation(), diag::err_flexible_array_has_nontrivial_dtor)
<< FD->getDeclName() << FD->getType();
FD->setInvalidDecl();
EnclosingDecl->setInvalidDecl();
@@ -11972,8 +12157,9 @@
SourceLocation loc = FD->getLocation();
if (getSourceManager().isInSystemHeader(loc)) {
if (!FD->hasAttr<UnavailableAttr>()) {
- FD->addAttr(new (Context) UnavailableAttr(loc, Context,
- "this system field has retaining ownership"));
+ FD->addAttr(UnavailableAttr::CreateImplicit(Context,
+ "this system field has retaining ownership",
+ loc));
}
} else {
Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag)
@@ -12021,12 +12207,6 @@
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.
@@ -12078,9 +12258,15 @@
if (!Completed)
Record->completeDefinition();
- if (Record->hasAttrs())
+ if (Record->hasAttrs()) {
CheckAlignasUnderalignment(Record);
+ if (const MSInheritanceAttr *IA = Record->getAttr<MSInheritanceAttr>())
+ checkMSInheritanceAttrOnDefinition(cast<CXXRecordDecl>(Record),
+ IA->getRange(), IA->getBestCase(),
+ IA->getSemanticSpelling());
+ }
+
// 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.
@@ -12175,10 +12361,7 @@
Diag(ClsIvar->getLocation(), diag::note_previous_definition);
continue;
}
- for (ObjCInterfaceDecl::known_extensions_iterator
- Ext = IDecl->known_extensions_begin(),
- ExtEnd = IDecl->known_extensions_end();
- Ext != ExtEnd; ++Ext) {
+ for (const auto *Ext : IDecl->known_extensions()) {
if (const ObjCIvarDecl *ClsExtIvar
= Ext->getIvarDecl(ClsFields[i]->getIdentifier())) {
Diag(ClsFields[i]->getLocation(),
@@ -12262,7 +12445,7 @@
else {
SourceLocation ExpLoc;
if (getLangOpts().CPlusPlus11 && Enum->isFixed() &&
- !getLangOpts().MicrosoftMode) {
+ !getLangOpts().MSVCCompat) {
// C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the
// constant-expression in the enumerator-definition shall be a converted
// constant expression of the underlying type.
@@ -12287,7 +12470,7 @@
// we perform a non-narrowing conversion as part of converted constant
// expression checking.
if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
- if (getLangOpts().MicrosoftMode) {
+ if (getLangOpts().MSVCCompat) {
Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy;
Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
} else
@@ -12371,7 +12554,7 @@
<< EnumVal.toString(10)
<< EltTy;
else
- Diag(IdLoc, diag::warn_enumerator_too_large)
+ Diag(IdLoc, diag::ext_enumerator_increment_too_large)
<< EnumVal.toString(10);
} else {
EltTy = T;
@@ -12729,7 +12912,7 @@
// The C99 rule is modified by a gcc extension
QualType BestPromotionType;
- bool Packed = Enum->getAttr<PackedAttr>() ? true : false;
+ bool Packed = Enum->hasAttr<PackedAttr>();
// -fshort-enums is the equivalent to specifying the packed attribute on all
// enum definitions.
if (LangOpts.ShortEnums)
@@ -12769,7 +12952,7 @@
BestWidth = Context.getTargetInfo().getLongLongWidth();
if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth)
- Diag(Enum->getLocation(), diag::warn_enum_too_large);
+ Diag(Enum->getLocation(), diag::ext_enum_too_large);
BestType = Context.LongLongTy;
}
}
@@ -12874,11 +13057,6 @@
Enum->completeDefinition(BestType, BestPromotionType,
NumPositiveBits, NumNegativeBits);
- // If we're declaring a function, ensure this decl isn't forgotten about -
- // it needs to go into the function scope.
- if (InFunctionDeclarator)
- DeclsInPrototypeScope.push_back(Enum);
-
CheckForDuplicateEnumValues(*this, Elements, Enum, EnumType);
// Now that the enum type is defined, ensure it's not been underaligned.
@@ -12898,6 +13076,36 @@
return New;
}
+static void checkModuleImportContext(Sema &S, Module *M,
+ SourceLocation ImportLoc,
+ DeclContext *DC) {
+ if (auto *LSD = dyn_cast<LinkageSpecDecl>(DC)) {
+ switch (LSD->getLanguage()) {
+ case LinkageSpecDecl::lang_c:
+ if (!M->IsExternC) {
+ S.Diag(ImportLoc, diag::err_module_import_in_extern_c)
+ << M->getFullModuleName();
+ S.Diag(LSD->getLocStart(), diag::note_module_import_in_extern_c);
+ return;
+ }
+ break;
+ case LinkageSpecDecl::lang_cxx:
+ break;
+ }
+ DC = LSD->getParent();
+ }
+
+ while (isa<LinkageSpecDecl>(DC))
+ DC = DC->getParent();
+ if (!isa<TranslationUnitDecl>(DC)) {
+ S.Diag(ImportLoc, diag::err_module_import_not_at_top_level)
+ << M->getFullModuleName() << DC;
+ S.Diag(cast<Decl>(DC)->getLocStart(),
+ diag::note_module_import_not_at_top_level)
+ << DC;
+ }
+}
+
DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
SourceLocation ImportLoc,
ModuleIdPath Path) {
@@ -12906,7 +13114,9 @@
/*IsIncludeDirective=*/false);
if (!Mod)
return true;
-
+
+ checkModuleImportContext(*this, Mod, ImportLoc, CurContext);
+
SmallVector<SourceLocation, 2> IdentifierLocs;
Module *ModCheck = Mod;
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
@@ -12928,6 +13138,8 @@
}
void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
+ checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext);
+
// FIXME: Should we synthesize an ImportDecl here?
PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc,
/*Complain=*/true);
@@ -12953,8 +13165,8 @@
SourceLocation AliasNameLoc) {
Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc,
LookupOrdinaryName);
- AsmLabelAttr *Attr =
- ::new (Context) AsmLabelAttr(AliasNameLoc, Context, AliasName->getName());
+ AsmLabelAttr *Attr = ::new (Context) AsmLabelAttr(AliasNameLoc, Context,
+ AliasName->getName(), 0);
if (PrevDecl)
PrevDecl->addAttr(Attr);
@@ -12969,7 +13181,7 @@
Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName);
if (PrevDecl) {
- PrevDecl->addAttr(::new (Context) WeakAttr(PragmaLoc, Context));
+ PrevDecl->addAttr(WeakAttr::CreateImplicit(Context, PragmaLoc));
} else {
(void)WeakUndeclaredIdentifiers.insert(
std::pair<IdentifierInfo*,WeakInfo>
@@ -13002,5 +13214,22 @@
AvailabilityResult Sema::getCurContextAvailability() const {
const Decl *D = cast<Decl>(getCurObjCLexicalContext());
+ // If we are within an Objective-C method, we should consult
+ // both the availability of the method as well as the
+ // enclosing class. If the class is (say) deprecated,
+ // the entire method is considered deprecated from the
+ // purpose of checking if the current context is deprecated.
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ AvailabilityResult R = MD->getAvailability();
+ if (R != AR_Available)
+ return R;
+ D = MD->getClassInterface();
+ }
+ // If we are within an Objective-c @implementation, it
+ // gets the same availability context as the @interface.
+ else if (const ObjCImplementationDecl *ID =
+ dyn_cast<ObjCImplementationDecl>(D)) {
+ D = ID->getClassInterface();
+ }
return D->getAvailability();
}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 318575a..38b3c45 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "TargetAttributesSema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
@@ -32,86 +31,23 @@
using namespace clang;
using namespace sema;
-/// These constants match the enumerated choices of
-/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
-enum AttributeDeclKind {
- ExpectedFunction,
- ExpectedUnion,
- ExpectedVariableOrFunction,
- ExpectedFunctionOrMethod,
- ExpectedParameter,
- ExpectedFunctionMethodOrBlock,
- ExpectedFunctionMethodOrClass,
- ExpectedFunctionMethodOrParameter,
- ExpectedClass,
- ExpectedVariable,
- ExpectedMethod,
- ExpectedVariableFunctionOrLabel,
- ExpectedFieldOrGlobalVar,
- ExpectedStruct,
- ExpectedVariableFunctionOrTag,
- ExpectedTLSVar,
- ExpectedVariableOrField,
- ExpectedVariableFieldOrTag,
- ExpectedTypeOrNamespace,
- ExpectedObjectiveCInterface,
- ExpectedMethodOrProperty,
- ExpectedStructOrUnion,
- ExpectedStructOrUnionOrClass
-};
+namespace AttributeLangSupport {
+ enum LANG {
+ C,
+ Cpp,
+ ObjC
+ };
+}
//===----------------------------------------------------------------------===//
// Helper functions
//===----------------------------------------------------------------------===//
-static const FunctionType *getFunctionType(const Decl *D,
- bool blocksToo = true) {
- QualType Ty;
- if (const ValueDecl *decl = dyn_cast<ValueDecl>(D))
- Ty = decl->getType();
- else if (const FieldDecl *decl = dyn_cast<FieldDecl>(D))
- Ty = decl->getType();
- else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(D))
- Ty = decl->getUnderlyingType();
- else
- return 0;
-
- if (Ty->isFunctionPointerType())
- Ty = Ty->getAs<PointerType>()->getPointeeType();
- else if (blocksToo && Ty->isBlockPointerType())
- Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
-
- return Ty->getAs<FunctionType>();
-}
-
-// FIXME: We should provide an abstraction around a method or function
-// to provide the following bits of information.
-
-/// isFunction - Return true if the given decl has function
-/// type (function or function-typed variable).
-static bool isFunction(const Decl *D) {
- return getFunctionType(D, false) != NULL;
-}
-
/// isFunctionOrMethod - Return true if the given decl has function
/// type (function or function-typed variable) or an Objective-C
/// method.
static bool isFunctionOrMethod(const Decl *D) {
- return isFunction(D) || isa<ObjCMethodDecl>(D);
-}
-
-/// isFunctionOrMethodOrBlock - Return true if the given decl has function
-/// type (function or function-typed variable) or an Objective-C
-/// method or a block.
-static bool isFunctionOrMethodOrBlock(const Decl *D) {
- if (isFunctionOrMethod(D))
- return true;
- // check for block is more involved.
- if (const VarDecl *V = dyn_cast<VarDecl>(D)) {
- QualType Ty = V->getType();
- return Ty->isBlockPointerType();
- }
- return isa<BlockDecl>(D);
+ return (D->getFunctionType() != NULL) || isa<ObjCMethodDecl>(D);
}
/// Return true if the given decl has a declarator that should have
@@ -126,28 +62,25 @@
/// information. This decl should have already passed
/// isFunctionOrMethod or isFunctionOrMethodOrBlock.
static bool hasFunctionProto(const Decl *D) {
- if (const FunctionType *FnTy = getFunctionType(D))
+ if (const FunctionType *FnTy = D->getFunctionType())
return isa<FunctionProtoType>(FnTy);
- else {
- assert(isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D));
- return true;
- }
+ return isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D);
}
-/// getFunctionOrMethodNumArgs - Return number of function or method
-/// arguments. It is an error to call this on a K&R function (use
+/// getFunctionOrMethodNumParams - Return number of function or method
+/// parameters. It is an error to call this on a K&R function (use
/// hasFunctionProto first).
-static unsigned getFunctionOrMethodNumArgs(const Decl *D) {
- if (const FunctionType *FnTy = getFunctionType(D))
- return cast<FunctionProtoType>(FnTy)->getNumArgs();
+static unsigned getFunctionOrMethodNumParams(const Decl *D) {
+ if (const FunctionType *FnTy = D->getFunctionType())
+ return cast<FunctionProtoType>(FnTy)->getNumParams();
if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
return BD->getNumParams();
return cast<ObjCMethodDecl>(D)->param_size();
}
-static QualType getFunctionOrMethodArgType(const Decl *D, unsigned Idx) {
- if (const FunctionType *FnTy = getFunctionType(D))
- return cast<FunctionProtoType>(FnTy)->getArgType(Idx);
+static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
+ if (const FunctionType *FnTy = D->getFunctionType())
+ return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
return BD->getParamDecl(Idx)->getType();
@@ -155,13 +88,13 @@
}
static QualType getFunctionOrMethodResultType(const Decl *D) {
- if (const FunctionType *FnTy = getFunctionType(D))
- return cast<FunctionProtoType>(FnTy)->getResultType();
- return cast<ObjCMethodDecl>(D)->getResultType();
+ if (const FunctionType *FnTy = D->getFunctionType())
+ return cast<FunctionProtoType>(FnTy)->getReturnType();
+ return cast<ObjCMethodDecl>(D)->getReturnType();
}
static bool isFunctionOrMethodVariadic(const Decl *D) {
- if (const FunctionType *FnTy = getFunctionType(D)) {
+ if (const FunctionType *FnTy = D->getFunctionType()) {
const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy);
return proto->isVariadic();
} else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
@@ -227,30 +160,63 @@
return true;
}
-
/// \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 Num) {
if (getNumAttributeArgs(Attr) < Num) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num;
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments)
+ << Attr.getName() << Num;
return false;
}
return true;
}
-/// \brief Check if IdxExpr is a valid argument index for a function or
+/// \brief If Expr is a valid integer constant, get the value of the integer
+/// expression and return success or failure. May output an error.
+static bool checkUInt32Argument(Sema &S, const AttributeList &Attr,
+ const Expr *Expr, uint32_t &Val,
+ unsigned Idx = UINT_MAX) {
+ llvm::APSInt I(32);
+ if (Expr->isTypeDependent() || Expr->isValueDependent() ||
+ !Expr->isIntegerConstantExpr(I, S.Context)) {
+ if (Idx != UINT_MAX)
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << Idx << AANT_ArgumentIntegerConstant
+ << Expr->getSourceRange();
+ else
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << Expr->getSourceRange();
+ return false;
+ }
+ Val = (uint32_t)I.getZExtValue();
+ return true;
+}
+
+/// \brief Diagnose mutually exclusive attributes when present on a given
+/// declaration. Returns true if diagnosed.
+template <typename AttrTy>
+static bool checkAttrMutualExclusion(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (AttrTy *A = D->getAttr<AttrTy>()) {
+ S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << Attr.getName() << A;
+ return true;
+ }
+ return false;
+}
+
+/// \brief Check if IdxExpr is a valid parameter index for a function or
/// instance method D. May output an error.
///
/// \returns true if IdxExpr is a valid index.
-static bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D,
- StringRef AttrName,
- SourceLocation AttrLoc,
- unsigned AttrArgNum,
- const Expr *IdxExpr,
- uint64_t &Idx)
-{
+static bool checkFunctionOrMethodParameterIndex(Sema &S, const Decl *D,
+ const AttributeList &Attr,
+ unsigned AttrArgNum,
+ const Expr *IdxExpr,
+ uint64_t &Idx) {
assert(isFunctionOrMethod(D));
// In C++ the implicit 'this' function parameter also counts.
@@ -258,30 +224,30 @@
bool HP = hasFunctionProto(D);
bool HasImplicitThisParam = isInstanceMethod(D);
bool IV = HP && isFunctionOrMethodVariadic(D);
- unsigned NumArgs = (HP ? getFunctionOrMethodNumArgs(D) : 0) +
- HasImplicitThisParam;
+ unsigned NumParams =
+ (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam;
llvm::APSInt IdxInt;
if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
!IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) {
- 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();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
+ << Attr.getName() << AttrArgNum << AANT_ArgumentIntegerConstant
+ << IdxExpr->getSourceRange();
return false;
}
Idx = IdxInt.getLimitedValue();
- if (Idx < 1 || (!IV && Idx > NumArgs)) {
- S.Diag(AttrLoc, diag::err_attribute_argument_out_of_bounds)
- << AttrName << AttrArgNum << IdxExpr->getSourceRange();
+ if (Idx < 1 || (!IV && Idx > NumParams)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << Attr.getName() << AttrArgNum << IdxExpr->getSourceRange();
return false;
}
Idx--; // Convert to zero-based.
if (HasImplicitThisParam) {
if (Idx == 0) {
- S.Diag(AttrLoc,
+ S.Diag(Attr.getLoc(),
diag::err_attribute_invalid_implicit_this_argument)
- << AttrName << IdxExpr->getSourceRange();
+ << Attr.getName() << IdxExpr->getSourceRange();
return false;
}
--Idx;
@@ -326,17 +292,13 @@
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
-///
-static bool mayBeSharedVariable(const Decl *D) {
- if (isa<FieldDecl>(D))
- return true;
- if (const VarDecl *vd = dyn_cast<VarDecl>(D))
- return vd->hasGlobalStorage() && !vd->getTLSKind();
-
- return false;
+/// \brief Applies the given attribute to the Decl without performing any
+/// additional semantic checking.
+template <typename AttrType>
+static void handleSimpleAttribute(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ D->addAttr(::new (S.Context) AttrType(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
/// \brief Check if the passed-in expression is of type int or bool.
@@ -367,28 +329,24 @@
/// \return true if the Decl is a pointer type; false otherwise
static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
const AttributeList &Attr) {
- if (const ValueDecl *vd = dyn_cast<ValueDecl>(D)) {
- QualType QT = vd->getType();
- if (QT->isAnyPointerType())
+ const ValueDecl *vd = cast<ValueDecl>(D);
+ QualType QT = vd->getType();
+ if (QT->isAnyPointerType())
+ return true;
+
+ if (const RecordType *RT = QT->getAs<RecordType>()) {
+ // If it's an incomplete type, it could be a smart pointer; skip it.
+ // (We don't want to force template instantiation if we can avoid it,
+ // since that would alter the order in which templates are instantiated.)
+ if (RT->isIncompleteType())
return true;
- if (const RecordType *RT = QT->getAs<RecordType>()) {
- // If it's an incomplete type, it could be a smart pointer; skip it.
- // (We don't want to force template instantiation if we can avoid it,
- // since that would alter the order in which templates are instantiated.)
- if (RT->isIncompleteType())
- return true;
-
- if (threadSafetyCheckIsSmartPointer(S, RT))
- return true;
- }
-
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_pointer)
- << Attr.getName()->getName() << QT;
- } else {
- S.Diag(Attr.getLoc(), diag::err_attribute_can_be_applied_only_to_value_decl)
- << Attr.getName();
+ if (threadSafetyCheckIsSmartPointer(S, RT))
+ return true;
}
+
+ S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_pointer)
+ << Attr.getName() << QT;
return false;
}
@@ -405,65 +363,78 @@
return 0;
}
+static bool checkRecordTypeForCapability(Sema &S, const AttributeList &Attr,
+ QualType Ty) {
+ const RecordType *RT = getRecordType(Ty);
-static bool checkBaseClassIsLockableCallback(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *Unused) {
- const RecordType *RT = Specifier->getType()->getAs<RecordType>();
- if (RT->getDecl()->getAttr<LockableAttr>())
+ if (!RT)
+ return false;
+
+ // Don't check for the capability if the class hasn't been defined yet.
+ if (RT->isIncompleteType())
return true;
+
+ // Allow smart pointers to be used as capability objects.
+ // FIXME -- Check the type that the smart pointer points to.
+ if (threadSafetyCheckIsSmartPointer(S, RT))
+ return true;
+
+ // Check if the record itself has a capability.
+ RecordDecl *RD = RT->getDecl();
+ if (RD->hasAttr<CapabilityAttr>())
+ return true;
+
+ // Else check if any base classes have a capability.
+ if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
+ CXXBasePaths BPaths(false, false);
+ if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &P,
+ void *) {
+ return BS->getType()->getAs<RecordType>()
+ ->getDecl()->hasAttr<CapabilityAttr>();
+ }, 0, BPaths))
+ return true;
+ }
return false;
}
+static bool checkTypedefTypeForCapability(Sema &S, const AttributeList &Attr,
+ QualType Ty) {
+ const auto *TD = Ty->getAs<TypedefType>();
+ if (!TD)
+ return false;
-/// \brief Thread Safety Analysis: Checks that the passed in RecordType
-/// resolves to a lockable object.
-static void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr,
- QualType Ty) {
- const RecordType *RT = getRecordType(Ty);
+ TypedefNameDecl *TN = TD->getDecl();
+ if (!TN)
+ return false;
- // Warn if could not get record type for this argument.
- if (!RT) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_class)
- << Attr.getName() << Ty.getAsString();
- return;
- }
-
- // Don't check for lockable if the class hasn't been defined yet.
- if (RT->isIncompleteType())
- return;
-
- // Allow smart pointers to be used as lockable objects.
- // FIXME -- Check the type that the smart pointer points to.
- if (threadSafetyCheckIsSmartPointer(S, RT))
- return;
-
- // Check if the type is lockable.
- RecordDecl *RD = RT->getDecl();
- if (RD->getAttr<LockableAttr>())
- return;
-
- // Else check if any base classes are lockable.
- if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
- CXXBasePaths BPaths(false, false);
- if (CRD->lookupInBases(checkBaseClassIsLockableCallback, 0, BPaths))
- return;
- }
-
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
- << Attr.getName() << Ty.getAsString();
+ return TN->hasAttr<CapabilityAttr>();
}
-/// \brief Thread Safety Analysis: Checks that all attribute arguments, starting
-/// from Sidx, resolve to a lockable object.
+/// \brief Checks that the passed in type is qualified as a capability. This
+/// type can either be a struct, or a typedef to a built-in type (such as int).
+static void checkForCapability(Sema &S, const AttributeList &Attr,
+ QualType Ty) {
+ if (checkTypedefTypeForCapability(S, Attr, Ty))
+ return;
+
+ if (checkRecordTypeForCapability(S, Attr, Ty))
+ return;
+
+ S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
+ << Attr.getName() << Ty;
+}
+
+/// \brief Checks that all attribute arguments, starting from Sidx, resolve to
+/// a capability object.
/// \param Sidx The attribute argument index to start checking with.
/// \param ParamIdxOk Whether an argument can be indexing into a function
/// parameter list.
-static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
- const AttributeList &Attr,
- SmallVectorImpl<Expr*> &Args,
- int Sidx = 0,
- bool ParamIdxOk = false) {
- for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) {
+static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
+ const AttributeList &Attr,
+ SmallVectorImpl<Expr *> &Args,
+ int Sidx = 0,
+ bool ParamIdxOk = false) {
+ for (unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) {
Expr *ArgExp = Attr.getArgAsExpr(Idx);
if (ArgExp->isTypeDependent()) {
@@ -499,7 +470,7 @@
if (DRE->getDecl()->isCXXInstanceMember())
ArgTy = DRE->getDecl()->getType();
- // First see if we can just cast to record type, or point to record type.
+ // First see if we can just cast to record type, or pointer to record type.
const RecordType *RT = getRecordType(ArgTy);
// Now check if we index into a record type function param.
@@ -520,7 +491,7 @@
}
}
- checkForLockableRecord(S, D, Attr, ArgTy);
+ checkForCapability(S, Attr, ArgTy);
Args.push_back(ArgExp);
}
@@ -534,38 +505,8 @@
// least add some helper functions to check most argument patterns (#
// and types of args).
-enum ThreadAttributeDeclKind {
- ThreadExpectedFieldOrGlobalVar,
- ThreadExpectedFunctionOrMethod,
- ThreadExpectedClassOrStruct
-};
-
-static bool checkGuardedVarAttrCommon(Sema &S, Decl *D,
- const AttributeList &Attr) {
- // 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)
- << Attr.getName() << ThreadExpectedFieldOrGlobalVar;
- return false;
- }
-
- return true;
-}
-
-static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkGuardedVarAttrCommon(S, D, Attr))
- return;
-
- D->addAttr(::new (S.Context)
- GuardedVarAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handlePtGuardedVarAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (!checkGuardedVarAttrCommon(S, D, Attr))
- return;
-
if (!threadSafetyCheckIsPointer(S, D, Attr))
return;
@@ -577,16 +518,9 @@
static bool checkGuardedByAttrCommon(Sema &S, Decl *D,
const AttributeList &Attr,
Expr* &Arg) {
- // 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)
- << Attr.getName() << ThreadExpectedFieldOrGlobalVar;
- return false;
- }
-
SmallVector<Expr*, 1> Args;
// check that all arguments are lockable objects
- checkAttrArgsAreLockableObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
unsigned Size = Args.size();
if (Size != 1)
return false;
@@ -601,7 +535,8 @@
if (!checkGuardedByAttrCommon(S, D, Attr, Arg))
return;
- D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg));
+ D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg,
+ Attr.getAttributeSpellingListIndex()));
}
static void handlePtGuardedByAttr(Sema &S, Decl *D,
@@ -614,85 +549,8 @@
return;
D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(),
- S.Context, Arg));
-}
-
-static bool checkLockableAttrCommon(Sema &S, Decl *D,
- const AttributeList &Attr) {
- // FIXME: Lockable structs for C code.
- if (!isa<RecordDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedClassOrStruct;
- return false;
- }
-
- return true;
-}
-
-static void handleLockableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkLockableAttrCommon(S, D, Attr))
- return;
-
- D->addAttr(::new (S.Context) LockableAttr(Attr.getRange(), S.Context));
-}
-
-static void handleScopedLockableAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!checkLockableAttrCommon(S, D, Attr))
- return;
-
- D->addAttr(::new (S.Context)
- ScopedLockableAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleNoThreadSafetyAnalysis(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context) NoThreadSafetyAnalysisAttr(Attr.getRange(),
- S.Context));
-}
-
-static void handleNoSanitizeAddressAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context)
- NoSanitizeAddressAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleNoSanitizeMemory(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context) NoSanitizeMemoryAttr(Attr.getRange(),
- S.Context));
-}
-
-static void handleNoSanitizeThread(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context) NoSanitizeThreadAttr(Attr.getRange(),
- S.Context));
+ S.Context, Arg,
+ Attr.getAttributeSpellingListIndex()));
}
static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
@@ -701,19 +559,11 @@
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return false;
- // D must be either a member field or global (potentially shared) variable.
- ValueDecl *VD = dyn_cast<ValueDecl>(D);
- if (!VD || !mayBeSharedVariable(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFieldOrGlobalVar;
- return false;
- }
-
// Check that this attribute only applies to lockable types.
- QualType QT = VD->getType();
+ QualType QT = cast<ValueDecl>(D)->getType();
if (!QT->isDependentType()) {
const RecordType *RT = getRecordType(QT);
- if (!RT || !RT->getDecl()->getAttr<LockableAttr>()) {
+ if (!RT || !RT->getDecl()->hasAttr<CapabilityAttr>()) {
S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
<< Attr.getName();
return false;
@@ -721,7 +571,7 @@
}
// Check that all arguments are lockable objects.
- checkAttrArgsAreLockableObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
if (Args.empty())
return false;
@@ -758,47 +608,12 @@
const AttributeList &Attr,
SmallVectorImpl<Expr *> &Args) {
// zero or more arguments ok
-
- // check that the attribute is applied to a function
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFunctionOrMethod;
- return false;
- }
-
// check that all arguments are lockable objects
- checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
return true;
}
-static void handleSharedLockFunctionAttr(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)
- SharedLockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleExclusiveLockFunctionAttr(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)
- ExclusiveLockFunctionAttr(Attr.getRange(), S.Context,
- StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleAssertSharedLockAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
SmallVector<Expr*, 1> Args;
@@ -833,12 +648,6 @@
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return false;
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFunctionOrMethod;
- return false;
- }
-
if (!isIntOrBool(Attr.getArgAsExpr(0))) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
<< Attr.getName() << 1 << AANT_ArgumentIntOrBool;
@@ -846,7 +655,7 @@
}
// check that all arguments are lockable objects
- checkAttrArgsAreLockableObjs(S, D, Attr, Args, 1);
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 1);
return true;
}
@@ -877,84 +686,11 @@
Attr.getAttributeSpellingListIndex()));
}
-static bool checkLocksRequiredCommon(Sema &S, Decl *D,
- const AttributeList &Attr,
- SmallVectorImpl<Expr *> &Args) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
- return false;
-
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFunctionOrMethod;
- return false;
- }
-
- // check that all arguments are lockable objects
- checkAttrArgsAreLockableObjs(S, D, Attr, Args);
- if (Args.empty())
- return false;
-
- return true;
-}
-
-static void handleExclusiveLocksRequiredAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkLocksRequiredCommon(S, D, Attr, Args))
- return;
-
- Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context)
- ExclusiveLocksRequiredAttr(Attr.getRange(), S.Context,
- StartArg, Args.size(),
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleSharedLocksRequiredAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkLocksRequiredCommon(S, D, Attr, Args))
- return;
-
- Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context)
- SharedLocksRequiredAttr(Attr.getRange(), S.Context,
- StartArg, Args.size(),
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleUnlockFunAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- // zero or more arguments ok
-
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFunctionOrMethod;
- return;
- }
-
- // check that all arguments are lockable objects
- SmallVector<Expr*, 1> Args;
- checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
- unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? 0 : &Args[0];
-
- D->addAttr(::new (S.Context)
- UnlockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleLockReturnedAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)
- << Attr.getName() << ThreadExpectedFunctionOrMethod;
- return;
- }
-
// check that the argument is lockable object
SmallVector<Expr*, 1> Args;
- checkAttrArgsAreLockableObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
unsigned Size = Args.size();
if (Size == 0)
return;
@@ -969,15 +705,9 @@
if (!checkAttributeAtLeastNumArgs(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;
- return;
- }
-
// check that all arguments are lockable objects
SmallVector<Expr*, 1> Args;
- checkAttrArgsAreLockableObjs(S, D, Attr, Args);
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
unsigned Size = Args.size();
if (Size == 0)
return;
@@ -988,6 +718,34 @@
Attr.getAttributeSpellingListIndex()));
}
+static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ Expr *Cond = Attr.getArgAsExpr(0);
+ if (!Cond->isTypeDependent()) {
+ ExprResult Converted = S.PerformContextuallyConvertToBool(Cond);
+ if (Converted.isInvalid())
+ return;
+ Cond = Converted.take();
+ }
+
+ StringRef Msg;
+ if (!S.checkStringLiteralArgumentAttr(Attr, 1, Msg))
+ return;
+
+ SmallVector<PartialDiagnosticAt, 8> Diags;
+ if (!Cond->isValueDependent() &&
+ !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D),
+ Diags)) {
+ S.Diag(Attr.getLoc(), diag::err_enable_if_never_constant_expr);
+ for (int I = 0, N = Diags.size(); I != N; ++I)
+ S.Diag(Diags[I].first, Diags[I].second);
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ EnableIfAttr(Attr.getRange(), S.Context, Cond, Msg,
+ Attr.getAttributeSpellingListIndex()));
+}
+
static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
ConsumableAttr::ConsumedState DefaultState;
@@ -1004,18 +762,13 @@
<< 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();
@@ -1038,12 +791,6 @@
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;
@@ -1076,13 +823,7 @@
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)) {
@@ -1123,12 +864,6 @@
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)) {
@@ -1179,12 +914,6 @@
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;
@@ -1214,12 +943,6 @@
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;
@@ -1245,21 +968,14 @@
static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,
const AttributeList &Attr) {
- TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
- if (TD == 0) {
- // __attribute__((ext_vector_type(N))) can only be applied to typedefs
- // and type-ids.
- S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
- return;
- }
-
// Remember this typedef decl, we will need it later for diagnostics.
- S.ExtVectorDecls.push_back(TD);
+ S.ExtVectorDecls.push_back(cast<TypedefNameDecl>(D));
}
static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (TagDecl *TD = dyn_cast<TagDecl>(D))
- TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context));
+ TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
// If the alignment is less than or equal to 8 bits, the packed attribute
// has no effect.
@@ -1276,28 +992,6 @@
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
-static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (RecordDecl *RD = dyn_cast<RecordDecl>(D))
- RD->addAttr(::new (S.Context)
- MsStructAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
-}
-
-static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) {
- // The IBAction attributes only apply to instance methods.
- if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
- if (MD->isInstanceMethod()) {
- D->addAttr(::new (S.Context)
- IBActionAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- return;
- }
-
- S.Diag(Attr.getLoc(), diag::warn_attribute_ibaction) << Attr.getName();
-}
-
static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) {
// The IBOutlet/IBOutletCollection attributes only apply to instance
// variables or properties of Objective-C classes. The outlet must also
@@ -1384,9 +1078,8 @@
if (const RecordType *UT = T->getAsUnionType())
if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
RecordDecl *UD = UT->getDecl();
- for (RecordDecl::field_iterator it = UD->field_begin(),
- itend = UD->field_end(); it != itend; ++it) {
- QualType QT = it->getType();
+ for (const auto *I : UD->fields()) {
+ QualType QT = I->getType();
if (QT->isAnyPointerType() || QT->isBlockPointerType()) {
T = QT;
return;
@@ -1395,74 +1088,34 @@
}
}
-static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isFunctionOrMethod(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
+static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr,
+ SourceRange R, bool isReturnValue = false) {
+ T = T.getNonReferenceType();
+ possibleTransparentUnionPointerType(T);
+
+ if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
+ S.Diag(Attr.getLoc(),
+ isReturnValue ? diag::warn_attribute_return_pointers_only
+ : diag::warn_attribute_pointers_only)
+ << Attr.getName() << R;
+ return false;
}
-
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
- return;
-
- SmallVector<unsigned, 8> SizeArgs;
- 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;
-
- // check if the function argument is of an integer type
- QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType();
- if (!T->isIntegerType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << Ex->getSourceRange();
- return;
- }
- 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)
- << Attr.getName() << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange();
- }
-
- D->addAttr(::new (S.Context)
- AllocSizeAttr(Attr.getRange(), S.Context,
- SizeArgs.data(), SizeArgs.size(),
- Attr.getAttributeSpellingListIndex()));
+ return true;
}
static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // GCC ignores the nonnull attribute on K&R style function prototypes, so we
- // ignore it as well
- if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
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))
+ if (!checkFunctionOrMethodParameterIndex(S, D, Attr, i + 1, Ex, Idx))
return;
// Is the function argument a pointer type?
- QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType();
- possibleTransparentUnionPointerType(T);
-
- if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
- // FIXME: Should also highlight argument in decl.
- S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only)
- << "nonnull" << Ex->getSourceRange();
+ // FIXME: Should also highlight argument in decl in the diagnostic.
+ if (!attrNonNullArgCheck(S, getFunctionOrMethodParamType(D, Idx), Attr,
+ Ex->getSourceRange()))
continue;
- }
NonNullArgs.push_back(Idx);
}
@@ -1470,8 +1123,8 @@
// If no arguments were specified to __attribute__((nonnull)) then all pointer
// arguments have a nonnull attribute.
if (NonNullArgs.empty()) {
- for (unsigned i = 0, e = getFunctionOrMethodNumArgs(D); i != e; ++i) {
- QualType T = getFunctionOrMethodArgType(D, i).getNonReferenceType();
+ for (unsigned i = 0, e = getFunctionOrMethodNumParams(D); i != e; ++i) {
+ QualType T = getFunctionOrMethodParamType(D, i).getNonReferenceType();
possibleTransparentUnionPointerType(T);
if (T->isAnyPointerType() || T->isBlockPointerType())
NonNullArgs.push_back(i);
@@ -1495,13 +1148,37 @@
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'";
+static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D,
+ const AttributeList &Attr) {
+ if (Attr.getNumArgs() > 0) {
+ if (D->getFunctionType()) {
+ handleNonNullAttr(S, D, Attr);
+ } else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_parm_no_args)
+ << D->getSourceRange();
+ }
+ return;
}
- llvm_unreachable("unknown ownership");
+
+ // Is the argument a pointer type?
+ if (!attrNonNullArgCheck(S, D->getType(), Attr, D->getSourceRange()))
+ return;
+
+ D->addAttr(::new (S.Context)
+ NonNullAttr(Attr.getRange(), S.Context, 0, 0,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleReturnsNonNullAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ QualType ResultType = getFunctionOrMethodResultType(D);
+ if (!attrNonNullArgCheck(S, ResultType, Attr, Attr.getRange(),
+ /* isReturnValue */ true))
+ return;
+
+ D->addAttr(::new (S.Context)
+ ReturnsNonNullAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
@@ -1519,58 +1196,49 @@
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() < 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() < 2) {
- S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2;
- return;
- }
- break;
- case AttributeList::AT_ownership_returns:
- K = OwnershipAttr::Returns;
+ // Figure out our Kind.
+ OwnershipAttr::OwnershipKind K =
+ OwnershipAttr(AL.getLoc(), S.Context, 0, 0, 0,
+ AL.getAttributeSpellingListIndex()).getOwnKind();
+ // Check arguments.
+ switch (K) {
+ case OwnershipAttr::Takes:
+ case OwnershipAttr::Holds:
+ if (AL.getNumArgs() < 2) {
+ S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments)
+ << AL.getName() << 2;
+ return;
+ }
+ break;
+ case OwnershipAttr::Returns:
if (AL.getNumArgs() > 2) {
- S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << 1;
+ S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments)
+ << AL.getName() << 1;
return;
}
break;
- default:
- // This should never happen given how we are called.
- llvm_unreachable("Unknown ownership attribute");
}
- if (!isFunction(D) || !hasFunctionProto(D)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL.getName() << ExpectedFunction;
- return;
- }
-
- StringRef Module = AL.getArgAsIdent(0)->Ident->getName();
+ IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident;
// Normalize the argument, __foo__ becomes foo.
- if (Module.startswith("__") && Module.endswith("__"))
- Module = Module.substr(2, Module.size() - 4);
+ StringRef ModuleName = Module->getName();
+ if (ModuleName.startswith("__") && ModuleName.endswith("__") &&
+ ModuleName.size() > 4) {
+ ModuleName = ModuleName.drop_front(2).drop_back(2);
+ Module = &S.PP.getIdentifierTable().get(ModuleName);
+ }
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))
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, i, Ex, Idx))
return;
// Is the function argument a pointer type?
- QualType T = getFunctionOrMethodArgType(D, Idx);
+ QualType T = getFunctionOrMethodParamType(D, Idx);
int Err = -1; // No error
switch (K) {
case OwnershipAttr::Takes:
@@ -1590,13 +1258,13 @@
}
// 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 && (*i)->args_end() !=
- std::find((*i)->args_begin(), (*i)->args_end(), Idx)) {
+ for (const auto *I : D->specific_attrs<OwnershipAttr>()) {
+ // FIXME: A returns attribute should conflict with any returns attribute
+ // with a different index too.
+ 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());
+ << AL.getName() << I;
return;
}
}
@@ -1608,7 +1276,7 @@
llvm::array_pod_sort(start, start + size);
D->addAttr(::new (S.Context)
- OwnershipAttr(AL.getLoc(), S.Context, K, Module, start, size,
+ OwnershipAttr(AL.getLoc(), S.Context, Module, start, size,
AL.getAttributeSpellingListIndex()));
}
@@ -1620,12 +1288,6 @@
return;
}
- if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariableOrFunction;
- return;
- }
-
NamedDecl *nd = cast<NamedDecl>(D);
// gcc rejects
@@ -1640,8 +1302,8 @@
// we reject them
const DeclContext *Ctx = D->getDeclContext()->getRedeclContext();
if (!Ctx->isFileContext()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) <<
- nd->getNameAsString();
+ S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context)
+ << nd;
return;
}
@@ -1698,77 +1360,22 @@
Attr.getAttributeSpellingListIndex()));
}
-static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context)
- MinSizeAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
+ if (checkAttrMutualExclusion<HotAttr>(S, D, Attr))
return;
- }
-
- if (D->hasAttr<HotAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << Attr.getName() << "hot";
- return;
- }
D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
}
static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
+ if (checkAttrMutualExclusion<ColdAttr>(S, D, Attr))
return;
- }
-
- if (D->hasAttr<ColdAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << Attr.getName() << "cold";
- return;
- }
D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
}
-static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
- D->addAttr(::new (S.Context)
- NakedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleAlwaysInlineAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
- D->addAttr(::new (S.Context)
- AlwaysInlineAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleTLSModelAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
StringRef Model;
@@ -1777,12 +1384,6 @@
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)
- << Attr.getName() << ExpectedTLSVar;
- return;
- }
-
// Check that the value.
if (Model != "global-dynamic" && Model != "local-dynamic"
&& Model != "initial-exec" && Model != "local-exec") {
@@ -1795,9 +1396,19 @@
Attr.getAttributeSpellingListIndex()));
}
+static void handleKernelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (S.LangOpts.Renderscript) {
+ D->addAttr(::new (S.Context)
+ KernelAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+ } else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "kernel";
+ }
+}
+
static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- QualType RetTy = FD->getResultType();
+ QualType RetTy = FD->getReturnType();
if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
D->addAttr(::new (S.Context)
MallocAttr(Attr.getRange(), S.Context,
@@ -1809,35 +1420,15 @@
S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
}
-static void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- D->addAttr(::new (S.Context)
- MayAliasAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (isa<VarDecl>(D))
- D->addAttr(::new (S.Context)
- NoCommonAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariable;
-}
-
static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.CPlusPlus) {
- S.Diag(Attr.getLoc(), diag::err_common_not_supported_cplusplus);
+ S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
+ << Attr.getName() << AttributeLangSupport::Cpp;
return;
}
- if (isa<VarDecl>(D))
- D->addAttr(::new (S.Context)
- CommonAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariable;
+ D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) {
@@ -1887,23 +1478,6 @@
Attr.getAttributeSpellingListIndex()));
}
-static void handleCXX11NoReturnAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- // C++11 [dcl.attr.noreturn]p1:
- // The attribute may be applied to the declarator-id in a function
- // declaration.
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context)
- CXX11NoReturnAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
// PS3 PPU-specific.
static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) {
/*
@@ -1929,14 +1503,8 @@
return result; // This will be returned in a register
}
*/
- if (!isa<RecordDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedClass;
- return;
- }
-
- if (D->getAttr<VecReturnAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn";
+ if (VecReturnAttr *A = D->getAttr<VecReturnAttr>()) {
+ S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << A;
return;
}
@@ -1953,9 +1521,8 @@
return;
}
- for (RecordDecl::field_iterator iter = record->field_begin();
- iter != record->field_end(); iter++) {
- if ((count == 1) || !iter->getType()->isVectorType()) {
+ for (const auto *I : record->fields()) {
+ if ((count == 1) || !I->getType()->isVectorType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
return;
}
@@ -1977,10 +1544,6 @@
diag::err_carries_dependency_param_not_function_decl);
return;
}
- } else if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionMethodOrParameter;
- return;
}
D->addAttr(::new (S.Context) CarriesDependencyAttr(
@@ -1988,36 +1551,10 @@
Attr.getAttributeSpellingListIndex()));
}
-static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- 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)
- << Attr.getName() << ExpectedVariableFunctionOrLabel;
- return;
- }
-
- D->addAttr(::new (S.Context)
- UnusedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleReturnsTwiceAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
- D->addAttr(::new (S.Context)
- ReturnsTwiceAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasLocalStorage()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used";
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
return;
}
} else if (!isFunctionOrMethod(D)) {
@@ -2034,29 +1571,15 @@
static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// check the attribute arguments.
if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 1;
return;
}
- int priority = 65535; // FIXME: Do not hardcode such constants.
- if (Attr.getNumArgs() > 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_type)
- << Attr.getName() << 1 << AANT_ArgumentIntegerConstant
- << E->getSourceRange();
- return;
- }
- priority = Idx.getZExtValue();
- }
-
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
+ uint32_t priority = ConstructorAttr::DefaultPriority;
+ if (Attr.getNumArgs() > 0 &&
+ !checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
return;
- }
D->addAttr(::new (S.Context)
ConstructorAttr(Attr.getRange(), S.Context, priority,
@@ -2066,29 +1589,15 @@
static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// check the attribute arguments.
if (Attr.getNumArgs() > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 1;
return;
}
- int priority = 65535; // FIXME: Do not hardcode such constants.
- if (Attr.getNumArgs() > 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_type)
- << Attr.getName() << 1 << AANT_ArgumentIntegerConstant
- << E->getSourceRange();
- return;
- }
- priority = Idx.getZExtValue();
- }
-
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
+ uint32_t priority = DestructorAttr::DefaultPriority;
+ if (Attr.getNumArgs() > 0 &&
+ !checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
return;
- }
D->addAttr(::new (S.Context)
DestructorAttr(Attr.getRange(), S.Context, priority,
@@ -2100,7 +1609,8 @@
const AttributeList &Attr) {
unsigned NumArgs = Attr.getNumArgs();
if (NumArgs > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 1;
return;
}
@@ -2113,38 +1623,19 @@
Attr.getAttributeSpellingListIndex()));
}
-static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) {
+ S.Diag(Attr.getLoc(), diag::err_objc_attr_protocol_requires_definition)
+ << Attr.getName() << Attr.getRange();
+ return;
+ }
+
D->addAttr(::new (S.Context)
- ArcWeakrefUnavailableAttr(Attr.getRange(), S.Context,
+ ObjCExplicitProtocolImplAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
}
-static void handleObjCRootClassAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<ObjCInterfaceDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedObjectiveCInterface;
- return;
- }
-
- D->addAttr(::new (S.Context)
- ObjCRootClassAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<ObjCInterfaceDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_suppress_autosynthesis);
- return;
- }
-
- D->addAttr(::new (S.Context)
- ObjCRequiresPropertyDefsAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static bool checkAvailabilityAttr(Sema &S, SourceRange Range,
IdentifierInfo *Platform,
VersionTuple Introduced,
@@ -2450,13 +1941,7 @@
static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
const AttributeList &Attr) {
- ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(decl);
- if (!method) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << ExpectedMethod;
- return;
- }
-
+ ObjCMethodDecl *method = cast<ObjCMethodDecl>(decl);
if (!Attr.isArgIdent(0)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
<< Attr.getName() << 1 << AANT_ArgumentIdentifier;
@@ -2471,30 +1956,17 @@
return;
}
- if (F == ObjCMethodFamilyAttr::OMF_init &&
- !method->getResultType()->isObjCObjectPointerType()) {
+ if (F == ObjCMethodFamilyAttr::OMF_init &&
+ !method->getReturnType()->isObjCObjectPointerType()) {
S.Diag(method->getLocation(), diag::err_init_method_bad_return_type)
- << method->getResultType();
+ << method->getReturnType();
// Ignore the attribute.
return;
}
method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(),
- S.Context, F));
-}
-
-static void handleObjCExceptionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D);
- if (OCI == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedObjectiveCInterface;
- return;
- }
-
- D->addAttr(::new (S.Context)
- ObjCExceptionAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ S.Context, F,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -2526,18 +1998,6 @@
Attr.getAttributeSpellingListIndex()));
}
-static void
-handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function);
- return;
- }
-
- D->addAttr(::new (S.Context)
- OverloadableAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!Attr.isArgIdent(0)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
@@ -2561,11 +2021,12 @@
static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// check the attribute arguments.
if (Attr.getNumArgs() > 2) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2;
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 2;
return;
}
- unsigned sentinel = 0;
+ unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel;
if (Attr.getNumArgs() > 0) {
Expr *E = Attr.getArgAsExpr(0);
llvm::APSInt Idx(32);
@@ -2586,7 +2047,7 @@
sentinel = Idx.getZExtValue();
}
- unsigned nullPos = 0;
+ unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos;
if (Attr.getNumArgs() > 1) {
Expr *E = Attr.getArgAsExpr(1);
llvm::APSInt Idx(32);
@@ -2632,7 +2093,8 @@
} else if (const VarDecl *V = dyn_cast<VarDecl>(D)) {
QualType Ty = V->getType();
if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
- const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(D)
+ const FunctionType *FT = Ty->isFunctionPointerType()
+ ? D->getFunctionType()
: Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
if (!cast<FunctionProtoType>(FT)->isVariadic()) {
int m = Ty->isFunctionPointerType() ? 0 : 1;
@@ -2654,27 +2116,15 @@
Attr.getAttributeSpellingListIndex()));
}
-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;
- return;
- }
-
- if (isFunction(D) && getFunctionType(D)->getResultType()->isVoidType()) {
+ if (D->getFunctionType() &&
+ D->getFunctionType()->getReturnType()->isVoidType()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
<< Attr.getName() << 0;
return;
}
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
- if (MD->getResultType()->isVoidType()) {
+ if (MD->getReturnType()->isVoidType()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
<< Attr.getName() << 1;
return;
@@ -2685,24 +2135,6 @@
Attr.getAttributeSpellingListIndex()));
}
-static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) {
- if (isa<CXXRecordDecl>(D)) {
- D->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context));
- return;
- }
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariableOrFunction;
- return;
- }
-
- NamedDecl *nd = cast<NamedDecl>(D);
-
- nd->addAttr(::new (S.Context)
- WeakAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// weak_import only applies to variable & function declarations.
bool isDef = false;
@@ -2727,59 +2159,26 @@
}
// Handles reqd_work_group_size and work_group_size_hint.
+template <typename WorkGroupAttr>
static void handleWorkGroupSize(Sema &S, Decl *D,
const AttributeList &Attr) {
- unsigned WGSize[3];
- for (unsigned i = 0; i < 3; ++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_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << E->getSourceRange();
+ uint32_t WGSize[3];
+ for (unsigned i = 0; i < 3; ++i)
+ if (!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(i), WGSize[i], i))
return;
- }
- WGSize[i] = (unsigned) ArgNum.getZExtValue();
- }
- if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize
- && D->hasAttr<ReqdWorkGroupSizeAttr>()) {
- ReqdWorkGroupSizeAttr *A = D->getAttr<ReqdWorkGroupSizeAttr>();
- if (!(A->getXDim() == WGSize[0] &&
- A->getYDim() == WGSize[1] &&
- A->getZDim() == WGSize[2])) {
- S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) <<
- Attr.getName();
- }
- }
+ WorkGroupAttr *Existing = D->getAttr<WorkGroupAttr>();
+ if (Existing && !(Existing->getXDim() == WGSize[0] &&
+ Existing->getYDim() == WGSize[1] &&
+ Existing->getZDim() == WGSize[2]))
+ S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
- if (Attr.getKind() == AttributeList::AT_WorkGroupSizeHint
- && D->hasAttr<WorkGroupSizeHintAttr>()) {
- WorkGroupSizeHintAttr *A = D->getAttr<WorkGroupSizeHintAttr>();
- if (!(A->getXDim() == WGSize[0] &&
- A->getYDim() == WGSize[1] &&
- A->getZDim() == WGSize[2])) {
- S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) <<
- Attr.getName();
- }
- }
-
- if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize)
- D->addAttr(::new (S.Context)
- ReqdWorkGroupSizeAttr(Attr.getRange(), S.Context,
- WGSize[0], WGSize[1], WGSize[2],
- Attr.getAttributeSpellingListIndex()));
- else
- D->addAttr(::new (S.Context)
- WorkGroupSizeHintAttr(Attr.getRange(), S.Context,
- WGSize[0], WGSize[1], WGSize[2],
+ D->addAttr(::new (S.Context) WorkGroupAttr(Attr.getRange(), S.Context,
+ WGSize[0], WGSize[1], WGSize[2],
Attr.getAttributeSpellingListIndex()));
}
static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) {
- assert(Attr.getKind() == AttributeList::AT_VecTypeHint);
-
if (!Attr.hasParsedType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
<< Attr.getName() << 1;
@@ -2798,9 +2197,7 @@
return;
}
- if (Attr.getKind() == AttributeList::AT_VecTypeHint &&
- D->hasAttr<VecTypeHintAttr>()) {
- VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>();
+ if (VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>()) {
if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) {
S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
return;
@@ -2808,7 +2205,8 @@
}
D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context,
- ParmTSI));
+ ParmTSI,
+ Attr.getAttributeSpellingListIndex()));
}
SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
@@ -2841,12 +2239,6 @@
return;
}
- // This attribute cannot be applied to local variables.
- if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) {
- S.Diag(LiteralLoc, diag::err_attribute_section_local_variable);
- return;
- }
-
unsigned Index = Attr.getAttributeSpellingListIndex();
SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), Str, Index);
if (NewAttr)
@@ -2854,37 +2246,9 @@
}
-static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (NoThrowAttr *Existing = D->getAttr<NoThrowAttr>()) {
- if (Existing->getLocation().isInvalid())
- Existing->setRange(Attr.getRange());
- } else {
- D->addAttr(::new (S.Context)
- NoThrowAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- }
-}
-
-static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (ConstAttr *Existing = D->getAttr<ConstAttr>()) {
- if (Existing->getLocation().isInvalid())
- Existing->setRange(Attr.getRange());
- } else {
- D->addAttr(::new (S.Context)
- ConstAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex() ));
- }
-}
-
-static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- D->addAttr(::new (S.Context)
- PureAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- VarDecl *VD = dyn_cast<VarDecl>(D);
- if (!VD || !VD->hasLocalStorage()) {
+ VarDecl *VD = cast<VarDecl>(D);
+ if (!VD->hasLocalStorage()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
return;
}
@@ -2948,20 +2312,13 @@
/// 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 (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
Expr *IdxExpr = Attr.getArgAsExpr(0);
- uint64_t ArgIdx;
- if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(),
- Attr.getLoc(), 1, IdxExpr, ArgIdx))
+ uint64_t Idx;
+ if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 1, IdxExpr, Idx))
return;
// make sure the format string is really a string
- QualType Ty = getFunctionOrMethodArgType(D, ArgIdx);
+ QualType Ty = getFunctionOrMethodParamType(D, Idx);
bool not_nsstring_type = !isNSStringType(Ty, S.Context);
if (not_nsstring_type &&
@@ -2986,7 +2343,7 @@
return;
}
- // We cannot use the ArgIdx returned from checkFunctionOrMethodArgumentIndex
+ // We cannot use the Idx returned from checkFunctionOrMethodParameterIndex
// because that has corrected for the implicit this parameter, and is zero-
// based. The attribute expects what the user wrote explicitly.
llvm::APSInt Val;
@@ -3033,12 +2390,12 @@
return;
}
- if (!isa<VarDecl>(D) || S.getCurFunctionOrMethodDecl()) {
+ if (S.getCurFunctionOrMethodDecl()) {
S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
Attr.setInvalid();
return;
}
- QualType T = dyn_cast<VarDecl>(D)->getType();
+ QualType T = cast<VarDecl>(D)->getType();
if (S.Context.getAsArrayType(T))
T = S.Context.getBaseElementType(T);
if (!T->getAs<RecordType>()) {
@@ -3046,22 +2403,17 @@
Attr.setInvalid();
return;
}
-
- 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_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << priorityExpr->getSourceRange();
+
+ Expr *E = Attr.getArgAsExpr(0);
+ uint32_t prioritynum;
+ if (!checkUInt32Argument(S, Attr, E, prioritynum)) {
Attr.setInvalid();
return;
}
- unsigned prioritynum = priority.getZExtValue();
+
if (prioritynum < 101 || prioritynum > 65535) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range)
- << priorityExpr->getSourceRange();
+ << E->getSourceRange();
Attr.setInvalid();
return;
}
@@ -3075,18 +2427,14 @@
int FirstArg,
unsigned AttrSpellingListIndex) {
// Check whether we already have an equivalent format attribute.
- for (specific_attr_iterator<FormatAttr>
- i = D->specific_attr_begin<FormatAttr>(),
- e = D->specific_attr_end<FormatAttr>();
- i != e ; ++i) {
- FormatAttr *f = *i;
- if (f->getType() == Format &&
- f->getFormatIdx() == FormatIdx &&
- f->getFirstArg() == FirstArg) {
+ for (auto *F : D->specific_attrs<FormatAttr>()) {
+ if (F->getType() == Format &&
+ F->getFormatIdx() == FormatIdx &&
+ F->getFirstArg() == FirstArg) {
// If we don't have a valid location for this attribute, adopt the
// location.
- if (f->getLocation().isInvalid())
- f->setRange(Range);
+ if (F->getLocation().isInvalid())
+ F->setRange(Range);
return NULL;
}
}
@@ -3104,17 +2452,10 @@
return;
}
- if (!isFunctionOrMethodOrBlock(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;
+ unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam;
IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
StringRef Format = II->getName();
@@ -3134,29 +2475,24 @@
if (Kind == InvalidFormat) {
S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
- << "format" << II->getName();
+ << Attr.getName() << II->getName();
return;
}
// checks for the 2nd argument
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_type)
- << Attr.getName() << 2 << AANT_ArgumentIntegerConstant
- << IdxExpr->getSourceRange();
+ uint32_t Idx;
+ if (!checkUInt32Argument(S, Attr, IdxExpr, Idx, 2))
return;
- }
- if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
+ if (Idx < 1 || Idx > NumArgs) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << "format" << 2 << IdxExpr->getSourceRange();
+ << Attr.getName() << 2 << IdxExpr->getSourceRange();
return;
}
// FIXME: Do we need to bounds check?
- unsigned ArgIdx = Idx.getZExtValue() - 1;
+ unsigned ArgIdx = Idx - 1;
if (HasImplicitThisParam) {
if (ArgIdx == 0) {
@@ -3169,7 +2505,7 @@
}
// make sure the format string is really a string
- QualType Ty = getFunctionOrMethodArgType(D, ArgIdx);
+ QualType Ty = getFunctionOrMethodParamType(D, ArgIdx);
if (Kind == CFStringFormat) {
if (!isCFStringType(Ty, S.Context)) {
@@ -3196,14 +2532,9 @@
// check the 3rd argument
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_type)
- << Attr.getName() << 3 << AANT_ArgumentIntegerConstant
- << FirstArgExpr->getSourceRange();
+ uint32_t FirstArg;
+ if (!checkUInt32Argument(S, Attr, FirstArgExpr, FirstArg, 3))
return;
- }
// check if the function is variadic if the 3rd argument non-zero
if (FirstArg != 0) {
@@ -3226,13 +2557,12 @@
// if 0 it disables parameter checking (to use with e.g. va_list)
} else if (FirstArg != 0 && FirstArg != NumArgs) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << "format" << 3 << FirstArgExpr->getSourceRange();
+ << Attr.getName() << 3 << FirstArgExpr->getSourceRange();
return;
}
FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), II,
- Idx.getZExtValue(),
- FirstArg.getZExtValue(),
+ Idx, FirstArg,
Attr.getAttributeSpellingListIndex());
if (NewAttr)
D->addAttr(NewAttr);
@@ -3280,8 +2610,13 @@
uint64_t FirstAlign = S.Context.getTypeAlign(FirstType);
for (; Field != FieldEnd; ++Field) {
QualType FieldType = Field->getType();
+ // FIXME: this isn't fully correct; we also need to test whether the
+ // members of the union would all have the same calling convention as the
+ // first member of the union. Checking just the size and alignment isn't
+ // sufficient (consider structs passed on the stack instead of in registers
+ // as an example).
if (S.Context.getTypeSize(FieldType) != FirstSize ||
- S.Context.getTypeAlign(FieldType) != FirstAlign) {
+ S.Context.getTypeAlign(FieldType) > FirstAlign) {
// Warn if we drop the attribute.
bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType)
@@ -3310,10 +2645,8 @@
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() == Str)
+ for (const auto *I : D->specific_attrs<AnnotateAttr>()) {
+ if (I->getAnnotation() == Str)
return;
}
@@ -3380,15 +2713,14 @@
if (FD->isBitField())
DiagKind = 3;
} else if (!isa<TagDecl>(D)) {
- Diag(AttrLoc, diag::err_attribute_wrong_decl_type)
- << (TmpAttr.isC11() ? "'_Alignas'" : "'alignas'")
+ Diag(AttrLoc, diag::err_attribute_wrong_decl_type) << &TmpAttr
<< (TmpAttr.isC11() ? ExpectedVariableOrField
: ExpectedVariableFieldOrTag);
return;
}
if (DiagKind != -1) {
Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type)
- << TmpAttr.isC11() << DiagKind;
+ << &TmpAttr << DiagKind;
return;
}
}
@@ -3422,14 +2754,12 @@
return;
}
- if (TmpAttr.isDeclspec()) {
- // We've already verified it's a power of 2, now let's make sure it's
- // 8192 or less.
- if (Alignment.getZExtValue() > 8192) {
- Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192)
- << E->getSourceRange();
- return;
- }
+ // Alignment calculations can wrap around if it's greater than 2**28.
+ unsigned MaxValidAlignment = TmpAttr.isDeclspec() ? 8192 : 268435456;
+ if (Alignment.getZExtValue() > MaxValidAlignment) {
+ Diag(AttrLoc, diag::err_attribute_aligned_too_great) << MaxValidAlignment
+ << E->getSourceRange();
+ return;
}
AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true,
@@ -3465,13 +2795,11 @@
// would otherwise be required for the entity being declared.
AlignedAttr *AlignasAttr = 0;
unsigned Align = 0;
- for (specific_attr_iterator<AlignedAttr>
- I = D->specific_attr_begin<AlignedAttr>(),
- E = D->specific_attr_end<AlignedAttr>(); I != E; ++I) {
+ for (auto *I : D->specific_attrs<AlignedAttr>()) {
if (I->isAlignmentDependent())
return;
if (I->isAlignas())
- AlignasAttr = *I;
+ AlignasAttr = I;
Align = std::max(Align, I->getAlignment(Context));
}
@@ -3484,6 +2812,35 @@
}
}
+bool Sema::checkMSInheritanceAttrOnDefinition(
+ CXXRecordDecl *RD, SourceRange Range, bool BestCase,
+ MSInheritanceAttr::Spelling SemanticSpelling) {
+ assert(RD->hasDefinition() && "RD has no definition!");
+
+ // We may not have seen base specifiers or any virtual methods yet. We will
+ // have to wait until the record is defined to catch any mismatches.
+ if (!RD->getDefinition()->isCompleteDefinition())
+ return false;
+
+ // The unspecified model never matches what a definition could need.
+ if (SemanticSpelling == MSInheritanceAttr::Keyword_unspecified_inheritance)
+ return false;
+
+ if (BestCase) {
+ if (RD->calculateInheritanceModel() == SemanticSpelling)
+ return false;
+ } else {
+ if (RD->calculateInheritanceModel() <= SemanticSpelling)
+ return false;
+ }
+
+ Diag(Range.getBegin(), diag::err_mismatched_ms_inheritance)
+ << 0 /*definition*/;
+ Diag(RD->getDefinition()->getLocation(), diag::note_defined_here)
+ << RD->getNameAsString();
+ return true;
+}
+
/// handleModeAttr - This attribute modifies the width of a decl with primitive
/// type.
///
@@ -3553,7 +2910,7 @@
OldTy = VD->getType();
else {
S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
- << "mode" << Attr.getRange();
+ << Attr.getName() << Attr.getRange();
return;
}
@@ -3575,7 +2932,7 @@
// FIXME: Make sure floating-point mappings are accurate
// FIXME: Support XF and TF types
if (!DestWidth) {
- S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name;
+ S.Diag(Attr.getLoc(), diag::err_machine_mode) << 0 /*Unknown*/ << Name;
return;
}
@@ -3588,7 +2945,7 @@
NewTy = S.Context.getRealTypeForBitwidth(DestWidth);
if (NewTy.isNull()) {
- S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+ S.Diag(Attr.getLoc(), diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
return;
}
@@ -3625,149 +2982,49 @@
Attr.getAttributeSpellingListIndex()));
}
-static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
+static void handleAlwaysInlineAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<OptimizeNoneAttr>(S, D, Attr))
return;
- }
D->addAttr(::new (S.Context)
- NoInlineAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
- D->addAttr(::new (S.Context)
- NoInstrumentFunctionAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleKernelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.Renderscript) {
- D->addAttr(::new (S.Context) KernelAttr(Attr.getRange(), S.Context));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "kernel";
- }
-}
-
-static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.CUDA) {
- if (!isa<VarDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariable;
- return;
- }
-
- D->addAttr(::new (S.Context)
- CUDAConstantAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant";
- }
-}
-
-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)
- << Attr.getName() << 0;
- return;
- }
-
- if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariableOrFunction;
- return;
- }
-
- D->addAttr(::new (S.Context)
- CUDADeviceAttr(Attr.getRange(), S.Context,
+ AlwaysInlineAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device";
- }
+}
+
+static void handleOptimizeNoneAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<AlwaysInlineAttr>(S, D, Attr))
+ return;
+
+ D->addAttr(::new (S.Context)
+ OptimizeNoneAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.CUDA) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
+ FunctionDecl *FD = cast<FunctionDecl>(D);
+ if (!FD->getReturnType()->isVoidType()) {
+ TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
+ if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
+ S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
+ << FD->getType()
+ << FixItHint::CreateReplacement(FTL.getReturnLoc().getSourceRange(),
+ "void");
+ } else {
+ S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
+ << FD->getType();
}
-
- FunctionDecl *FD = cast<FunctionDecl>(D);
- if (!FD->getResultType()->isVoidType()) {
- TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
- if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
- S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
- << FD->getType()
- << FixItHint::CreateReplacement(FTL.getResultLoc().getSourceRange(),
- "void");
- } else {
- S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
- << FD->getType();
- }
- return;
- }
-
- D->addAttr(::new (S.Context)
- CUDAGlobalAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global";
- }
-}
-
-static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.CUDA) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
- return;
- }
-
- D->addAttr(::new (S.Context)
- CUDAHostAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host";
- }
-}
-
-static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (S.LangOpts.CUDA) {
- if (!isa<VarDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedVariable;
- return;
- }
-
- D->addAttr(::new (S.Context)
- CUDASharedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared";
- }
-}
-
-static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- FunctionDecl *Fn = dyn_cast<FunctionDecl>(D);
- if (Fn == 0) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunction;
return;
}
+ D->addAttr(::new (S.Context)
+ CUDAGlobalAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ FunctionDecl *Fn = cast<FunctionDecl>(D);
if (!Fn->isInlineSpecified()) {
S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
return;
@@ -3864,25 +3121,6 @@
}
}
-static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){
- D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context));
-}
-
-static void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){
- 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_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << E->getSourceRange();
- return;
- }
-
- D->addAttr(::new (S.Context) OpenCLImageAccessAttr(
- Attr.getRange(), S.Context, ArgNum.getZExtValue()));
-}
-
bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
const FunctionDecl *FD) {
if (attr.isInvalid())
@@ -3894,8 +3132,7 @@
return true;
}
- // TODO: diagnose uses of these conventions on the wrong target. Or, better
- // move to TargetAttributesSema one day.
+ // TODO: diagnose uses of these conventions on the wrong target.
switch (attr.getKind()) {
case AttributeList::AT_CDecl: CC = CC_C; break;
case AttributeList::AT_FastCall: CC = CC_X86FastCall; break;
@@ -3948,24 +3185,6 @@
return false;
}
-static void handleRegparmAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (hasDeclarator(D)) return;
-
- unsigned numParams;
- if (S.CheckRegparmAttr(Attr, numParams))
- return;
-
- if (!isa<ObjCMethodDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- D->addAttr(::new (S.Context)
- RegparmAttr(Attr.getRange(), S.Context, numParams,
- Attr.getAttributeSpellingListIndex()));
-}
-
/// Checks a regparm attribute, returning true if it is ill-formed and
/// otherwise setting numParams to the appropriate value.
bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
@@ -3977,13 +3196,9 @@
return true;
}
+ uint32_t NP;
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_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << NumParamsExpr->getSourceRange();
+ if (!checkUInt32Argument(*this, Attr, NumParamsExpr, NP)) {
Attr.setInvalid();
return true;
}
@@ -3995,7 +3210,7 @@
return true;
}
- numParams = NumParams.getZExtValue();
+ numParams = NP;
if (numParams > Context.getTargetInfo().getRegParmMax()) {
Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number)
<< Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange();
@@ -4006,53 +3221,28 @@
return false;
}
-static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){
- if (S.LangOpts.CUDA) {
- // check the attribute arguments.
- if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) {
- // FIXME: 0 is not okay.
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2;
- return;
- }
-
- if (!isFunctionOrMethod(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedFunctionOrMethod;
- return;
- }
-
- 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_type)
- << Attr.getName() << 1 << AANT_ArgumentIntegerConstant
- << MaxThreadsExpr->getSourceRange();
- return;
- }
-
- llvm::APSInt MinBlocks(32);
- if (Attr.getNumArgs() > 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_type)
- << Attr.getName() << 2 << AANT_ArgumentIntegerConstant
- << MinBlocksExpr->getSourceRange();
- return;
- }
- }
-
- D->addAttr(::new (S.Context)
- CUDALaunchBoundsAttr(Attr.getRange(), S.Context,
- MaxThreads.getZExtValue(),
- MinBlocks.getZExtValue(),
- Attr.getAttributeSpellingListIndex()));
- } else {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds";
+static void handleLaunchBoundsAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) {
+ // FIXME: 0 is not okay.
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 2;
+ return;
}
+
+ uint32_t MaxThreads, MinBlocks = 0;
+ if (!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), MaxThreads, 1))
+ return;
+ if (Attr.getNumArgs() > 1 && !checkUInt32Argument(S, Attr,
+ Attr.getArgAsExpr(1),
+ MinBlocks, 2))
+ return;
+
+ D->addAttr(::new (S.Context)
+ CUDALaunchBoundsAttr(Attr.getRange(), S.Context,
+ MaxThreads, MinBlocks,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
@@ -4066,7 +3256,6 @@
if (!checkAttributeNumArgs(S, Attr, 3))
return;
- StringRef AttrName = Attr.getName()->getName();
IdentifierInfo *ArgumentKind = Attr.getArgAsIdent(0)->Ident;
if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
@@ -4076,21 +3265,19 @@
}
uint64_t ArgumentIdx;
- if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName,
- Attr.getLoc(), 2,
- Attr.getArgAsExpr(1), ArgumentIdx))
+ if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 2, Attr.getArgAsExpr(1),
+ ArgumentIdx))
return;
uint64_t TypeTagIdx;
- if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName,
- Attr.getLoc(), 3,
- Attr.getArgAsExpr(2), TypeTagIdx))
+ if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 3, Attr.getArgAsExpr(2),
+ TypeTagIdx))
return;
- bool IsPointer = (AttrName == "pointer_with_type_tag");
+ bool IsPointer = (Attr.getName()->getName() == "pointer_with_type_tag");
if (IsPointer) {
// Ensure that buffer has a pointer type.
- QualType BufferTy = getFunctionOrMethodArgType(D, ArgumentIdx);
+ QualType BufferTy = getFunctionOrMethodParamType(D, ArgumentIdx);
if (!BufferTy->isPointerType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
<< Attr.getName();
@@ -4114,6 +3301,12 @@
if (!checkAttributeNumArgs(S, Attr, 1))
return;
+ if (!isa<VarDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedVariable;
+ return;
+ }
+
IdentifierInfo *PointerKind = Attr.getArgAsIdent(0)->Ident;
TypeSourceInfo *MatchingCTypeLoc = 0;
S.GetTypeFromParser(Attr.getMatchingCType(), &MatchingCTypeLoc);
@@ -4143,14 +3336,9 @@
}
static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- ParmVarDecl *param = dyn_cast<ParmVarDecl>(D);
- if (!param) {
- S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
- << Attr.getRange() << Attr.getName() << ExpectedParameter;
- return;
- }
-
+ ParmVarDecl *param = cast<ParmVarDecl>(D);
bool typeOK, cf;
+
if (Attr.getKind() == AttributeList::AT_NSConsumed) {
typeOK = isValidSubjectOfNSAttribute(S, param->getType());
cf = false;
@@ -4175,33 +3363,20 @@
Attr.getAttributeSpellingListIndex()));
}
-static void handleNSConsumesSelfAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- if (!isa<ObjCMethodDecl>(D)) {
- S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
- << Attr.getRange() << Attr.getName() << ExpectedMethod;
- return;
- }
-
- D->addAttr(::new (S.Context)
- NSConsumesSelfAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
QualType returnType;
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
- returnType = MD->getResultType();
+ returnType = MD->getReturnType();
else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&
(Attr.getKind() == AttributeList::AT_NSReturnsRetained))
return; // ignore: was handled as a type attribute
else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
returnType = PD->getType();
else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- returnType = FD->getResultType();
+ returnType = FD->getReturnType();
else {
S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
<< Attr.getRange() << Attr.getName()
@@ -4271,27 +3446,17 @@
SourceLocation loc = attr.getLoc();
QualType resultType;
-
- ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D);
-
- if (!method) {
- 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();
- }
+ if (isa<ObjCMethodDecl>(D))
+ resultType = cast<ObjCMethodDecl>(D)->getReturnType();
else
- // Check that the method returns a normal pointer.
- resultType = method->getResultType();
+ resultType = cast<ObjCPropertyDecl>(D)->getType();
if (!resultType->isReferenceType() &&
(!resultType->isPointerType() || resultType->isObjCRetainableType())) {
S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
<< SourceRange(loc)
- << attr.getName() << (method ? EP_ObjCMethod : EP_ObjCProperty)
+ << attr.getName()
+ << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty)
<< /*non-retainable pointer*/ 2;
// Drop the attribute.
@@ -4305,14 +3470,8 @@
static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
const AttributeList &attr) {
- SourceLocation loc = attr.getLoc();
- ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D);
+ ObjCMethodDecl *method = cast<ObjCMethodDecl>(D);
- if (!method) {
- S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << SourceRange(loc, loc) << attr.getName() << ExpectedMethod;
- return;
- }
DeclContext *DC = method->getDeclContext();
if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
@@ -4331,99 +3490,85 @@
attr.getAttributeSpellingListIndex()));
}
-/// Handle cf_audited_transfer and cf_unknown_transfer.
-static void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) {
- if (!isa<FunctionDecl>(D)) {
- S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << A.getRange() << A.getName() << ExpectedFunction;
+static void handleCFAuditedTransferAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<CFUnknownTransferAttr>(S, D, Attr))
return;
- }
-
- bool IsAudited = (A.getKind() == AttributeList::AT_CFAuditedTransfer);
-
- // Check whether there's a conflicting attribute already present.
- Attr *Existing;
- if (IsAudited) {
- Existing = D->getAttr<CFUnknownTransferAttr>();
- } else {
- Existing = D->getAttr<CFAuditedTransferAttr>();
- }
- if (Existing) {
- S.Diag(D->getLocStart(), diag::err_attributes_are_not_compatible)
- << A.getName()
- << (IsAudited ? "cf_unknown_transfer" : "cf_audited_transfer")
- << A.getRange() << Existing->getRange();
- return;
- }
-
- // All clear; add the attribute.
- if (IsAudited) {
- D->addAttr(::new (S.Context)
- CFAuditedTransferAttr(A.getRange(), S.Context,
- A.getAttributeSpellingListIndex()));
- } else {
- D->addAttr(::new (S.Context)
- CFUnknownTransferAttr(A.getRange(), S.Context,
- A.getAttributeSpellingListIndex()));
- }
-}
-
-static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D,
- const AttributeList &Attr) {
- RecordDecl *RD = dyn_cast<RecordDecl>(D);
- if (!RD || RD->isUnion()) {
- S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << Attr.getRange() << Attr.getName() << ExpectedStruct;
- }
-
- 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 (Parm && S.getLangOpts().ObjC1) {
- // Check for an existing type with this name.
- LookupResult R(S, DeclarationName(Parm->Ident), Parm->Loc,
- Sema::LookupOrdinaryName);
- if (S.LookupName(R, Sc)) {
- NamedDecl *Target = R.getFoundDecl();
- if (Target && !isa<ObjCInterfaceDecl>(Target)) {
- S.Diag(D->getLocStart(), diag::err_ns_bridged_not_interface);
- S.Diag(Target->getLocStart(), diag::note_declared_at);
- }
- }
- }
D->addAttr(::new (S.Context)
- NSBridgedAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0,
- Attr.getAttributeSpellingListIndex()));
+ CFAuditedTransferAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleCFUnknownTransferAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<CFAuditedTransferAttr>(S, D, Attr))
+ return;
+
+ D->addAttr(::new (S.Context)
+ CFUnknownTransferAttr(Attr.getRange(), S.Context,
+ 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;
+ IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0;
+
if (!Parm) {
- S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id);
+ S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
return;
}
D->addAttr(::new (S.Context)
- ObjCBridgeAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0,
+ ObjCBridgeAttr(Attr.getRange(), S.Context, Parm->Ident,
Attr.getAttributeSpellingListIndex()));
}
+static void handleObjCBridgeMutableAttr(Sema &S, Scope *Sc, Decl *D,
+ const AttributeList &Attr) {
+ IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0;
+
+ if (!Parm) {
+ S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ ObjCBridgeMutableAttr(Attr.getRange(), S.Context, Parm->Ident,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleObjCBridgeRelatedAttr(Sema &S, Scope *Sc, Decl *D,
+ const AttributeList &Attr) {
+ IdentifierInfo *RelatedClass =
+ Attr.isArgIdent(0) ? Attr.getArgAsIdent(0)->Ident : 0;
+ if (!RelatedClass) {
+ S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
+ return;
+ }
+ IdentifierInfo *ClassMethod =
+ Attr.getArgAsIdent(1) ? Attr.getArgAsIdent(1)->Ident : 0;
+ IdentifierInfo *InstanceMethod =
+ Attr.getArgAsIdent(2) ? Attr.getArgAsIdent(2)->Ident : 0;
+ D->addAttr(::new (S.Context)
+ ObjCBridgeRelatedAttr(Attr.getRange(), S.Context, RelatedClass,
+ ClassMethod, InstanceMethod,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ ObjCInterfaceDecl *IFace;
+ if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
+ IFace = CatDecl->getClassInterface();
+ else
+ IFace = cast<ObjCInterfaceDecl>(D->getDeclContext());
+ IFace->setHasDesignatedInitializers();
+ D->addAttr(::new (S.Context)
+ ObjCDesignatedInitializerAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
static void handleObjCOwnershipAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (hasDeclarator(D)) return;
@@ -4434,12 +3579,6 @@
static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (!isa<VarDecl>(D) && !isa<FieldDecl>(D)) {
- S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << Attr.getRange() << Attr.getName() << ExpectedVariable;
- return;
- }
-
ValueDecl *vd = cast<ValueDecl>(D);
QualType type = vd->getType();
@@ -4483,19 +3622,18 @@
// Microsoft specific attribute handlers.
//===----------------------------------------------------------------------===//
-// 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;
-}
-
static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkMicrosoftExt(S, Attr, S.LangOpts.Borland))
+ if (!S.LangOpts.CPlusPlus) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
+ << Attr.getName() << AttributeLangSupport::C;
return;
+ }
+
+ if (!isa<CXXRecordDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedClass;
+ return;
+ }
StringRef StrRef;
SourceLocation LiteralLoc;
@@ -4529,55 +3667,305 @@
Attr.getAttributeSpellingListIndex()));
}
-static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkMicrosoftExt(S, Attr))
+static void handleMSInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (!S.LangOpts.CPlusPlus) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
+ << Attr.getName() << AttributeLangSupport::C;
return;
-
- AttributeList::Kind Kind = Attr.getKind();
- if (Kind == AttributeList::AT_SingleInheritance)
- D->addAttr(
- ::new (S.Context)
- SingleInheritanceAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else if (Kind == AttributeList::AT_MultipleInheritance)
- D->addAttr(
- ::new (S.Context)
- MultipleInheritanceAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
- else if (Kind == AttributeList::AT_VirtualInheritance)
- D->addAttr(
- ::new (S.Context)
- VirtualInheritanceAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ }
+ MSInheritanceAttr *IA = S.mergeMSInheritanceAttr(
+ D, Attr.getRange(), /*BestCase=*/true,
+ Attr.getAttributeSpellingListIndex(),
+ (MSInheritanceAttr::Spelling)Attr.getSemanticSpelling());
+ if (IA)
+ D->addAttr(IA);
}
-static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkMicrosoftExt(S, Attr))
+static void handleARMInterruptAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() > 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 1;
+ return;
+ }
+
+ StringRef Str;
+ SourceLocation ArgLoc;
+
+ if (Attr.getNumArgs() == 0)
+ Str = "";
+ else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
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 (!checkMicrosoftExt(S, Attr))
+ 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)
- ForceInlineAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index));
}
-static void handleSelectAnyAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkMicrosoftExt(S, Attr))
+static void handleMSP430InterruptAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!checkAttributeNumArgs(S, Attr, 1))
return;
- // Check linkage after possibly merging declaratinos. See
- // checkAttributesAfterMerging().
+
+ if (!Attr.isArgExpr(0)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
+ << AANT_ArgumentIntegerConstant;
+ return;
+ }
+
+ // FIXME: Check for decl - it should be void ()(void).
+
+ 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_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << NumParamsExpr->getSourceRange();
+ return;
+ }
+
+ unsigned Num = NumParams.getLimitedValue(255);
+ if ((Num & 1) || Num > 30) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << Attr.getName() << (int)NumParams.getSExtValue()
+ << NumParamsExpr->getSourceRange();
+ return;
+ }
+
D->addAttr(::new (S.Context)
- SelectAnyAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ MSP430InterruptAttr(Attr.getLoc(), S.Context, Num,
+ Attr.getAttributeSpellingListIndex()));
+ D->addAttr(UsedAttr::CreateImplicit(S.Context));
+}
+
+static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ // Dispatch the interrupt attribute based on the current target.
+ if (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::msp430)
+ handleMSP430InterruptAttr(S, D, Attr);
+ else
+ handleARMInterruptAttr(S, D, Attr);
+}
+
+static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D,
+ const AttributeList& Attr) {
+ // If we try to apply it to a function pointer, don't warn, but don't
+ // do anything, either. It doesn't matter anyway, because there's nothing
+ // special about calling a force_align_arg_pointer function.
+ ValueDecl *VD = dyn_cast<ValueDecl>(D);
+ if (VD && VD->getType()->isFunctionPointerType())
+ return;
+ // Also don't warn on function pointer typedefs.
+ TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
+ if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
+ TD->getUnderlyingType()->isFunctionType()))
+ return;
+ // Attribute can only be applied to function types.
+ if (!isa<FunctionDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << /* function */0;
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ X86ForceAlignArgPointerAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex) {
+ if (D->hasAttr<DLLExportAttr>()) {
+ Diag(Range.getBegin(), diag::warn_attribute_ignored) << "'dllimport'";
+ return NULL;
+ }
+
+ if (D->hasAttr<DLLImportAttr>())
+ return NULL;
+
+ return ::new (Context) DLLImportAttr(Range, Context, AttrSpellingListIndex);
+}
+
+static void handleDLLImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ // Attribute can be applied only to functions or variables.
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (!FD && !isa<VarDecl>(D)) {
+ // Apparently Visual C++ thinks it is okay to not emit a warning
+ // in this case, so only emit a warning when -fms-extensions is not
+ // specified.
+ if (!S.getLangOpts().MicrosoftExt)
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedVariableOrFunction;
+ return;
+ }
+
+ // Currently, the dllimport attribute is ignored for inlined functions.
+ // Warning is emitted.
+ if (FD && FD->isInlineSpecified()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return;
+ }
+
+ unsigned Index = Attr.getAttributeSpellingListIndex();
+ DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index);
+ if (NewAttr)
+ D->addAttr(NewAttr);
+}
+
+DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex) {
+ if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
+ Diag(Import->getLocation(), diag::warn_attribute_ignored) << Import;
+ D->dropAttr<DLLImportAttr>();
+ }
+
+ if (D->hasAttr<DLLExportAttr>())
+ return NULL;
+
+ return ::new (Context) DLLExportAttr(Range, Context, AttrSpellingListIndex);
+}
+
+static void handleDLLExportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ // Currently, the dllexport attribute is ignored for inlined functions, unless
+ // the -fkeep-inline-functions flag has been used. Warning is emitted.
+ if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isInlineSpecified()) {
+ // FIXME: ... unless the -fkeep-inline-functions flag has been used.
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return;
+ }
+
+ unsigned Index = Attr.getAttributeSpellingListIndex();
+ DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index);
+ if (NewAttr)
+ D->addAttr(NewAttr);
+}
+
+MSInheritanceAttr *
+Sema::mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
+ unsigned AttrSpellingListIndex,
+ MSInheritanceAttr::Spelling SemanticSpelling) {
+ if (MSInheritanceAttr *IA = D->getAttr<MSInheritanceAttr>()) {
+ if (IA->getSemanticSpelling() == SemanticSpelling)
+ return 0;
+ Diag(IA->getLocation(), diag::err_mismatched_ms_inheritance)
+ << 1 /*previous declaration*/;
+ Diag(Range.getBegin(), diag::note_previous_ms_inheritance);
+ D->dropAttr<MSInheritanceAttr>();
+ }
+
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
+ if (RD->hasDefinition()) {
+ if (checkMSInheritanceAttrOnDefinition(RD, Range, BestCase,
+ SemanticSpelling)) {
+ return 0;
+ }
+ } else {
+ if (isa<ClassTemplatePartialSpecializationDecl>(RD)) {
+ Diag(Range.getBegin(), diag::warn_ignored_ms_inheritance)
+ << 1 /*partial specialization*/;
+ return 0;
+ }
+ if (RD->getDescribedClassTemplate()) {
+ Diag(Range.getBegin(), diag::warn_ignored_ms_inheritance)
+ << 0 /*primary template*/;
+ return 0;
+ }
+ }
+
+ return ::new (Context)
+ MSInheritanceAttr(Range, Context, BestCase, AttrSpellingListIndex);
+}
+
+static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ // The capability attributes take a single string parameter for the name of
+ // the capability they represent. The lockable attribute does not take any
+ // parameters. However, semantically, both attributes represent the same
+ // concept, and so they use the same semantic attribute. Eventually, the
+ // lockable attribute will be removed.
+ //
+ // For backwards compatibility, any capability which has no specified string
+ // literal will be considered a "mutex."
+ StringRef N("mutex");
+ SourceLocation LiteralLoc;
+ if (Attr.getKind() == AttributeList::AT_Capability &&
+ !S.checkStringLiteralArgumentAttr(Attr, 0, N, &LiteralLoc))
+ return;
+
+ // Currently, there are only two names allowed for a capability: role and
+ // mutex (case insensitive). Diagnose other capability names.
+ if (!N.equals_lower("mutex") && !N.equals_lower("role"))
+ S.Diag(LiteralLoc, diag::warn_invalid_capability_name) << N;
+
+ D->addAttr(::new (S.Context) CapabilityAttr(Attr.getRange(), S.Context, N,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleAssertCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ D->addAttr(::new (S.Context) AssertCapabilityAttr(Attr.getRange(), S.Context,
+ Attr.getArgAsExpr(0),
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleAcquireCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ SmallVector<Expr*, 1> Args;
+ if (!checkLockFunAttrCommon(S, D, Attr, Args))
+ return;
+
+ D->addAttr(::new (S.Context) AcquireCapabilityAttr(Attr.getRange(),
+ S.Context,
+ Args.data(), Args.size(),
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ SmallVector<Expr*, 2> Args;
+ if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
+ return;
+
+ D->addAttr(::new (S.Context) TryAcquireCapabilityAttr(Attr.getRange(),
+ S.Context,
+ Attr.getArgAsExpr(0),
+ Args.data(),
+ Args.size(),
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleReleaseCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ // Check that all arguments are lockable objects.
+ SmallVector<Expr *, 1> Args;
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 0, true);
+
+ D->addAttr(::new (S.Context) ReleaseCapabilityAttr(
+ Attr.getRange(), S.Context, Args.data(), Args.size(),
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ return;
+
+ // check that all arguments are lockable objects
+ SmallVector<Expr*, 1> Args;
+ checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
+ if (Args.empty())
+ return;
+
+ RequiresCapabilityAttr *RCA = ::new (S.Context)
+ RequiresCapabilityAttr(Attr.getRange(), S.Context, Args.data(),
+ Args.size(), Attr.getAttributeSpellingListIndex());
+
+ D->addAttr(RCA);
}
/// Handles semantic checking for features that are common to all attributes,
@@ -4591,15 +3979,24 @@
// 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)
+ Attr.getKind() == AttributeList::UnknownAttribute)
return false;
+ // Check whether the attribute requires specific language extensions to be
+ // enabled.
+ if (!Attr.diagnoseLangOpts(S))
+ return true;
+
// 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;
+
+ // Check whether the attribute appertains to the given subject.
+ if (!Attr.diagnoseAppertainsTo(S, D))
+ return true;
+
return false;
}
@@ -4613,7 +4010,7 @@
static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
const AttributeList &Attr,
bool IncludeCXX11Attributes) {
- if (Attr.isInvalid())
+ if (Attr.isInvalid() || Attr.getKind() == AttributeList::IgnoredAttribute)
return;
// Ignore C++11 attributes on declarator chunks: they appertain to the type
@@ -4621,146 +4018,277 @@
if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes)
return;
+ // Unknown attributes are automatically warned on. Target-specific attributes
+ // which do not apply to the current target architecture are treated as
+ // though they were unknown attributes.
+ if (Attr.getKind() == AttributeList::UnknownAttribute ||
+ !Attr.existsInTarget(S.Context.getTargetInfo().getTriple())) {
+ S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute()
+ ? diag::warn_unhandled_ms_attribute_ignored
+ : diag::warn_unknown_attribute_ignored)
+ << Attr.getName();
+ return;
+ }
+
if (handleCommonAttributeFeatures(S, scope, D, Attr))
return;
switch (Attr.getKind()) {
- case AttributeList::AT_IBAction: handleIBAction(S, D, Attr); break;
- case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break;
- case AttributeList::AT_IBOutletCollection:
- handleIBOutletCollection(S, D, Attr); break;
- case AttributeList::AT_AddressSpace:
- case AttributeList::AT_ObjCGC:
- 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.
+ default:
+ // Type attributes are handled elsewhere; silently move on.
+ assert(Attr.isTypeAttr() && "Non-type attribute not handled");
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;
+ case AttributeList::AT_Interrupt:
+ handleInterruptAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_X86ForceAlignArgPointer:
+ handleX86ForceAlignArgPointerAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_DLLExport:
+ handleDLLExportAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_DLLImport:
+ handleDLLImportAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Mips16:
+ handleSimpleAttribute<Mips16Attr>(S, D, Attr);
+ break;
+ case AttributeList::AT_NoMips16:
+ handleSimpleAttribute<NoMips16Attr>(S, D, Attr);
+ break;
+ case AttributeList::AT_IBAction:
+ handleSimpleAttribute<IBActionAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_IBOutlet:
+ handleIBOutlet(S, D, Attr);
+ break;
+ case AttributeList::AT_IBOutletCollection:
+ handleIBOutletCollection(S, D, Attr);
+ break;
+ case AttributeList::AT_Alias:
+ handleAliasAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Aligned:
+ handleAlignedAttr(S, D, Attr);
+ break;
case AttributeList::AT_AlwaysInline:
- handleAlwaysInlineAttr (S, D, Attr); break;
+ handleAlwaysInlineAttr(S, D, Attr);
+ break;
case AttributeList::AT_AnalyzerNoReturn:
- handleAnalyzerNoReturnAttr (S, D, Attr); break;
- case AttributeList::AT_TLSModel: handleTLSModelAttr (S, D, Attr); break;
- case AttributeList::AT_Annotate: handleAnnotateAttr (S, D, Attr); break;
- case AttributeList::AT_Availability:handleAvailabilityAttr(S, D, Attr); break;
+ handleAnalyzerNoReturnAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_TLSModel:
+ handleTLSModelAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Annotate:
+ handleAnnotateAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Availability:
+ handleAvailabilityAttr(S, D, Attr);
+ break;
case AttributeList::AT_CarriesDependency:
handleDependencyAttr(S, scope, D, Attr);
break;
- case AttributeList::AT_Common: handleCommonAttr (S, D, Attr); break;
- case AttributeList::AT_CUDAConstant:handleConstantAttr (S, D, Attr); break;
- case AttributeList::AT_Constructor: handleConstructorAttr (S, D, Attr); break;
+ case AttributeList::AT_Common:
+ handleCommonAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_CUDAConstant:
+ handleSimpleAttribute<CUDAConstantAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Constructor:
+ handleConstructorAttr(S, D, Attr);
+ break;
case AttributeList::AT_CXX11NoReturn:
- handleCXX11NoReturnAttr(S, D, Attr);
+ handleSimpleAttribute<CXX11NoReturnAttr>(S, D, Attr);
break;
case AttributeList::AT_Deprecated:
handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);
break;
- case AttributeList::AT_Destructor: handleDestructorAttr (S, D, Attr); break;
+ case AttributeList::AT_Destructor:
+ handleDestructorAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_EnableIf:
+ handleEnableIfAttr(S, D, Attr);
+ break;
case AttributeList::AT_ExtVectorType:
handleExtVectorTypeAttr(S, scope, D, Attr);
break;
case AttributeList::AT_MinSize:
- handleMinSizeAttr(S, D, Attr);
+ handleSimpleAttribute<MinSizeAttr>(S, D, Attr);
break;
- 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_OptimizeNone:
+ handleOptimizeNoneAttr(S, D, Attr);
+ break;
+ 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:
+ handleSimpleAttribute<CUDADeviceAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_CUDAHost:
+ handleSimpleAttribute<CUDAHostAttr>(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_Kernel: handleKernelAttr (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:
- handleOwnershipAttr (S, D, Attr); break;
- case AttributeList::AT_Cold: handleColdAttr (S, D, Attr); break;
- case AttributeList::AT_Hot: handleHotAttr (S, D, Attr); break;
- case AttributeList::AT_Naked: handleNakedAttr (S, D, Attr); break;
- case AttributeList::AT_NoReturn: handleNoReturnAttr (S, D, Attr); break;
- case AttributeList::AT_NoThrow: handleNothrowAttr (S, D, Attr); break;
- case AttributeList::AT_CUDAShared: handleSharedAttr (S, D, Attr); break;
- case AttributeList::AT_VecReturn: handleVecReturnAttr (S, D, Attr); break;
+ case AttributeList::AT_Kernel:
+ handleKernelAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Malloc:
+ handleMallocAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_MayAlias:
+ handleSimpleAttribute<MayAliasAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Mode:
+ handleModeAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_NoCommon:
+ handleSimpleAttribute<NoCommonAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_NonNull:
+ if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D))
+ handleNonNullAttrParameter(S, PVD, Attr);
+ else
+ handleNonNullAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_ReturnsNonNull:
+ handleReturnsNonNullAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Overloadable:
+ handleSimpleAttribute<OverloadableAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Ownership:
+ handleOwnershipAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Cold:
+ handleColdAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Hot:
+ handleHotAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Naked:
+ handleSimpleAttribute<NakedAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_NoReturn:
+ handleNoReturnAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_NoThrow:
+ handleSimpleAttribute<NoThrowAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_CUDAShared:
+ handleSimpleAttribute<CUDASharedAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_VecReturn:
+ handleVecReturnAttr(S, D, Attr);
+ break;
case AttributeList::AT_ObjCOwnership:
- handleObjCOwnershipAttr(S, D, Attr); break;
+ handleObjCOwnershipAttr(S, D, Attr);
+ break;
case AttributeList::AT_ObjCPreciseLifetime:
- handleObjCPreciseLifetimeAttr(S, D, Attr); break;
+ handleObjCPreciseLifetimeAttr(S, D, Attr);
+ break;
case AttributeList::AT_ObjCReturnsInnerPointer:
- handleObjCReturnsInnerPointerAttr(S, D, Attr); break;
+ handleObjCReturnsInnerPointerAttr(S, D, Attr);
+ break;
case AttributeList::AT_ObjCRequiresSuper:
- handleObjCRequiresSuperAttr(S, D, Attr); break;
-
- case AttributeList::AT_NSBridged:
- handleNSBridgedAttr(S, scope, D, Attr); break;
-
+ handleObjCRequiresSuperAttr(S, D, Attr);
+ break;
+
case AttributeList::AT_ObjCBridge:
- handleObjCBridgeAttr(S, scope, D, Attr); break;
+ handleObjCBridgeAttr(S, scope, D, Attr);
+ break;
+
+ case AttributeList::AT_ObjCBridgeMutable:
+ handleObjCBridgeMutableAttr(S, scope, D, Attr);
+ break;
+
+ case AttributeList::AT_ObjCBridgeRelated:
+ handleObjCBridgeRelatedAttr(S, scope, D, Attr);
+ break;
+
+ case AttributeList::AT_ObjCDesignatedInitializer:
+ handleObjCDesignatedInitializer(S, D, Attr);
+ break;
case AttributeList::AT_CFAuditedTransfer:
+ handleCFAuditedTransferAttr(S, D, Attr);
+ break;
case AttributeList::AT_CFUnknownTransfer:
- handleCFTransferAttr(S, D, Attr); break;
+ handleCFUnknownTransferAttr(S, D, Attr);
+ break;
- // Checker-specific.
case AttributeList::AT_CFConsumed:
- case AttributeList::AT_NSConsumed: handleNSConsumedAttr (S, D, Attr); break;
+ case AttributeList::AT_NSConsumed:
+ handleNSConsumedAttr(S, D, Attr);
+ break;
case AttributeList::AT_NSConsumesSelf:
- handleNSConsumesSelfAttr(S, D, Attr); break;
+ handleSimpleAttribute<NSConsumesSelfAttr>(S, D, Attr);
+ break;
case AttributeList::AT_NSReturnsAutoreleased:
case AttributeList::AT_NSReturnsNotRetained:
case AttributeList::AT_CFReturnsNotRetained:
case AttributeList::AT_NSReturnsRetained:
case AttributeList::AT_CFReturnsRetained:
- handleNSReturnsRetainedAttr(S, D, Attr); break;
-
+ handleNSReturnsRetainedAttr(S, D, Attr);
+ break;
case AttributeList::AT_WorkGroupSizeHint:
+ handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, Attr);
+ break;
case AttributeList::AT_ReqdWorkGroupSize:
- handleWorkGroupSize(S, D, Attr); break;
-
+ handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, Attr);
+ break;
case AttributeList::AT_VecTypeHint:
- handleVecTypeHint(S, D, Attr); break;
+ handleVecTypeHint(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_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);
break;
- case AttributeList::AT_ArcWeakrefUnavailable:
- handleArcWeakrefUnavailableAttr (S, D, Attr);
+ case AttributeList::AT_ArcWeakrefUnavailable:
+ handleSimpleAttribute<ArcWeakrefUnavailableAttr>(S, D, Attr);
break;
case AttributeList::AT_ObjCRootClass:
- handleObjCRootClassAttr(S, D, Attr);
+ handleSimpleAttribute<ObjCRootClassAttr>(S, D, Attr);
break;
- case AttributeList::AT_ObjCRequiresPropertyDefs:
- handleObjCRequiresPropertyDefsAttr (S, D, Attr);
+ case AttributeList::AT_ObjCExplicitProtocolImpl:
+ handleObjCSuppresProtocolAttr(S, D, Attr);
break;
- case AttributeList::AT_Unused: handleUnusedAttr (S, D, Attr); break;
+ case AttributeList::AT_ObjCRequiresPropertyDefs:
+ handleSimpleAttribute<ObjCRequiresPropertyDefsAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Unused:
+ handleSimpleAttribute<UnusedAttr>(S, D, Attr);
+ break;
case AttributeList::AT_ReturnsTwice:
- handleReturnsTwiceAttr(S, D, Attr);
+ handleSimpleAttribute<ReturnsTwiceAttr>(S, D, Attr);
break;
- case AttributeList::AT_Used: handleUsedAttr (S, D, Attr); break;
+ case AttributeList::AT_Used:
+ handleUsedAttr(S, D, Attr);
+ break;
case AttributeList::AT_Visibility:
handleVisibilityAttr(S, D, Attr, false);
break;
@@ -4768,36 +4296,58 @@
handleVisibilityAttr(S, D, Attr, true);
break;
case AttributeList::AT_WarnUnused:
- handleWarnUnusedAttr(S, D, Attr);
+ handleSimpleAttribute<WarnUnusedAttr>(S, D, Attr);
break;
- case AttributeList::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, Attr);
+ case AttributeList::AT_WarnUnusedResult:
+ handleWarnUnusedResult(S, D, Attr);
break;
- case AttributeList::AT_Weak: handleWeakAttr (S, D, Attr); break;
- case AttributeList::AT_WeakRef: handleWeakRefAttr (S, D, Attr); break;
- case AttributeList::AT_WeakImport: handleWeakImportAttr (S, D, Attr); break;
+ case AttributeList::AT_Weak:
+ handleSimpleAttribute<WeakAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_WeakRef:
+ handleWeakRefAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_WeakImport:
+ handleWeakImportAttr(S, D, Attr);
+ break;
case AttributeList::AT_TransparentUnion:
handleTransparentUnionAttr(S, D, Attr);
break;
case AttributeList::AT_ObjCException:
- handleObjCExceptionAttr(S, D, Attr);
+ handleSimpleAttribute<ObjCExceptionAttr>(S, D, Attr);
break;
case AttributeList::AT_ObjCMethodFamily:
handleObjCMethodFamilyAttr(S, D, Attr);
break;
- case AttributeList::AT_ObjCNSObject:handleObjCNSObject (S, D, Attr); break;
- case AttributeList::AT_Blocks: handleBlocksAttr (S, D, Attr); break;
- case AttributeList::AT_Sentinel: handleSentinelAttr (S, D, Attr); break;
- case AttributeList::AT_Const: handleConstAttr (S, D, Attr); break;
- case AttributeList::AT_Pure: handlePureAttr (S, D, Attr); break;
- case AttributeList::AT_Cleanup: handleCleanupAttr (S, D, Attr); break;
- case AttributeList::AT_NoDebug: handleNoDebugAttr (S, D, Attr); break;
- case AttributeList::AT_NoInline: handleNoInlineAttr (S, D, Attr); break;
- case AttributeList::AT_Regparm: handleRegparmAttr (S, D, Attr); break;
- case AttributeList::IgnoredAttribute:
- // Just ignore
+ case AttributeList::AT_ObjCNSObject:
+ handleObjCNSObject(S, D, Attr);
break;
- case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg.
- handleNoInstrumentFunctionAttr(S, D, Attr);
+ case AttributeList::AT_Blocks:
+ handleBlocksAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Sentinel:
+ handleSentinelAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_Const:
+ handleSimpleAttribute<ConstAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Pure:
+ handleSimpleAttribute<PureAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_Cleanup:
+ handleCleanupAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_NoDebug:
+ handleNoDebugAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_NoDuplicate:
+ handleSimpleAttribute<NoDuplicateAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_NoInline:
+ handleSimpleAttribute<NoInlineAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg.
+ handleSimpleAttribute<NoInstrumentFunctionAttr>(S, D, Attr);
break;
case AttributeList::AT_StdCall:
case AttributeList::AT_CDecl:
@@ -4812,32 +4362,24 @@
handleCallConvAttr(S, D, Attr);
break;
case AttributeList::AT_OpenCLKernel:
- handleOpenCLKernelAttr(S, D, Attr);
+ handleSimpleAttribute<OpenCLKernelAttr>(S, D, Attr);
break;
case AttributeList::AT_OpenCLImageAccess:
- handleOpenCLImageAccessAttr(S, D, Attr);
+ handleSimpleAttribute<OpenCLImageAccessAttr>(S, D, Attr);
break;
// Microsoft attributes:
case AttributeList::AT_MsStruct:
- handleMsStructAttr(S, D, Attr);
+ handleSimpleAttribute<MsStructAttr>(S, D, Attr);
break;
case AttributeList::AT_Uuid:
handleUuidAttr(S, D, Attr);
break;
- case AttributeList::AT_SingleInheritance:
- case AttributeList::AT_MultipleInheritance:
- case AttributeList::AT_VirtualInheritance:
- handleInheritanceAttr(S, D, Attr);
- break;
- case AttributeList::AT_Win64:
- handlePortabilityAttr(S, D, Attr);
- break;
- case AttributeList::AT_ForceInline:
- handleForceInlineAttr(S, D, Attr);
+ case AttributeList::AT_MSInheritance:
+ handleMSInheritanceAttr(S, D, Attr);
break;
case AttributeList::AT_SelectAny:
- handleSelectAnyAttr(S, D, Attr);
+ handleSimpleAttribute<SelectAnyAttr>(S, D, Attr);
break;
// Thread safety attributes:
@@ -4848,28 +4390,25 @@
handleAssertSharedLockAttr(S, D, Attr);
break;
case AttributeList::AT_GuardedVar:
- handleGuardedVarAttr(S, D, Attr);
+ handleSimpleAttribute<GuardedVarAttr>(S, D, Attr);
break;
case AttributeList::AT_PtGuardedVar:
handlePtGuardedVarAttr(S, D, Attr);
break;
case AttributeList::AT_ScopedLockable:
- handleScopedLockableAttr(S, D, Attr);
+ handleSimpleAttribute<ScopedLockableAttr>(S, D, Attr);
break;
case AttributeList::AT_NoSanitizeAddress:
- handleNoSanitizeAddressAttr(S, D, Attr);
+ handleSimpleAttribute<NoSanitizeAddressAttr>(S, D, Attr);
break;
case AttributeList::AT_NoThreadSafetyAnalysis:
- handleNoThreadSafetyAnalysis(S, D, Attr);
+ handleSimpleAttribute<NoThreadSafetyAnalysisAttr>(S, D, Attr);
break;
case AttributeList::AT_NoSanitizeThread:
- handleNoSanitizeThread(S, D, Attr);
+ handleSimpleAttribute<NoSanitizeThreadAttr>(S, D, Attr);
break;
case AttributeList::AT_NoSanitizeMemory:
- handleNoSanitizeMemory(S, D, Attr);
- break;
- case AttributeList::AT_Lockable:
- handleLockableAttr(S, D, Attr);
+ handleSimpleAttribute<NoSanitizeMemoryAttr>(S, D, Attr);
break;
case AttributeList::AT_GuardedBy:
handleGuardedByAttr(S, D, Attr);
@@ -4877,12 +4416,6 @@
case AttributeList::AT_PtGuardedBy:
handlePtGuardedByAttr(S, D, Attr);
break;
- case AttributeList::AT_ExclusiveLockFunction:
- handleExclusiveLockFunctionAttr(S, D, Attr);
- break;
- case AttributeList::AT_ExclusiveLocksRequired:
- handleExclusiveLocksRequiredAttr(S, D, Attr);
- break;
case AttributeList::AT_ExclusiveTrylockFunction:
handleExclusiveTrylockFunctionAttr(S, D, Attr);
break;
@@ -4892,18 +4425,9 @@
case AttributeList::AT_LocksExcluded:
handleLocksExcludedAttr(S, D, Attr);
break;
- case AttributeList::AT_SharedLockFunction:
- handleSharedLockFunctionAttr(S, D, Attr);
- break;
- case AttributeList::AT_SharedLocksRequired:
- handleSharedLocksRequiredAttr(S, D, Attr);
- break;
case AttributeList::AT_SharedTrylockFunction:
handleSharedTrylockFunctionAttr(S, D, Attr);
break;
- case AttributeList::AT_UnlockFunction:
- handleUnlockFunAttr(S, D, Attr);
- break;
case AttributeList::AT_AcquiredBefore:
handleAcquiredBeforeAttr(S, D, Attr);
break;
@@ -4911,10 +4435,38 @@
handleAcquiredAfterAttr(S, D, Attr);
break;
+ // Capability analysis attributes.
+ case AttributeList::AT_Capability:
+ case AttributeList::AT_Lockable:
+ handleCapabilityAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_RequiresCapability:
+ handleRequiresCapabilityAttr(S, D, Attr);
+ break;
+
+ case AttributeList::AT_AssertCapability:
+ handleAssertCapabilityAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_AcquireCapability:
+ handleAcquireCapabilityAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_ReleaseCapability:
+ handleReleaseCapabilityAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_TryAcquireCapability:
+ handleTryAcquireCapabilityAttr(S, D, Attr);
+ break;
+
// Consumed analysis attributes.
case AttributeList::AT_Consumable:
handleConsumableAttr(S, D, Attr);
break;
+ case AttributeList::AT_ConsumableAutoCast:
+ handleSimpleAttribute<ConsumableAutoCastAttr>(S, D, Attr);
+ break;
+ case AttributeList::AT_ConsumableSetOnRead:
+ handleSimpleAttribute<ConsumableSetOnReadAttr>(S, D, Attr);
+ break;
case AttributeList::AT_CallableWhen:
handleCallableWhenAttr(S, D, Attr);
break;
@@ -4938,15 +4490,6 @@
case AttributeList::AT_TypeTagForDatatype:
handleTypeTagForDatatypeAttr(S, D, Attr);
break;
-
- default:
- // Ask target about the attribute.
- const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
- if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
- S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute() ?
- diag::warn_unhandled_ms_attribute_ignored :
- diag::warn_unknown_attribute_ignored) << Attr.getName();
- break;
}
}
@@ -4958,15 +4501,32 @@
for (const AttributeList* l = AttrList; l; l = l->getNext())
ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes);
+ // FIXME: We should be able to handle these cases in TableGen.
// GCC accepts
// static int a9 __attribute__((weakref));
// but that looks really pointless. We reject it.
if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
- Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) <<
- cast<NamedDecl>(D)->getNameAsString();
+ Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias)
+ << cast<NamedDecl>(D);
D->dropAttr<WeakRefAttr>();
return;
}
+
+ if (!D->hasAttr<OpenCLKernelAttr>()) {
+ // These attributes cannot be applied to a non-kernel function.
+ if (Attr *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
+ Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
+ D->setInvalidDecl();
+ }
+ if (Attr *A = D->getAttr<WorkGroupSizeHintAttr>()) {
+ Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
+ D->setInvalidDecl();
+ }
+ if (Attr *A = D->getAttr<VecTypeHintAttr>()) {
+ Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
+ D->setInvalidDecl();
+ }
+ }
}
// Annotation attributes are the only attributes allowed after an access
@@ -5041,9 +4601,8 @@
QualType FDTy = FD->getType();
if (const FunctionProtoType *FT = FDTy->getAs<FunctionProtoType>()) {
SmallVector<ParmVarDecl*, 16> Params;
- for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
- AE = FT->arg_type_end(); AI != AE; ++AI) {
- ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, *AI);
+ for (const auto &AI : FT->param_types()) {
+ ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, AI);
Param->setScopeInfo(0, Params.size());
Params.push_back(Param);
}
@@ -5070,18 +4629,20 @@
if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
IdentifierInfo *NDId = ND->getIdentifier();
NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation());
- NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context,
- NDId->getName()));
- NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
+ NewD->addAttr(AliasAttr::CreateImplicit(Context, NDId->getName(),
+ W.getLocation()));
+ NewD->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation()));
WeakTopLevelDecl.push_back(NewD);
// FIXME: "hideous" code from Sema::LazilyCreateBuiltin
// to insert Decl at TU scope, sorry.
DeclContext *SavedContext = CurContext;
CurContext = Context.getTranslationUnitDecl();
+ NewD->setDeclContext(CurContext);
+ NewD->setLexicalDeclContext(CurContext);
PushOnScopeChains(NewD, S);
CurContext = SavedContext;
} else { // just add weak to existing
- ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
+ ND->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation()));
}
}
@@ -5150,8 +4711,9 @@
static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag,
Decl *decl) {
if (decl && isForbiddenTypeAllowed(S, decl)) {
- decl->addAttr(new (S.Context) UnavailableAttr(diag.Loc, S.Context,
- "this system declaration uses an unsupported type"));
+ decl->addAttr(UnavailableAttr::CreateImplicit(S.Context,
+ "this system declaration uses an unsupported type",
+ diag.Loc));
return;
}
if (S.getLangOpts().ObjCAutoRefCount)
@@ -5199,9 +4761,11 @@
switch (diag.Kind) {
case DelayedDiagnostic::Deprecation:
- // Don't bother giving deprecation diagnostics if the decl is invalid.
+ case DelayedDiagnostic::Unavailable:
+ // Don't bother giving deprecation/unavailable diagnostics if
+ // the decl is invalid.
if (!decl->isInvalidDecl())
- HandleDelayedDeprecationCheck(diag, decl);
+ HandleDelayedAvailabilityCheck(diag, decl);
break;
case DelayedDiagnostic::Access:
@@ -5236,61 +4800,120 @@
return false;
}
+static bool isDeclUnavailable(Decl *D) {
+ do {
+ if (D->isUnavailable())
+ return true;
+ // A category implicitly has the availability of the interface.
+ if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D))
+ return CatD->getClassInterface()->isUnavailable();
+ } while ((D = cast_or_null<Decl>(D->getDeclContext())));
+ return false;
+}
+
static void
-DoEmitDeprecationWarning(Sema &S, const NamedDecl *D, StringRef Message,
- SourceLocation Loc,
- const ObjCInterfaceDecl *UnknownObjCClass,
- const ObjCPropertyDecl *ObjCPropery) {
+DoEmitAvailabilityWarning(Sema &S,
+ DelayedDiagnostic::DDKind K,
+ Decl *Ctx,
+ const NamedDecl *D,
+ StringRef Message,
+ SourceLocation Loc,
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ const ObjCPropertyDecl *ObjCProperty) {
+
+ // Diagnostics for deprecated or unavailable.
+ unsigned diag, diag_message, diag_fwdclass_message;
+
+ // Matches 'diag::note_property_attribute' options.
+ unsigned property_note_select;
+
+ // Matches diag::note_availability_specified_here.
+ unsigned available_here_select_kind;
+
+ // Don't warn if our current context is deprecated or unavailable.
+ switch (K) {
+ case DelayedDiagnostic::Deprecation:
+ if (isDeclDeprecated(Ctx))
+ return;
+ diag = diag::warn_deprecated;
+ diag_message = diag::warn_deprecated_message;
+ diag_fwdclass_message = diag::warn_deprecated_fwdclass_message;
+ property_note_select = /* deprecated */ 0;
+ available_here_select_kind = /* deprecated */ 2;
+ break;
+
+ case DelayedDiagnostic::Unavailable:
+ if (isDeclUnavailable(Ctx))
+ return;
+ diag = diag::err_unavailable;
+ diag_message = diag::err_unavailable_message;
+ diag_fwdclass_message = diag::warn_unavailable_fwdclass_message;
+ property_note_select = /* unavailable */ 1;
+ available_here_select_kind = /* unavailable */ 0;
+ break;
+
+ default:
+ llvm_unreachable("Neither a deprecation or unavailable kind");
+ }
+
DeclarationName Name = D->getDeclName();
if (!Message.empty()) {
- S.Diag(Loc, diag::warn_deprecated_message) << Name << Message;
- S.Diag(D->getLocation(),
- isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at
- : diag::note_previous_decl) << Name;
- if (ObjCPropery)
- S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute)
- << ObjCPropery->getDeclName() << 0;
+ S.Diag(Loc, diag_message) << Name << Message;
+ if (ObjCProperty)
+ S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
+ << ObjCProperty->getDeclName() << property_note_select;
} else if (!UnknownObjCClass) {
- S.Diag(Loc, diag::warn_deprecated) << D->getDeclName();
- S.Diag(D->getLocation(),
- isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at
- : diag::note_previous_decl) << Name;
- if (ObjCPropery)
- S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute)
- << ObjCPropery->getDeclName() << 0;
+ S.Diag(Loc, diag) << Name;
+ if (ObjCProperty)
+ S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
+ << ObjCProperty->getDeclName() << property_note_select;
} else {
- S.Diag(Loc, diag::warn_deprecated_fwdclass_message) << Name;
+ S.Diag(Loc, diag_fwdclass_message) << Name;
S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
}
+
+ S.Diag(D->getLocation(), diag::note_availability_specified_here)
+ << D << available_here_select_kind;
}
-void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD,
- Decl *Ctx) {
- if (isDeclDeprecated(Ctx))
- return;
-
+void Sema::HandleDelayedAvailabilityCheck(DelayedDiagnostic &DD,
+ Decl *Ctx) {
DD.Triggered = true;
- DoEmitDeprecationWarning(*this, DD.getDeprecationDecl(),
- DD.getDeprecationMessage(), DD.Loc,
- DD.getUnknownObjCClass(),
- DD.getObjCProperty());
+ DoEmitAvailabilityWarning(*this,
+ (DelayedDiagnostic::DDKind) DD.Kind,
+ Ctx,
+ DD.getDeprecationDecl(),
+ DD.getDeprecationMessage(),
+ DD.Loc,
+ DD.getUnknownObjCClass(),
+ DD.getObjCProperty());
}
-void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message,
- SourceLocation Loc,
- const ObjCInterfaceDecl *UnknownObjCClass,
- const ObjCPropertyDecl *ObjCProperty) {
+void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD,
+ NamedDecl *D, StringRef Message,
+ SourceLocation Loc,
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ const ObjCPropertyDecl *ObjCProperty) {
// Delay if we're currently parsing a declaration.
if (DelayedDiagnostics.shouldDelayDiagnostics()) {
- DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D,
- UnknownObjCClass,
- ObjCProperty,
- Message));
+ DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(AD, Loc, D,
+ UnknownObjCClass,
+ ObjCProperty,
+ Message));
return;
}
- // Otherwise, don't warn if our current context is deprecated.
- if (isDeclDeprecated(cast<Decl>(getCurLexicalContext())))
- return;
- DoEmitDeprecationWarning(*this, D, Message, Loc, UnknownObjCClass, ObjCProperty);
+ Decl *Ctx = cast<Decl>(getCurLexicalContext());
+ DelayedDiagnostic::DDKind K;
+ switch (AD) {
+ case AD_Deprecation:
+ K = DelayedDiagnostic::Deprecation;
+ break;
+ case AD_Unavailable:
+ K = DelayedDiagnostic::Unavailable;
+ break;
+ }
+
+ DoEmitAvailabilityWarning(*this, K, Ctx, D, Message, Loc,
+ UnknownObjCClass, ObjCProperty);
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 6b3400a..850db26 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -212,11 +212,9 @@
"Shouldn't collect exceptions when throw-all is guaranteed.");
ComputedEST = EST_Dynamic;
// Record the exceptions in this function's exception specification.
- for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
- EEnd = Proto->exception_end();
- E != EEnd; ++E)
- if (ExceptionsSeen.insert(Self->Context.getCanonicalType(*E)))
- Exceptions.push_back(*E);
+ for (const auto &E : Proto->exceptions())
+ if (ExceptionsSeen.insert(Self->Context.getCanonicalType(E)))
+ Exceptions.push_back(E);
}
void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) {
@@ -380,16 +378,16 @@
MightBeFunction = false;
continue;
}
- for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) {
- ParmVarDecl *Param =
- cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param);
+ for (unsigned argIdx = 0, e = chunk.Fun.NumParams; argIdx != e;
+ ++argIdx) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(chunk.Fun.Params[argIdx].Param);
if (Param->hasUnparsedDefaultArg()) {
- CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens;
+ CachedTokens *Toks = chunk.Fun.Params[argIdx].DefaultArgTokens;
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
<< SourceRange((*Toks)[1].getLocation(),
Toks->back().getLocation());
delete Toks;
- chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0;
+ chunk.Fun.Params[argIdx].DefaultArgTokens = 0;
} else if (Param->getDefaultArg()) {
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
<< Param->getDefaultArg()->getSourceRange();
@@ -586,6 +584,7 @@
}
}
+ const FunctionDecl *Def;
// C++11 [dcl.constexpr]p1: If any declaration of a function or function
// template has a constexpr specifier then all its declarations shall
// contain the constexpr specifier.
@@ -594,6 +593,13 @@
<< New << New->isConstexpr();
Diag(Old->getLocation(), diag::note_previous_declaration);
Invalid = true;
+ } else if (!Old->isInlined() && New->isInlined() && Old->isDefined(Def)) {
+ // C++11 [dcl.fcn.spec]p4:
+ // If the definition of a function appears in a translation unit before its
+ // first declaration as inline, the program is ill-formed.
+ Diag(New->getLocation(), diag::err_inline_decl_follows_def) << New;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ Invalid = true;
}
// C++11 [dcl.fct.default]p4: If a friend declaration specifies a default
@@ -714,8 +720,9 @@
const FunctionDecl *FD) {
unsigned ArgIndex = 0;
const FunctionProtoType *FT = FD->getType()->getAs<FunctionProtoType>();
- for (FunctionProtoType::arg_type_iterator i = FT->arg_type_begin(),
- e = FT->arg_type_end(); i != e; ++i, ++ArgIndex) {
+ for (FunctionProtoType::param_type_iterator i = FT->param_type_begin(),
+ e = FT->param_type_end();
+ i != e; ++i, ++ArgIndex) {
const ParmVarDecl *PD = FD->getParamDecl(ArgIndex);
SourceLocation ParamLoc = PD->getLocation();
if (!(*i)->isDependentType() &&
@@ -760,10 +767,9 @@
Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base)
<< isa<CXXConstructorDecl>(NewFD)
<< getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
- for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
- E = RD->vbases_end(); I != E; ++I)
- Diag(I->getLocStart(),
- diag::note_constexpr_virtual_base_here) << I->getSourceRange();
+ for (const auto &I : RD->vbases())
+ Diag(I.getLocStart(),
+ diag::note_constexpr_virtual_base_here) << I.getSourceRange();
return false;
}
}
@@ -789,7 +795,7 @@
}
// - its return type shall be a literal type;
- QualType RT = NewFD->getResultType();
+ QualType RT = NewFD->getReturnType();
if (!RT->isDependentType() &&
RequireLiteralType(NewFD->getLocation(), RT,
diag::err_constexpr_non_literal_return))
@@ -813,9 +819,8 @@
// C++11 [dcl.constexpr]p3 and p4:
// The definition of a constexpr function(p3) or constructor(p4) [...] shall
// contain only
- for (DeclStmt::decl_iterator DclIt = DS->decl_begin(),
- DclEnd = DS->decl_end(); DclIt != DclEnd; ++DclIt) {
- switch ((*DclIt)->getKind()) {
+ for (const auto *DclIt : DS->decls()) {
+ switch (DclIt->getKind()) {
case Decl::StaticAssert:
case Decl::Using:
case Decl::UsingShadow:
@@ -831,7 +836,7 @@
case Decl::TypeAlias: {
// - typedef declarations and alias-declarations that do not define
// classes or enumerations,
- TypedefNameDecl *TN = cast<TypedefNameDecl>(*DclIt);
+ const auto *TN = cast<TypedefNameDecl>(DclIt);
if (TN->getUnderlyingType()->isVariablyModifiedType()) {
// Don't allow variably-modified types in constexpr functions.
TypeLoc TL = TN->getTypeSourceInfo()->getTypeLoc();
@@ -846,7 +851,7 @@
case Decl::Enum:
case Decl::CXXRecord:
// C++1y allows types to be defined, not just declared.
- if (cast<TagDecl>(*DclIt)->isThisDeclarationADefinition())
+ if (cast<TagDecl>(DclIt)->isThisDeclarationADefinition())
SemaRef.Diag(DS->getLocStart(),
SemaRef.getLangOpts().CPlusPlus1y
? diag::warn_cxx11_compat_constexpr_type_definition
@@ -865,7 +870,7 @@
// C++1y [dcl.constexpr]p3 allows anything except:
// a definition of a variable of non-literal type or of static or
// thread storage duration or for which no initialization is performed.
- VarDecl *VD = cast<VarDecl>(*DclIt);
+ const auto *VD = cast<VarDecl>(DclIt);
if (VD->isThisDeclarationADefinition()) {
if (VD->isStaticLocal()) {
SemaRef.Diag(VD->getLocation(),
@@ -880,7 +885,8 @@
diag::err_constexpr_local_var_non_literal_type,
isa<CXXConstructorDecl>(Dcl)))
return false;
- if (!VD->hasInit() && !VD->isCXXForRangeDecl()) {
+ if (!VD->getType()->isDependentType() &&
+ !VD->hasInit() && !VD->isCXXForRangeDecl()) {
SemaRef.Diag(VD->getLocation(),
diag::err_constexpr_local_var_no_init)
<< isa<CXXConstructorDecl>(Dcl);
@@ -932,8 +938,13 @@
if (Field->isUnnamedBitfield())
return;
+ // Anonymous unions with no variant members and empty anonymous structs do not
+ // need to be explicitly initialized. FIXME: Anonymous structs that contain no
+ // indirect fields don't need initializing.
if (Field->isAnonymousStructOrUnion() &&
- Field->getType()->getAsCXXRecordDecl()->isEmpty())
+ (Field->getType()->isUnionType()
+ ? !Field->getType()->getAsCXXRecordDecl()->hasVariantMembers()
+ : Field->getType()->getAsCXXRecordDecl()->isEmpty()))
return;
if (!Inits.count(Field)) {
@@ -944,12 +955,11 @@
SemaRef.Diag(Field->getLocation(), diag::note_constexpr_ctor_missing_init);
} else if (Field->isAnonymousStructOrUnion()) {
const RecordDecl *RD = Field->getType()->castAs<RecordType>()->getDecl();
- for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
- I != E; ++I)
+ for (auto *I : RD->fields())
// If an anonymous union contains an anonymous struct of which any member
// is initialized, all members must be initialized.
- if (!RD->isUnion() || Inits.count(*I))
- CheckConstexprCtorInitializer(SemaRef, Dcl, *I, Inits, Diagnosed);
+ if (!RD->isUnion() || Inits.count(I))
+ CheckConstexprCtorInitializer(SemaRef, Dcl, I, Inits, Diagnosed);
}
}
@@ -993,9 +1003,8 @@
Cxx1yLoc = S->getLocStart();
CompoundStmt *CompStmt = cast<CompoundStmt>(S);
- for (CompoundStmt::body_iterator BodyIt = CompStmt->body_begin(),
- BodyEnd = CompStmt->body_end(); BodyIt != BodyEnd; ++BodyIt) {
- if (!CheckConstexprFunctionStmt(SemaRef, Dcl, *BodyIt, ReturnStmts,
+ for (auto *BodyIt : CompStmt->body()) {
+ if (!CheckConstexprFunctionStmt(SemaRef, Dcl, BodyIt, ReturnStmts,
Cxx1yLoc))
return false;
}
@@ -1097,9 +1106,8 @@
// [... list of cases ...]
CompoundStmt *CompBody = cast<CompoundStmt>(Body);
SourceLocation Cxx1yLoc;
- for (CompoundStmt::body_iterator BodyIt = CompBody->body_begin(),
- BodyEnd = CompBody->body_end(); BodyIt != BodyEnd; ++BodyIt) {
- if (!CheckConstexprFunctionStmt(*this, Dcl, *BodyIt, ReturnStmts, Cxx1yLoc))
+ for (auto *BodyIt : CompBody->body()) {
+ if (!CheckConstexprFunctionStmt(*this, Dcl, BodyIt, ReturnStmts, Cxx1yLoc))
return false;
}
@@ -1116,11 +1124,12 @@
// DR1359:
// - every non-variant non-static data member and base class sub-object
// shall be initialized;
- // - if the class is a non-empty union, or for each non-empty anonymous
- // union member of a non-union class, exactly one non-static data member
+ // DR1460:
+ // - if the class is a union having variant members, exactly one of them
// shall be initialized;
if (RD->isUnion()) {
- if (Constructor->getNumCtorInitializers() == 0 && !RD->isEmpty()) {
+ if (Constructor->getNumCtorInitializers() == 0 &&
+ RD->hasVariantMembers()) {
Diag(Dcl->getLocation(), diag::err_constexpr_union_ctor_no_init);
return false;
}
@@ -1139,25 +1148,26 @@
break;
}
}
+ // DR1460:
+ // - if the class is a union-like class, but is not a union, for each of
+ // its anonymous union members having variant members, exactly one of
+ // them shall be initialized;
if (AnyAnonStructUnionMembers ||
Constructor->getNumCtorInitializers() != RD->getNumBases() + Fields) {
// Check initialization of non-static data members. Base classes are
// always initialized so do not need to be checked. Dependent bases
// might not have initializers in the member initializer list.
llvm::SmallSet<Decl*, 16> Inits;
- for (CXXConstructorDecl::init_const_iterator
- I = Constructor->init_begin(), E = Constructor->init_end();
- I != E; ++I) {
- if (FieldDecl *FD = (*I)->getMember())
+ for (const auto *I: Constructor->inits()) {
+ if (FieldDecl *FD = I->getMember())
Inits.insert(FD);
- else if (IndirectFieldDecl *ID = (*I)->getIndirectMember())
+ else if (IndirectFieldDecl *ID = I->getIndirectMember())
Inits.insert(ID->chain_begin(), ID->chain_end());
}
bool Diagnosed = false;
- for (CXXRecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end(); I != E; ++I)
- CheckConstexprCtorInitializer(*this, Dcl, *I, Inits, Diagnosed);
+ for (auto *I : RD->fields())
+ CheckConstexprCtorInitializer(*this, Dcl, I, Inits, Diagnosed);
if (Diagnosed)
return false;
}
@@ -1168,7 +1178,7 @@
// statement. We still do, unless the return type is void, because
// otherwise if there's no return statement, the function cannot
// be used in a core constant expression.
- bool OK = getLangOpts().CPlusPlus1y && Dcl->getResultType()->isVoidType();
+ bool OK = getLangOpts().CPlusPlus1y && Dcl->getReturnType()->isVoidType();
Diag(Dcl->getLocation(),
OK ? diag::warn_cxx11_compat_constexpr_body_no_return
: diag::err_constexpr_body_no_return);
@@ -1261,10 +1271,8 @@
Class = Class->getCanonicalDecl();
while (true) {
- for (CXXRecordDecl::base_class_const_iterator I = Current->bases_begin(),
- E = Current->bases_end();
- I != E; ++I) {
- CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl();
+ for (const auto &I : Current->bases()) {
+ CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
if (!Base)
continue;
@@ -1509,7 +1517,7 @@
Invalid = true;
}
if (RD->hasAttr<WeakAttr>())
- Class->addAttr(::new (Context) WeakAttr(SourceRange(), Context));
+ Class->addAttr(WeakAttr::CreateImplicit(Context));
}
}
}
@@ -1965,7 +1973,8 @@
const char *PrevSpec;
unsigned DiagID;
if (D.getMutableDeclSpec().SetStorageClassSpec(
- *this, DeclSpec::SCS_static, ConstexprLoc, PrevSpec, DiagID)) {
+ *this, DeclSpec::SCS_static, ConstexprLoc, PrevSpec, DiagID,
+ Context.getPrintingPolicy())) {
assert(DS.getStorageClassSpec() == DeclSpec::SCS_mutable &&
"This is the only DeclSpec that should fail to be applied");
B << 1;
@@ -2082,7 +2091,7 @@
}
if (VS.isOverrideSpecified())
- Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context));
+ Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context, 0));
if (VS.isFinalSpecified())
Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context,
VS.isFinalSpelledSealed()));
@@ -2306,38 +2315,44 @@
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)) {
+ for (auto *I : RD->decls()) {
+ if (auto *FD = dyn_cast<FieldDecl>(I)) {
UninitializedFields.insert(FD);
- } else if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(*I)) {
+ } else if (auto *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();
+ for (const auto *FieldInit : Constructor->inits()) {
+ Expr *InitExpr = FieldInit->getInit();
CheckInitExprContainsUninitializedFields(
SemaRef, InitExpr, UninitializedFields, Constructor);
- if (FieldDecl *Field = (*FieldInit)->getAnyMember())
+ if (FieldDecl *Field = FieldInit->getAnyMember())
UninitializedFields.erase(Field);
}
}
} // namespace
-/// ActOnCXXInClassMemberInitializer - This is invoked after parsing an
-/// in-class initializer for a non-static C++ class member, and after
-/// instantiating an in-class initializer in a class template. Such actions
-/// are deferred until the class is complete.
-void
-Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc,
- Expr *InitExpr) {
+/// \brief Enter a new C++ default initializer scope. After calling this, the
+/// caller must call \ref ActOnFinishCXXInClassMemberInitializer, even if
+/// parsing or instantiating the initializer failed.
+void Sema::ActOnStartCXXInClassMemberInitializer() {
+ // Create a synthetic function scope to represent the call to the constructor
+ // that notionally surrounds a use of this initializer.
+ PushFunctionScope();
+}
+
+/// \brief This is invoked after parsing an in-class initializer for a
+/// non-static C++ class member, and after instantiating an in-class initializer
+/// in a class template. Such actions are deferred until the class is complete.
+void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
+ SourceLocation InitLoc,
+ Expr *InitExpr) {
+ // Pop the notional constructor scope we created earlier.
+ PopFunctionScopeInfo(0, D);
+
FieldDecl *FD = cast<FieldDecl>(D);
assert(FD->getInClassInitStyle() != ICIS_NoInit &&
"must set init style when field is created");
@@ -2392,13 +2407,11 @@
const CXXBaseSpecifier *&VirtualBaseSpec) {
// First, check for a direct base class.
DirectBaseSpec = 0;
- for (CXXRecordDecl::base_class_const_iterator Base
- = ClassDecl->bases_begin();
- Base != ClassDecl->bases_end(); ++Base) {
- if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base->getType())) {
+ for (const auto &Base : ClassDecl->bases()) {
+ if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base.getType())) {
// We found a direct base of this type. That's what we're
// initializing.
- DirectBaseSpec = &*Base;
+ DirectBaseSpec = &Base;
break;
}
}
@@ -2471,7 +2484,7 @@
explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl)
: ClassDecl(ClassDecl) {}
- bool ValidateCandidate(const TypoCorrection &candidate) LLVM_OVERRIDE {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
if (NamedDecl *ND = candidate.getCorrectionDecl()) {
if (FieldDecl *Member = dyn_cast<FieldDecl>(ND))
return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl);
@@ -2629,13 +2642,10 @@
if (BaseType.isNull()) {
BaseType = Context.getTypeDeclType(TyD);
- if (SS.isSet()) {
- NestedNameSpecifier *Qualifier =
- static_cast<NestedNameSpecifier*>(SS.getScopeRep());
-
+ if (SS.isSet())
// FIXME: preserve source range information
- BaseType = Context.getElaboratedType(ETK_None, Qualifier, BaseType);
- }
+ BaseType = Context.getElaboratedType(ETK_None, SS.getScopeRep(),
+ BaseType);
}
}
@@ -3320,6 +3330,7 @@
ImplicitInitializerKind IIK;
llvm::DenseMap<const void *, CXXCtorInitializer*> AllBaseFields;
SmallVector<CXXCtorInitializer*, 8> AllToInit;
+ llvm::DenseMap<TagDecl*, FieldDecl*> ActiveUnionMember;
BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits)
: S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) {
@@ -3357,20 +3368,48 @@
return false;
}
-};
-}
-/// \brief Determine whether the given indirect field declaration is somewhere
-/// within an anonymous union.
-static bool isWithinAnonymousUnion(IndirectFieldDecl *F) {
- for (IndirectFieldDecl::chain_iterator C = F->chain_begin(),
- CEnd = F->chain_end();
- C != CEnd; ++C)
- if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>((*C)->getDeclContext()))
- if (Record->isUnion())
+ bool isInactiveUnionMember(FieldDecl *Field) {
+ RecordDecl *Record = Field->getParent();
+ if (!Record->isUnion())
+ return false;
+
+ if (FieldDecl *Active =
+ ActiveUnionMember.lookup(Record->getCanonicalDecl()))
+ return Active != Field->getCanonicalDecl();
+
+ // In an implicit copy or move constructor, ignore any in-class initializer.
+ if (isImplicitCopyOrMove())
+ return true;
+
+ // If there's no explicit initialization, the field is active only if it
+ // has an in-class initializer...
+ if (Field->hasInClassInitializer())
+ return false;
+ // ... or it's an anonymous struct or union whose class has an in-class
+ // initializer.
+ if (!Field->isAnonymousStructOrUnion())
+ return true;
+ CXXRecordDecl *FieldRD = Field->getType()->getAsCXXRecordDecl();
+ return !FieldRD->hasInClassInitializer();
+ }
+
+ /// \brief Determine whether the given field is, or is within, a union member
+ /// that is inactive (because there was an initializer given for a different
+ /// member of the union, or because the union was not initialized at all).
+ bool isWithinInactiveUnionMember(FieldDecl *Field,
+ IndirectFieldDecl *Indirect) {
+ if (!Indirect)
+ return isInactiveUnionMember(Field);
+
+ for (auto *C : Indirect->chain()) {
+ FieldDecl *Field = dyn_cast<FieldDecl>(C);
+ if (Field && isInactiveUnionMember(Field))
return true;
-
- return false;
+ }
+ return false;
+ }
+};
}
/// \brief Determine whether the given type is an incomplete or zero-lenfgth
@@ -3399,9 +3438,21 @@
if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(Field))
return Info.addFieldInitializer(Init);
- // C++11 [class.base.init]p8: if the entity is a non-static data member that
- // has a brace-or-equal-initializer, the entity is initialized as specified
- // in [dcl.init].
+ // C++11 [class.base.init]p8:
+ // if the entity is a non-static data member that has a
+ // brace-or-equal-initializer and either
+ // -- the constructor's class is a union and no other variant member of that
+ // union is designated by a mem-initializer-id or
+ // -- the constructor's class is not a union, and, if the entity is a member
+ // of an anonymous union, no other member of that union is designated by
+ // a mem-initializer-id,
+ // the entity is initialized as specified in [dcl.init].
+ //
+ // We also apply the same rules to handle anonymous structs within anonymous
+ // unions.
+ if (Info.isWithinInactiveUnionMember(Field, Indirect))
+ return false;
+
if (Field->hasInClassInitializer() && !Info.isImplicitCopyOrMove()) {
Expr *DIE = CXXDefaultInitExpr::Create(SemaRef.Context,
Info.Ctor->getLocation(), Field);
@@ -3419,12 +3470,6 @@
return Info.addFieldInitializer(Init);
}
- // Don't build an implicit initializer for union members if none was
- // explicitly specified.
- if (Field->getParent()->isUnion() ||
- (Indirect && isWithinAnonymousUnion(Indirect)))
- return false;
-
// Don't initialize incomplete or zero-length arrays.
if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType()))
return false;
@@ -3502,24 +3547,35 @@
if (Member->isBaseInitializer())
Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
- else
+ else {
Info.AllBaseFields[Member->getAnyMember()] = Member;
+
+ if (IndirectFieldDecl *F = Member->getIndirectMember()) {
+ for (auto *C : F->chain()) {
+ FieldDecl *FD = dyn_cast<FieldDecl>(C);
+ if (FD && FD->getParent()->isUnion())
+ Info.ActiveUnionMember.insert(std::make_pair(
+ FD->getParent()->getCanonicalDecl(), FD->getCanonicalDecl()));
+ }
+ } else if (FieldDecl *FD = Member->getMember()) {
+ if (FD->getParent()->isUnion())
+ Info.ActiveUnionMember.insert(std::make_pair(
+ FD->getParent()->getCanonicalDecl(), FD->getCanonicalDecl()));
+ }
+ }
}
// Keep track of the direct virtual bases.
llvm::SmallPtrSet<CXXBaseSpecifier *, 16> DirectVBases;
- for (CXXRecordDecl::base_class_iterator I = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); I != E; ++I) {
- if (I->isVirtual())
- DirectVBases.insert(I);
+ for (auto &I : ClassDecl->bases()) {
+ if (I.isVirtual())
+ DirectVBases.insert(&I);
}
// Push virtual bases before others.
- for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
- E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
-
+ for (auto &VBase : ClassDecl->vbases()) {
if (CXXCtorInitializer *Value
- = Info.AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
+ = 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
@@ -3528,7 +3584,7 @@
// 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;
+ << VBase.getType() << ClassDecl;
DiagnoseAbstractType(ClassDecl);
}
@@ -3538,10 +3594,10 @@
// 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);
+ bool IsInheritedVirtualBase = !DirectVBases.count(&VBase);
CXXCtorInitializer *CXXBaseInit;
if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
- VBase, IsInheritedVirtualBase,
+ &VBase, IsInheritedVirtualBase,
CXXBaseInit)) {
HadError = true;
continue;
@@ -3552,19 +3608,18 @@
}
// Non-virtual bases.
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); Base != E; ++Base) {
+ for (auto &Base : ClassDecl->bases()) {
// Virtuals are in the virtual base list and already constructed.
- if (Base->isVirtual())
+ if (Base.isVirtual())
continue;
if (CXXCtorInitializer *Value
- = Info.AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
+ = Info.AllBaseFields.lookup(Base.getType()->getAs<RecordType>())) {
Info.AllToInit.push_back(Value);
} else if (!AnyErrors) {
CXXCtorInitializer *CXXBaseInit;
if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
- Base, /*IsInheritedVirtualBase=*/false,
+ &Base, /*IsInheritedVirtualBase=*/false,
CXXBaseInit)) {
HadError = true;
continue;
@@ -3575,10 +3630,8 @@
}
// Fields.
- for (DeclContext::decl_iterator Mem = ClassDecl->decls_begin(),
- MemEnd = ClassDecl->decls_end();
- Mem != MemEnd; ++Mem) {
- if (FieldDecl *F = dyn_cast<FieldDecl>(*Mem)) {
+ for (auto *Mem : ClassDecl->decls()) {
+ if (auto *F = dyn_cast<FieldDecl>(Mem)) {
// C++ [class.bit]p2:
// A declaration for a bit-field that omits the identifier declares an
// unnamed bit-field. Unnamed bit-fields are not members and cannot be
@@ -3601,7 +3654,7 @@
if (Info.isImplicitCopyOrMove())
continue;
- if (IndirectFieldDecl *F = dyn_cast<IndirectFieldDecl>(*Mem)) {
+ if (auto *F = dyn_cast<IndirectFieldDecl>(Mem)) {
if (F->getType()->isIncompleteArrayType()) {
assert(ClassDecl->hasFlexibleArrayMember() &&
"Incomplete array type is not valid");
@@ -3638,9 +3691,8 @@
if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
const RecordDecl *RD = RT->getDecl();
if (RD->isAnonymousStructOrUnion()) {
- for (RecordDecl::field_iterator Field = RD->field_begin(),
- E = RD->field_end(); Field != E; ++Field)
- PopulateKeysForFields(*Field, IdealInits);
+ for (auto *Field : RD->fields())
+ PopulateKeysForFields(Field, IdealInits);
return;
}
}
@@ -3688,26 +3740,22 @@
const CXXRecordDecl *ClassDecl = Constructor->getParent();
// 1. Virtual bases.
- for (CXXRecordDecl::base_class_const_iterator VBase =
- ClassDecl->vbases_begin(),
- E = ClassDecl->vbases_end(); VBase != E; ++VBase)
- IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, VBase->getType()));
+ for (const auto &VBase : ClassDecl->vbases())
+ IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, VBase.getType()));
// 2. Non-virtual bases.
- for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); Base != E; ++Base) {
- if (Base->isVirtual())
+ for (const auto &Base : ClassDecl->bases()) {
+ if (Base.isVirtual())
continue;
- IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, Base->getType()));
+ IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, Base.getType()));
}
// 3. Direct fields.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- E = ClassDecl->field_end(); Field != E; ++Field) {
+ for (auto *Field : ClassDecl->fields()) {
if (Field->isUnnamedBitfield())
continue;
- PopulateKeysForFields(*Field, IdealInitKeys);
+ PopulateKeysForFields(Field, IdealInitKeys);
}
unsigned NumIdealInits = IdealInitKeys.size();
@@ -3903,9 +3951,7 @@
// emitted, and we currently don't say.
// Non-static data members.
- for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
- E = ClassDecl->field_end(); I != E; ++I) {
- FieldDecl *Field = *I;
+ for (auto *Field : ClassDecl->fields()) {
if (Field->isInvalidDecl())
continue;
@@ -3942,13 +3988,12 @@
llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases;
// Bases.
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); Base != E; ++Base) {
+ for (const auto &Base : ClassDecl->bases()) {
// Bases are always records in a well-formed non-dependent class.
- const RecordType *RT = Base->getType()->getAs<RecordType>();
+ const RecordType *RT = Base.getType()->getAs<RecordType>();
// Remember direct virtual bases.
- if (Base->isVirtual())
+ if (Base.isVirtual())
DirectVirtualBases.insert(RT);
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
@@ -3962,10 +4007,10 @@
assert(Dtor && "No dtor found for BaseClassDecl!");
// FIXME: caret should be on the start of the class name
- CheckDestructorAccess(Base->getLocStart(), Dtor,
+ CheckDestructorAccess(Base.getLocStart(), Dtor,
PDiag(diag::err_access_dtor_base)
- << Base->getType()
- << Base->getSourceRange(),
+ << Base.getType()
+ << Base.getSourceRange(),
Context.getTypeDeclType(ClassDecl));
MarkFunctionReferenced(Location, Dtor);
@@ -3973,11 +4018,9 @@
}
// Virtual bases.
- for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
- E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
-
+ for (const auto &VBase : ClassDecl->vbases()) {
// Bases are always records in a well-formed non-dependent class.
- const RecordType *RT = VBase->getType()->castAs<RecordType>();
+ const RecordType *RT = VBase.getType()->castAs<RecordType>();
// Ignore direct virtual bases.
if (DirectVirtualBases.count(RT))
@@ -3995,11 +4038,11 @@
if (CheckDestructorAccess(
ClassDecl->getLocation(), Dtor,
PDiag(diag::err_access_dtor_vbase)
- << Context.getTypeDeclType(ClassDecl) << VBase->getType(),
+ << Context.getTypeDeclType(ClassDecl) << VBase.getType(),
Context.getTypeDeclType(ClassDecl)) ==
AR_accessible) {
CheckDerivedToBaseConversion(
- Context.getTypeDeclType(ClassDecl), VBase->getType(),
+ Context.getTypeDeclType(ClassDecl), VBase.getType(),
diag::err_access_dtor_vbase, 0, ClassDecl->getLocation(),
SourceRange(), DeclarationName(), 0);
}
@@ -4030,7 +4073,7 @@
NonAbstractTypeDiagnoser(unsigned DiagID, AbstractDiagSelID SelID)
: TypeDiagnoser(DiagID == 0), DiagID(DiagID), SelID(SelID) { }
- void diagnose(Sema &S, SourceLocation Loc, QualType T) LLVM_OVERRIDE {
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
if (Suppressed) return;
if (SelID == -1)
S.Diag(Loc, DiagID) << T;
@@ -4172,12 +4215,12 @@
}
void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) {
- Visit(TL.getResultLoc(), Sema::AbstractReturnType);
- for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
- if (!TL.getArg(I))
+ Visit(TL.getReturnLoc(), Sema::AbstractReturnType);
+ for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) {
+ if (!TL.getParam(I))
continue;
-
- TypeSourceInfo *TSI = TL.getArg(I)->getTypeSourceInfo();
+
+ TypeSourceInfo *TSI = TL.getParam(I)->getTypeSourceInfo();
if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType);
}
}
@@ -4267,9 +4310,7 @@
/// Check for invalid uses of an abstract type within a class definition.
static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
CXXRecordDecl *RD) {
- for (CXXRecordDecl::decl_iterator
- I = RD->decls_begin(), E = RD->decls_end(); I != E; ++I) {
- Decl *D = *I;
+ for (auto *D : RD->decls()) {
if (D->isImplicit()) continue;
// Methods and method templates.
@@ -4318,9 +4359,7 @@
!Record->isAggregate() && !Record->hasUserDeclaredConstructor() &&
!Record->isLambda()) {
bool Complained = false;
- for (RecordDecl::field_iterator F = Record->field_begin(),
- FEnd = Record->field_end();
- F != FEnd; ++F) {
+ for (const auto *F : Record->fields()) {
if (F->hasInClassInitializer() || F->isUnnamedBitfield())
continue;
@@ -4381,27 +4420,25 @@
}
if (!Record->isDependentType()) {
- for (CXXRecordDecl::method_iterator M = Record->method_begin(),
- MEnd = Record->method_end();
- M != MEnd; ++M) {
+ for (auto *M : Record->methods()) {
// See if a method overloads virtual methods in a base
// class without overriding any.
if (!M->isStatic())
- DiagnoseHiddenVirtualMethods(*M);
+ DiagnoseHiddenVirtualMethods(M);
// Check whether the explicitly-defaulted special members are valid.
if (!M->isInvalidDecl() && M->isExplicitlyDefaulted())
- CheckExplicitlyDefaultedSpecialMember(*M);
+ CheckExplicitlyDefaultedSpecialMember(M);
// For an explicitly defaulted or deleted special member, we defer
// determining triviality until the class is complete. That time is now!
if (!M->isImplicit() && !M->isUserProvided()) {
- CXXSpecialMember CSM = getSpecialMember(*M);
+ CXXSpecialMember CSM = getSpecialMember(M);
if (CSM != CXXInvalid) {
- M->setTrivial(SpecialMemberIsTrivial(*M, CSM));
+ M->setTrivial(SpecialMemberIsTrivial(M, CSM));
// Inform the class that we've finished declaring this member.
- Record->finishedDefaultedOrDeletedMember(*M);
+ Record->finishedDefaultedOrDeletedMember(M);
}
}
}
@@ -4420,10 +4457,8 @@
// destructor for the class is trivial.
if (LangOpts.CPlusPlus11 && !Record->isDependentType() &&
!Record->isLiteral() && !Record->getNumVBases()) {
- for (CXXRecordDecl::method_iterator M = Record->method_begin(),
- MEnd = Record->method_end();
- M != MEnd; ++M) {
- if (M->isConstexpr() && M->isInstance() && !isa<CXXConstructorDecl>(*M)) {
+ for (const auto *M : Record->methods()) {
+ if (M->isConstexpr() && M->isInstance() && !isa<CXXConstructorDecl>(M)) {
switch (Record->getTemplateSpecializationKind()) {
case TSK_ImplicitInstantiation:
case TSK_ExplicitInstantiationDeclaration:
@@ -4446,11 +4481,18 @@
}
}
- // 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>();
+ // ms_struct is a request to use the same ABI rules as MSVC. Check
+ // whether this class uses any C++ features that are implemented
+ // completely differently in MSVC, and if so, emit a diagnostic.
+ // That diagnostic defaults to an error, but we allow projects to
+ // map it down to a warning (or ignore it). It's a fairly common
+ // practice among users of the ms_struct pragma to mass-annotate
+ // headers, sweeping up a bunch of types that the project doesn't
+ // really rely on MSVC-compatible layout for. We must therefore
+ // support "ms_struct except for C++ stuff" as a secondary ABI.
+ if (Record->isMsStruct(Context) &&
+ (Record->isPolymorphic() || Record->getNumBases())) {
+ Diag(Record->getLocation(), diag::warn_cxx_ms_struct);
}
// Declare inheriting constructors. We do this eagerly here because:
@@ -4463,14 +4505,43 @@
DeclareInheritingConstructors(Record);
}
+/// Look up the special member function that would be called by a special
+/// member function for a subobject of class type.
+///
+/// \param Class The class type of the subobject.
+/// \param CSM The kind of special member function.
+/// \param FieldQuals If the subobject is a field, its cv-qualifiers.
+/// \param ConstRHS True if this is a copy operation with a const object
+/// on its RHS, that is, if the argument to the outer special member
+/// function is 'const' and this is not a field marked 'mutable'.
+static Sema::SpecialMemberOverloadResult *lookupCallFromSpecialMember(
+ Sema &S, CXXRecordDecl *Class, Sema::CXXSpecialMember CSM,
+ unsigned FieldQuals, bool ConstRHS) {
+ unsigned LHSQuals = 0;
+ if (CSM == Sema::CXXCopyAssignment || CSM == Sema::CXXMoveAssignment)
+ LHSQuals = FieldQuals;
+
+ unsigned RHSQuals = FieldQuals;
+ if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor)
+ RHSQuals = 0;
+ else if (ConstRHS)
+ RHSQuals |= Qualifiers::Const;
+
+ return S.LookupSpecialMember(Class, CSM,
+ RHSQuals & Qualifiers::Const,
+ RHSQuals & Qualifiers::Volatile,
+ false,
+ LHSQuals & Qualifiers::Const,
+ LHSQuals & Qualifiers::Volatile);
+}
+
/// Is the special member function which would be selected to perform the
/// specified operation on the specified class type a constexpr constructor?
static bool specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
Sema::CXXSpecialMember CSM,
- bool ConstArg) {
+ unsigned Quals, bool ConstRHS) {
Sema::SpecialMemberOverloadResult *SMOR =
- S.LookupSpecialMember(ClassDecl, CSM, ConstArg,
- false, false, false, false);
+ lookupCallFromSpecialMember(S, ClassDecl, CSM, Quals, ConstRHS);
if (!SMOR || !SMOR->getMethod())
// A constructor we wouldn't select can't be "involved in initializing"
// anything.
@@ -4540,14 +4611,12 @@
// 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) {
- const RecordType *BaseType = B->getType()->getAs<RecordType>();
+ for (const auto &B : ClassDecl->bases()) {
+ const RecordType *BaseType = B.getType()->getAs<RecordType>();
if (!BaseType) continue;
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
- if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, ConstArg))
+ if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg))
return false;
}
@@ -4555,18 +4624,18 @@
// [...] 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
+ // -- for each non-static 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) {
+ for (const auto *F : ClassDecl->fields()) {
if (F->isInvalidDecl())
continue;
- if (const RecordType *RecordTy =
- S.Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
+ QualType BaseType = S.Context.getBaseElementType(F->getType());
+ if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
- if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM, ConstArg))
+ if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM,
+ BaseType.getCVRQualifiers(),
+ ConstArg && !F->isMutable()))
return false;
}
}
@@ -4598,15 +4667,6 @@
return S.ComputeInheritingCtorExceptionSpec(cast<CXXConstructorDecl>(MD));
}
-static void
-updateExceptionSpec(Sema &S, FunctionDecl *FD, const FunctionProtoType *FPT,
- const Sema::ImplicitExceptionSpecification &ExceptSpec) {
- FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- ExceptSpec.getEPI(EPI);
- FD->setType(S.Context.getFunctionType(FPT->getResultType(),
- FPT->getArgTypes(), EPI));
-}
-
static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S,
CXXMethodDecl *MD) {
FunctionProtoType::ExtProtoInfo EPI;
@@ -4631,8 +4691,11 @@
ImplicitExceptionSpecification ExceptSpec =
computeImplicitExceptionSpec(*this, Loc, MD);
+ FunctionProtoType::ExtProtoInfo EPI;
+ ExceptSpec.getEPI(EPI);
+
// Update the type of the special member to use it.
- updateExceptionSpec(*this, MD, FPT, ExceptSpec);
+ UpdateExceptionSpec(MD, EPI);
// A user-provided destructor can be defined outside the class. When that
// happens, be sure to update the exception specification on both
@@ -4640,8 +4703,7 @@
const FunctionProtoType *CanonicalFPT =
MD->getCanonicalDecl()->getType()->castAs<FunctionProtoType>();
if (CanonicalFPT->getExceptionSpecType() == EST_Unevaluated)
- updateExceptionSpec(*this, MD->getCanonicalDecl(),
- CanonicalFPT, ExceptSpec);
+ UpdateExceptionSpec(MD->getCanonicalDecl(), EPI);
}
void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
@@ -4691,7 +4753,7 @@
QualType ReturnType = Context.VoidTy;
if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) {
// Check for return type matching.
- ReturnType = Type->getResultType();
+ ReturnType = Type->getReturnType();
QualType ExpectedReturnType =
Context.getLValueReferenceType(Context.getTypeDeclType(RD));
if (!Context.hasSameType(ReturnType, ExpectedReturnType)) {
@@ -4709,7 +4771,7 @@
}
// Check for parameter type matching.
- QualType ArgType = ExpectedParams ? Type->getArgType(0) : QualType();
+ QualType ArgType = ExpectedParams ? Type->getParamType(0) : QualType();
bool HasConstParam = false;
if (ExpectedParams && ArgType->isReferenceType()) {
// Argument must be reference to possibly-const T.
@@ -4803,6 +4865,7 @@
// [For a] user-provided explicitly-defaulted function [...] if such a
// function is implicitly defined as deleted, the program is ill-formed.
Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM;
+ ShouldDeleteSpecialMember(MD, CSM, /*Diagnose*/true);
HadError = true;
}
}
@@ -4865,7 +4928,7 @@
bool Diagnose;
// Properties of the special member, computed for convenience.
- bool IsConstructor, IsAssignment, IsMove, ConstArg, VolatileArg;
+ bool IsConstructor, IsAssignment, IsMove, ConstArg;
SourceLocation Loc;
bool AllFieldsAreConst;
@@ -4874,7 +4937,7 @@
Sema::CXXSpecialMember CSM, bool Diagnose)
: S(S), MD(MD), CSM(CSM), Diagnose(Diagnose),
IsConstructor(false), IsAssignment(false), IsMove(false),
- ConstArg(false), VolatileArg(false), Loc(MD->getLocation()),
+ ConstArg(false), Loc(MD->getLocation()),
AllFieldsAreConst(true) {
switch (CSM) {
case Sema::CXXDefaultConstructor:
@@ -4899,8 +4962,9 @@
}
if (MD->getNumParams()) {
- ConstArg = MD->getParamDecl(0)->getType().isConstQualified();
- VolatileArg = MD->getParamDecl(0)->getType().isVolatileQualified();
+ if (const ReferenceType *RT =
+ MD->getParamDecl(0)->getType()->getAs<ReferenceType>())
+ ConstArg = RT->getPointeeType().isConstQualified();
}
}
@@ -4908,21 +4972,9 @@
/// Look up the corresponding special member in the given class.
Sema::SpecialMemberOverloadResult *lookupIn(CXXRecordDecl *Class,
- unsigned Quals) {
- unsigned TQ = MD->getTypeQualifiers();
- // 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),
- MD->getRefQualifier() == RQ_RValue,
- TQ & Qualifiers::Const,
- TQ & Qualifiers::Volatile);
+ unsigned Quals, bool IsMutable) {
+ return lookupCallFromSpecialMember(S, Class, CSM, Quals,
+ ConstArg && !IsMutable);
}
typedef llvm::PointerUnion<CXXBaseSpecifier*, FieldDecl*> Subobject;
@@ -5017,6 +5069,7 @@
bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
CXXRecordDecl *Class, Subobject Subobj, unsigned Quals) {
FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
+ bool IsMutable = Field && Field->isMutable();
// C++11 [class.ctor]p5:
// -- any direct or virtual base class, or non-static data member with no
@@ -5034,7 +5087,8 @@
// that is deleted or inaccessible
if (!(CSM == Sema::CXXDefaultConstructor &&
Field && Field->hasInClassInitializer()) &&
- shouldDeleteForSubobjectCall(Subobj, lookupIn(Class, Quals), false))
+ shouldDeleteForSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable),
+ false))
return true;
// C++11 [class.ctor]p5, C++11 [class.copy]p11:
@@ -5122,9 +5176,7 @@
bool AllVariantFieldsAreConst = true;
// FIXME: Handle anonymous unions declared within anonymous unions.
- for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(),
- UE = FieldRecord->field_end();
- UI != UE; ++UI) {
+ for (auto *UI : FieldRecord->fields()) {
QualType UnionFieldType = S.Context.getBaseElementType(UI->getType());
if (!UnionFieldType.isConstQualified())
@@ -5132,14 +5184,14 @@
CXXRecordDecl *UnionFieldRecord = UnionFieldType->getAsCXXRecordDecl();
if (UnionFieldRecord &&
- shouldDeleteForClassSubobject(UnionFieldRecord, *UI,
+ shouldDeleteForClassSubobject(UnionFieldRecord, UI,
UnionFieldType.getCVRQualifiers()))
return true;
}
// At least one member in each anonymous union must be non-const
if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst &&
- FieldRecord->field_begin() != FieldRecord->field_end()) {
+ !FieldRecord->field_empty()) {
if (Diagnose)
S.Diag(FieldRecord->getLocation(),
diag::note_deleted_default_ctor_all_const)
@@ -5167,7 +5219,7 @@
// This is a silly definition, because it gives an empty union a deleted
// default constructor. Don't do that.
if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst &&
- (MD->getParent()->field_begin() != MD->getParent()->field_end())) {
+ !MD->getParent()->field_empty()) {
if (Diagnose)
S.Diag(MD->getParent()->getLocation(),
diag::note_deleted_default_ctor_all_const)
@@ -5218,27 +5270,25 @@
// In Microsoft mode, a user-declared move only causes the deletion of the
// corresponding copy operation, not both copy operations.
if (RD->hasUserDeclaredMoveConstructor() &&
- (!getLangOpts().MicrosoftMode || CSM == CXXCopyConstructor)) {
+ (!getLangOpts().MSVCCompat || CSM == CXXCopyConstructor)) {
if (!Diagnose) return true;
// Find any user-declared move constructor.
- for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(),
- E = RD->ctor_end(); I != E; ++I) {
+ for (auto *I : RD->ctors()) {
if (I->isMoveConstructor()) {
- UserDeclaredMove = *I;
+ UserDeclaredMove = I;
break;
}
}
assert(UserDeclaredMove);
} else if (RD->hasUserDeclaredMoveAssignment() &&
- (!getLangOpts().MicrosoftMode || CSM == CXXCopyAssignment)) {
+ (!getLangOpts().MSVCCompat || CSM == CXXCopyAssignment)) {
if (!Diagnose) return true;
// Find any user-declared move assignment operator.
- for (CXXRecordDecl::method_iterator I = RD->method_begin(),
- E = RD->method_end(); I != E; ++I) {
+ for (auto *I : RD->methods()) {
if (I->isMoveAssignmentOperator()) {
- UserDeclaredMove = *I;
+ UserDeclaredMove = I;
break;
}
}
@@ -5274,26 +5324,22 @@
SpecialMemberDeletionInfo SMI(*this, MD, CSM, Diagnose);
- for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(),
- BE = RD->bases_end(); BI != BE; ++BI)
- if (!BI->isVirtual() &&
- SMI.shouldDeleteForBase(BI))
+ for (auto &BI : RD->bases())
+ if (!BI.isVirtual() &&
+ 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))
+ for (auto &BI : RD->vbases())
+ if (SMI.shouldDeleteForBase(&BI))
return true;
}
- for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
- FE = RD->field_end(); FI != FE; ++FI)
+ for (auto *FI : RD->fields())
if (!FI->isInvalidDecl() && !FI->isUnnamedBitfield() &&
- SMI.shouldDeleteForField(*FI))
+ SMI.shouldDeleteForField(FI))
return true;
if (SMI.shouldDeleteForAllConstMembers())
@@ -5312,7 +5358,7 @@
/// member that was most likely to be intended to be trivial, if any.
static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM, unsigned Quals,
- CXXMethodDecl **Selected) {
+ bool ConstRHS, CXXMethodDecl **Selected) {
if (Selected)
*Selected = 0;
@@ -5336,11 +5382,10 @@
CXXConstructorDecl *DefCtor = 0;
if (RD->needsImplicitDefaultConstructor())
S.DeclareImplicitDefaultConstructor(RD);
- for (CXXRecordDecl::ctor_iterator CI = RD->ctor_begin(),
- CE = RD->ctor_end(); CI != CE; ++CI) {
+ for (auto *CI : RD->ctors()) {
if (!CI->isDefaultConstructor())
continue;
- DefCtor = *CI;
+ DefCtor = CI;
if (!DefCtor->isUserProvided())
break;
}
@@ -5403,11 +5448,7 @@
case Sema::CXXMoveAssignment:
NeedOverloadResolution:
Sema::SpecialMemberOverloadResult *SMOR =
- S.LookupSpecialMember(RD, CSM,
- Quals & Qualifiers::Const,
- Quals & Qualifiers::Volatile,
- /*RValueThis*/false, /*ConstThis*/false,
- /*VolatileThis*/false);
+ lookupCallFromSpecialMember(S, RD, CSM, Quals, ConstRHS);
// The standard doesn't describe how to behave if the lookup is ambiguous.
// We treat it as not making the member non-trivial, just like the standard
@@ -5433,10 +5474,9 @@
}
static CXXConstructorDecl *findUserDeclaredCtor(CXXRecordDecl *RD) {
- for (CXXRecordDecl::ctor_iterator CI = RD->ctor_begin(), CE = RD->ctor_end();
- CI != CE; ++CI)
+ for (auto *CI : RD->ctors())
if (!CI->isImplicit())
- return *CI;
+ return CI;
// Look for constructor templates.
typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl> tmpl_iter;
@@ -5462,7 +5502,7 @@
/// Check whether the special member selected for a given type would be trivial.
static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
- QualType SubType,
+ QualType SubType, bool ConstRHS,
Sema::CXXSpecialMember CSM,
TrivialSubobjectKind Kind,
bool Diagnose) {
@@ -5472,10 +5512,13 @@
CXXMethodDecl *Selected;
if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(),
- Diagnose ? &Selected : 0))
+ ConstRHS, Diagnose ? &Selected : 0))
return true;
if (Diagnose) {
+ if (ConstRHS)
+ SubType.addConst();
+
if (!Selected && CSM == Sema::CXXDefaultConstructor) {
S.Diag(SubobjLoc, diag::note_nontrivial_no_def_ctor)
<< Kind << SubType.getUnqualifiedType();
@@ -5511,8 +5554,7 @@
static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM,
bool ConstArg, bool Diagnose) {
- for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
- FE = RD->field_end(); FI != FE; ++FI) {
+ for (const auto *FI : RD->fields()) {
if (FI->isInvalidDecl() || FI->isUnnamedBitfield())
continue;
@@ -5532,7 +5574,7 @@
// brace-or-equal-initializer
if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) {
if (Diagnose)
- S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << *FI;
+ S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << FI;
return false;
}
@@ -5548,10 +5590,9 @@
return false;
}
- if (ConstArg && !FI->isMutable())
- FieldType.addConst();
- if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, CSM,
- TSK_Field, Diagnose))
+ bool ConstRHS = ConstArg && !FI->isMutable();
+ if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, ConstRHS,
+ CSM, TSK_Field, Diagnose))
return false;
}
@@ -5562,10 +5603,9 @@
/// the given kind.
void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) {
QualType Ty = Context.getRecordType(RD);
- if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)
- Ty.addConst();
- checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, CSM,
+ bool ConstArg = (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment);
+ checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, ConstArg, CSM,
TSK_CompleteObject, /*Diagnose*/true);
}
@@ -5648,12 +5688,9 @@
// A [default constructor or destructor] is trivial if
// -- all the direct base classes have trivial [default constructors or
// destructors]
- for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(),
- BE = RD->bases_end(); BI != BE; ++BI)
- if (!checkTrivialSubobjectCall(*this, BI->getLocStart(),
- ConstArg ? BI->getType().withConst()
- : BI->getType(),
- CSM, TSK_BaseClass, Diagnose))
+ for (const auto &BI : RD->bases())
+ if (!checkTrivialSubobjectCall(*this, BI.getLocStart(), BI.getType(),
+ ConstArg, CSM, TSK_BaseClass, Diagnose))
return false;
// C++11 [class.ctor]p5, C++11 [class.dtor]p5:
@@ -5697,8 +5734,7 @@
}
// Must have a virtual method.
- for (CXXRecordDecl::method_iterator MI = RD->method_begin(),
- ME = RD->method_end(); MI != ME; ++MI) {
+ for (const auto *MI : RD->methods()) {
if (MI->isVirtual()) {
SourceLocation MLoc = MI->getLocStart();
Diag(MLoc, diag::note_nontrivial_has_virtual) << RD << 0;
@@ -5992,6 +6028,18 @@
PopDeclContext();
}
+/// This is used to implement the constant expression evaluation part of the
+/// attribute enable_if extension. There is nothing in standard C++ which would
+/// require reentering parameters.
+void Sema::ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param) {
+ if (!Param)
+ return;
+
+ S->AddDecl(Param);
+ if (Param->getDeclName())
+ IdResolver.AddDecl(Param);
+}
+
/// ActOnStartDelayedCXXMethodDeclaration - We have completed
/// parsing a top-level (non-nested) C++ class, and we are now
/// parsing those parts of the given Method declaration that could
@@ -6108,14 +6156,14 @@
// case any of the errors above fired) and with "void" as the
// return type, since constructors don't have return types.
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
- if (Proto->getResultType() == Context.VoidTy && !D.isInvalidType())
+ if (Proto->getReturnType() == Context.VoidTy && !D.isInvalidType())
return R;
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
EPI.TypeQuals = 0;
EPI.RefQualifier = RQ_None;
-
- return Context.getFunctionType(Context.VoidTy, Proto->getArgTypes(), EPI);
+
+ return Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI);
}
/// CheckConstructor - Checks a fully-formed constructor for
@@ -6190,9 +6238,9 @@
static inline bool
FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) {
- return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
- FTI.ArgInfo[0].Param &&
- cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType());
+ return (FTI.NumParams == 1 && !FTI.isVariadic && FTI.Params[0].Ident == 0 &&
+ FTI.Params[0].Param &&
+ cast<ParmVarDecl>(FTI.Params[0].Param)->getType()->isVoidType());
}
/// CheckDestructorDeclarator - Called by ActOnDeclarator to check
@@ -6273,11 +6321,11 @@
}
// Make sure we don't have any parameters.
- if (FTI.NumArgs > 0 && !FTIHasSingleVoidArgument(FTI)) {
+ if (FTI.NumParams > 0 && !FTIHasSingleVoidArgument(FTI)) {
Diag(D.getIdentifierLoc(), diag::err_destructor_with_params);
// Delete the parameters.
- FTI.freeArgs();
+ FTI.freeParams();
D.setInvalidType();
}
@@ -6343,11 +6391,11 @@
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
// Make sure we don't have any parameters.
- if (Proto->getNumArgs() > 0) {
+ if (Proto->getNumParams() > 0) {
Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params);
// Delete the parameters.
- D.getFunctionTypeInfo().freeArgs();
+ D.getFunctionTypeInfo().freeParams();
D.setInvalidType();
} else if (Proto->isVariadic()) {
Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic);
@@ -6356,11 +6404,11 @@
// Diagnose "&operator bool()" and other such nonsense. This
// is actually a gcc extension which we don't support.
- if (Proto->getResultType() != ConvType) {
+ if (Proto->getReturnType() != ConvType) {
Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl)
- << Proto->getResultType();
+ << Proto->getReturnType();
D.setInvalidType();
- ConvType = Proto->getResultType();
+ ConvType = Proto->getReturnType();
}
// C++ [class.conv.fct]p4:
@@ -6464,9 +6512,8 @@
NS->setInline(*IsInline);
// Patch up the lookup table for the containing namespace. This isn't really
// correct, but it's good enough for this particular case.
- for (DeclContext::decl_iterator I = PrevNS->decls_begin(),
- E = PrevNS->decls_end(); I != E; ++I)
- if (NamedDecl *ND = dyn_cast<NamedDecl>(*I))
+ for (auto *I : PrevNS->decls())
+ if (auto *ND = dyn_cast<NamedDecl>(I))
PrevNS->getParent()->makeDeclVisibleInContext(ND);
return;
}
@@ -6477,8 +6524,7 @@
S.Diag(Loc, diag::warn_inline_namespace_reopened_noninline)
<< FixItHint::CreateInsertion(KeywordLoc, "inline ");
else
- S.Diag(Loc, diag::err_inline_namespace_mismatch)
- << IsInline;
+ S.Diag(Loc, diag::err_inline_namespace_mismatch) << *IsInline;
S.Diag(PrevNS->getLocation(), diag::note_previous_definition);
*IsInline = PrevNS->isInline();
@@ -6830,7 +6876,7 @@
// Callback to only accept typo corrections that are namespaces.
class NamespaceValidatorCCC : public CorrectionCandidateCallback {
public:
- bool ValidateCandidate(const TypoCorrection &candidate) LLVM_OVERRIDE {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
if (NamedDecl *ND = candidate.getCorrectionDecl())
return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
return false;
@@ -6886,7 +6932,7 @@
UsingDirectiveDecl *UDir = 0;
NestedNameSpecifier *Qualifier = 0;
if (SS.isSet())
- Qualifier = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ Qualifier = SS.getScopeRep();
// Lookup namespace name.
LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
@@ -7130,13 +7176,7 @@
if (FoundEquivalentDecl)
return false;
- if (Target->isFunctionOrFunctionTemplate()) {
- FunctionDecl *FD;
- if (isa<FunctionTemplateDecl>(Target))
- FD = cast<FunctionTemplateDecl>(Target)->getTemplatedDecl();
- else
- FD = cast<FunctionDecl>(Target);
-
+ if (FunctionDecl *FD = Target->getAsFunction()) {
NamedDecl *OldDecl = 0;
switch (CheckOverload(0, FD, Previous, OldDecl, /*IsForUsingDecl*/ true)) {
case Ovl_Overload:
@@ -7145,7 +7185,7 @@
case Ovl_NonFunction:
Diag(Using->getLocation(), diag::err_using_decl_conflict);
break;
-
+
// We found a decl with the exact signature.
case Ovl_Match:
// If we're in a record, we want to hide the target, so we
@@ -7274,7 +7314,7 @@
: HasTypenameKeyword(HasTypenameKeyword),
IsInstantiation(IsInstantiation), RequireMember(RequireMember) {}
- bool ValidateCandidate(const TypoCorrection &Candidate) LLVM_OVERRIDE {
+ bool ValidateCandidate(const TypoCorrection &Candidate) override {
NamedDecl *ND = Candidate.getCorrectionDecl();
// Keywords are not valid here.
@@ -7353,7 +7393,7 @@
return 0;
// Check for bad qualifiers.
- if (CheckUsingDeclQualifier(UsingLoc, SS, IdentLoc))
+ if (CheckUsingDeclQualifier(UsingLoc, SS, NameInfo, IdentLoc))
return 0;
DeclContext *LookupContext = computeDeclContext(SS);
@@ -7534,8 +7574,7 @@
if (!CurContext->getRedeclContext()->isRecord())
return false;
- NestedNameSpecifier *Qual
- = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+ NestedNameSpecifier *Qual = SS.getScopeRep();
for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
NamedDecl *D = *I;
@@ -7580,6 +7619,7 @@
/// scope. If an error is found, diagnoses it and returns true.
bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
SourceLocation NameLoc) {
DeclContext *NamedContext = computeDeclContext(SS);
@@ -7591,8 +7631,56 @@
// If we weren't able to compute a valid scope, it must be a
// dependent class scope.
if (!NamedContext || NamedContext->isRecord()) {
+ auto *RD = dyn_cast<CXXRecordDecl>(NamedContext);
+ if (RD && RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), RD))
+ RD = 0;
+
Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member)
<< SS.getRange();
+
+ // If we have a complete, non-dependent source type, try to suggest a
+ // way to get the same effect.
+ if (!RD)
+ return true;
+
+ // Find what this using-declaration was referring to.
+ LookupResult R(*this, NameInfo, LookupOrdinaryName);
+ R.setHideTags(false);
+ R.suppressDiagnostics();
+ LookupQualifiedName(R, RD);
+
+ if (R.getAsSingle<TypeDecl>()) {
+ if (getLangOpts().CPlusPlus11) {
+ // Convert 'using X::Y;' to 'using Y = X::Y;'.
+ Diag(SS.getBeginLoc(), diag::note_using_decl_class_member_workaround)
+ << 0 // alias declaration
+ << FixItHint::CreateInsertion(SS.getBeginLoc(),
+ NameInfo.getName().getAsString() +
+ " = ");
+ } else {
+ // Convert 'using X::Y;' to 'typedef X::Y Y;'.
+ SourceLocation InsertLoc =
+ PP.getLocForEndOfToken(NameInfo.getLocEnd());
+ Diag(InsertLoc, diag::note_using_decl_class_member_workaround)
+ << 1 // typedef declaration
+ << FixItHint::CreateReplacement(UsingLoc, "typedef")
+ << FixItHint::CreateInsertion(
+ InsertLoc, " " + NameInfo.getName().getAsString());
+ }
+ } else if (R.getAsSingle<VarDecl>()) {
+ // Don't provide a fixit outside C++11 mode; we don't want to suggest
+ // repeating the type of the static data member here.
+ FixItHint FixIt;
+ if (getLangOpts().CPlusPlus11) {
+ // Convert 'using X::Y;' to 'auto &Y = X::Y;'.
+ FixIt = FixItHint::CreateReplacement(
+ UsingLoc, "auto &" + NameInfo.getName().getAsString() + " = ");
+ }
+
+ Diag(UsingLoc, diag::note_using_decl_class_member_workaround)
+ << 2 // reference declaration
+ << FixIt;
+ }
return true;
}
@@ -7618,7 +7706,7 @@
// but we don't have that level of source info.
Diag(SS.getRange().getBegin(),
diag::err_using_decl_nested_name_specifier_is_not_class)
- << (NestedNameSpecifier*) SS.getScopeRep() << SS.getRange();
+ << SS.getScopeRep() << SS.getRange();
return true;
}
@@ -7643,7 +7731,7 @@
Diag(SS.getRange().getBegin(),
diag::err_using_decl_nested_name_specifier_is_not_base_class)
- << (NestedNameSpecifier*) SS.getScopeRep()
+ << SS.getScopeRep()
<< cast<CXXRecordDecl>(CurContext)
<< SS.getRange();
return true;
@@ -7703,7 +7791,7 @@
Diag(SS.getRange().getBegin(),
diag::err_using_decl_nested_name_specifier_is_not_base_class)
- << (NestedNameSpecifier*) SS.getScopeRep()
+ << SS.getScopeRep()
<< cast<CXXRecordDecl>(CurContext)
<< SS.getRange();
@@ -7923,40 +8011,34 @@
return ExceptSpec;
// Direct base-class constructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
- BEnd = ClassDecl->bases_end();
- B != BEnd; ++B) {
- if (B->isVirtual()) // Handled below.
+ for (const auto &B : ClassDecl->bases()) {
+ if (B.isVirtual()) // Handled below.
continue;
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+ ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
}
}
// Virtual base-class constructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
- BEnd = ClassDecl->vbases_end();
- B != BEnd; ++B) {
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ for (const auto &B : ClassDecl->vbases()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+ ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
}
}
// Field constructors.
- for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
- FEnd = ClassDecl->field_end();
- F != FEnd; ++F) {
+ for (const auto *F : ClassDecl->fields()) {
if (F->hasInClassInitializer()) {
if (Expr *E = F->getInClassInitializer())
ExceptSpec.CalledExpr(E);
@@ -8012,40 +8094,34 @@
ExceptSpec.CalledDecl(CD->getLocStart(), InheritedCD);
// Direct base-class constructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
- BEnd = ClassDecl->bases_end();
- B != BEnd; ++B) {
- if (B->isVirtual()) // Handled below.
+ for (const auto &B : ClassDecl->bases()) {
+ if (B.isVirtual()) // Handled below.
continue;
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
if (BaseClassDecl == InheritedDecl)
continue;
CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
if (Constructor)
- ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+ ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
}
}
// Virtual base-class constructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
- BEnd = ClassDecl->vbases_end();
- B != BEnd; ++B) {
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ for (const auto &B : ClassDecl->vbases()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
if (BaseClassDecl == InheritedDecl)
continue;
CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
if (Constructor)
- ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+ ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
}
}
// Field constructors.
- for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
- FEnd = ClassDecl->field_end();
- F != FEnd; ++F) {
+ for (const auto *F : ClassDecl->fields()) {
if (F->hasInClassInitializer()) {
if (Expr *E = F->getInClassInitializer())
ExceptSpec.CalledExpr(E);
@@ -8256,10 +8332,8 @@
/// Process all constructors for a class.
void visitAll(const CXXRecordDecl *RD, VisitFn Callback) {
- for (CXXRecordDecl::ctor_iterator CtorIt = RD->ctor_begin(),
- CtorE = RD->ctor_end();
- CtorIt != CtorE; ++CtorIt)
- (this->*Callback)(*CtorIt);
+ for (const auto *Ctor : RD->ctors())
+ (this->*Callback)(Ctor);
for (CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl>
I(RD->decls_begin()), E(RD->decls_end());
I != E; ++I) {
@@ -8278,7 +8352,7 @@
void inherit(const CXXConstructorDecl *Ctor) {
const FunctionProtoType *CtorType =
Ctor->getType()->castAs<FunctionProtoType>();
- ArrayRef<QualType> ArgTypes(CtorType->getArgTypes());
+ ArrayRef<QualType> ArgTypes(CtorType->getParamTypes());
FunctionProtoType::ExtProtoInfo EPI = CtorType->getExtProtoInfo();
SourceLocation UsingLoc = getUsingLoc(Ctor->getParent());
@@ -8306,7 +8380,7 @@
do
declareCtor(UsingLoc, Ctor,
SemaRef.Context.getFunctionType(
- Ctor->getResultType(), ArgTypes.slice(0, Params), EPI));
+ Ctor->getReturnType(), ArgTypes.slice(0, Params), EPI));
while (Params > MinParams &&
Ctor->getParamDecl(--Params)->hasDefaultArg());
}
@@ -8420,21 +8494,21 @@
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.ExceptionSpecType = EST_Unevaluated;
EPI.ExceptionSpecDecl = DerivedCtor;
- DerivedCtor->setType(Context.getFunctionType(FPT->getResultType(),
- FPT->getArgTypes(), EPI));
+ DerivedCtor->setType(Context.getFunctionType(FPT->getReturnType(),
+ FPT->getParamTypes(), EPI));
// Build the parameter declarations.
SmallVector<ParmVarDecl *, 16> ParamDecls;
- for (unsigned I = 0, N = FPT->getNumArgs(); I != N; ++I) {
+ for (unsigned I = 0, N = FPT->getNumParams(); I != N; ++I) {
TypeSourceInfo *TInfo =
- Context.getTrivialTypeSourceInfo(FPT->getArgType(I), UsingLoc);
+ Context.getTrivialTypeSourceInfo(FPT->getParamType(I), UsingLoc);
ParmVarDecl *PD = ParmVarDecl::Create(
Context, DerivedCtor, UsingLoc, UsingLoc, /*IdentifierInfo=*/0,
- FPT->getArgType(I), TInfo, SC_None, /*DefaultArg=*/0);
+ FPT->getParamType(I), TInfo, SC_None, /*DefaultArg=*/0);
PD->setScopeInfo(0, I);
PD->setImplicit();
ParamDecls.push_back(PD);
- ProtoLoc.setArg(I, PD);
+ ProtoLoc.setParam(I, PD);
}
// Set up the new constructor.
@@ -8475,11 +8549,9 @@
// Find base classes from which we might inherit constructors.
SmallVector<CXXRecordDecl*, 4> InheritedBases;
- for (CXXRecordDecl::base_class_iterator BaseIt = ClassDecl->bases_begin(),
- BaseE = ClassDecl->bases_end();
- BaseIt != BaseE; ++BaseIt)
- if (BaseIt->getInheritConstructors())
- InheritedBases.push_back(BaseIt->getType()->getAsCXXRecordDecl());
+ for (const auto &BaseIt : ClassDecl->bases())
+ if (BaseIt.getInheritConstructors())
+ InheritedBases.push_back(BaseIt.getType()->getAsCXXRecordDecl());
// Go no further if we're not inheriting any constructors.
if (InheritedBases.empty())
@@ -8532,30 +8604,24 @@
return ExceptSpec;
// Direct base-class destructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
- BEnd = ClassDecl->bases_end();
- B != BEnd; ++B) {
- if (B->isVirtual()) // Handled below.
+ for (const auto &B : ClassDecl->bases()) {
+ if (B.isVirtual()) // Handled below.
continue;
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
- ExceptSpec.CalledDecl(B->getLocStart(),
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>())
+ ExceptSpec.CalledDecl(B.getLocStart(),
LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
}
// Virtual base-class destructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
- BEnd = ClassDecl->vbases_end();
- B != BEnd; ++B) {
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
- ExceptSpec.CalledDecl(B->getLocStart(),
+ for (const auto &B : ClassDecl->vbases()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>())
+ ExceptSpec.CalledDecl(B.getLocStart(),
LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
}
// Field destructors.
- for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
- FEnd = ClassDecl->field_end();
- F != FEnd; ++F) {
+ for (const auto *F : ClassDecl->fields()) {
if (const RecordType *RecordTy
= Context.getBaseElementType(F->getType())->getAs<RecordType>())
ExceptSpec.CalledDecl(F->getLocation(),
@@ -8719,7 +8785,7 @@
QualType VarType;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.BuildDeclRefExpr(Var, VarType, VK_LValue, Loc).take());
}
@@ -8729,7 +8795,7 @@
class ThisBuilder: public ExprBuilder {
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.ActOnCXXThis(Loc).takeAs<Expr>());
}
};
@@ -8741,7 +8807,7 @@
const CXXCastPath &Path;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.ImpCastExprToType(Builder.build(S, Loc), Type,
CK_UncheckedDerivedToBase, Kind,
&Path).take());
@@ -8756,7 +8822,7 @@
const ExprBuilder &Builder;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(
S.CreateBuiltinUnaryOp(Loc, UO_Deref, Builder.build(S, Loc)).take());
}
@@ -8772,7 +8838,7 @@
LookupResult &MemberLookup;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.BuildMemberReferenceExpr(
Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(), 0,
MemberLookup, 0).take());
@@ -8788,7 +8854,7 @@
const ExprBuilder &Builder;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(CastForMoving(S, Builder.build(S, Loc)));
}
@@ -8799,7 +8865,7 @@
const ExprBuilder &Builder;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(
S.DefaultLvalueConversion(Builder.build(S, Loc)).take());
}
@@ -8812,8 +8878,7 @@
const ExprBuilder &Index;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const
- LLVM_OVERRIDE {
+ virtual Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.CreateBuiltinArraySubscriptExpr(
Base.build(S, Loc), Loc, Index.build(S, Loc), Loc).take());
}
@@ -9127,8 +9192,9 @@
return ExceptSpec;
const FunctionProtoType *T = MD->getType()->castAs<FunctionProtoType>();
- assert(T->getNumArgs() == 1 && "not a copy assignment op");
- unsigned ArgQuals = T->getArgType(0).getNonReferenceType().getCVRQualifiers();
+ assert(T->getNumParams() == 1 && "not a copy assignment op");
+ unsigned ArgQuals =
+ T->getParamType(0).getNonReferenceType().getCVRQualifiers();
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have an
@@ -9140,33 +9206,26 @@
// Based on a similar decision made for constness in C++0x, we're erring on
// the side of assuming such calls to be made regardless of whether they
// actually happen.
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- BaseEnd = ClassDecl->bases_end();
- Base != BaseEnd; ++Base) {
- if (Base->isVirtual())
+ for (const auto &Base : ClassDecl->bases()) {
+ if (Base.isVirtual())
continue;
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
ArgQuals, false, 0))
- ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
+ ExceptSpec.CalledDecl(Base.getLocStart(), CopyAssign);
}
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd; ++Base) {
+ for (const auto &Base : ClassDecl->vbases()) {
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
ArgQuals, false, 0))
- ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
+ ExceptSpec.CalledDecl(Base.getLocStart(), CopyAssign);
}
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd;
- ++Field) {
+ for (const auto *Field : ClassDecl->fields()) {
QualType FieldType = Context.getBaseElementType(Field->getType());
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
if (CXXMethodDecl *CopyAssign =
@@ -9263,24 +9322,22 @@
UserDeclaredOperation = RD->getDestructor();
} else if (!isa<CXXConstructorDecl>(CopyOp) &&
RD->hasUserDeclaredCopyConstructor() &&
- !S.getLangOpts().MicrosoftMode) {
+ !S.getLangOpts().MSVCCompat) {
// Find any user-declared copy constructor.
- for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(),
- E = RD->ctor_end(); I != E; ++I) {
+ for (auto *I : RD->ctors()) {
if (I->isCopyConstructor()) {
- UserDeclaredOperation = *I;
+ UserDeclaredOperation = I;
break;
}
}
assert(UserDeclaredOperation);
} else if (isa<CXXConstructorDecl>(CopyOp) &&
RD->hasUserDeclaredCopyAssignment() &&
- !S.getLangOpts().MicrosoftMode) {
+ !S.getLangOpts().MSVCCompat) {
// Find any user-declared move assignment operator.
- for (CXXRecordDecl::method_iterator I = RD->method_begin(),
- E = RD->method_end(); I != E; ++I) {
+ for (auto *I : RD->methods()) {
if (I->isCopyAssignmentOperator()) {
- UserDeclaredOperation = *I;
+ UserDeclaredOperation = I;
break;
}
}
@@ -9359,18 +9416,17 @@
// Assign base classes.
bool Invalid = false;
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); Base != E; ++Base) {
+ for (auto &Base : ClassDecl->bases()) {
// Form the assignment:
// static_cast<Base*>(this)->Base::operator=(static_cast<Base&>(other));
- QualType BaseType = Base->getType().getUnqualifiedType();
+ QualType BaseType = Base.getType().getUnqualifiedType();
if (!BaseType->isRecordType()) {
Invalid = true;
continue;
}
CXXCastPath BasePath;
- BasePath.push_back(Base);
+ BasePath.push_back(&Base);
// Construct the "from" expression, which is an implicit cast to the
// appropriately-qualified base type.
@@ -9401,9 +9457,7 @@
}
// Assign non-static members.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
+ for (auto *Field : ClassDecl->fields()) {
if (Field->isUnnamedBitfield())
continue;
@@ -9450,7 +9504,7 @@
CXXScopeSpec SS; // Intentionally empty
LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
LookupMemberName);
- MemberLookup.addDecl(*Field);
+ MemberLookup.addDecl(Field);
MemberLookup.resolveKind();
MemberBuilder From(OtherRef, OtherRefType, /*IsArrow=*/false, MemberLookup);
@@ -9530,33 +9584,26 @@
// actually happen.
// Note that a move constructor is not implicitly declared when there are
// virtual bases, but it can still be user-declared and explicitly defaulted.
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- BaseEnd = ClassDecl->bases_end();
- Base != BaseEnd; ++Base) {
- if (Base->isVirtual())
+ for (const auto &Base : ClassDecl->bases()) {
+ if (Base.isVirtual())
continue;
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
0, false, 0))
- ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
+ ExceptSpec.CalledDecl(Base.getLocStart(), MoveAssign);
}
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd; ++Base) {
+ for (const auto &Base : ClassDecl->vbases()) {
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
0, false, 0))
- ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
+ ExceptSpec.CalledDecl(Base.getLocStart(), MoveAssign);
}
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd;
- ++Field) {
+ for (const auto *Field : ClassDecl->fields()) {
QualType FieldType = Context.getBaseElementType(Field->getType());
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
if (CXXMethodDecl *MoveAssign =
@@ -9654,10 +9701,8 @@
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);
+ for (auto &BI : Class->bases()) {
+ Worklist.push_back(&BI);
while (!Worklist.empty()) {
CXXBaseSpecifier *BaseSpec = Worklist.pop_back_val();
CXXRecordDecl *Base = BaseSpec->getType()->getAsCXXRecordDecl();
@@ -9689,19 +9734,19 @@
// 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))
+ VBases.insert(std::make_pair(Base->getCanonicalDecl(), &BI))
.first->second;
- if (Existing && Existing != BI) {
+ 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)
+ S.Diag(BI.getLocStart(), diag::note_vbase_moved_here)
<< (Base->getCanonicalDecl() ==
- BI->getType()->getAsCXXRecordDecl()->getCanonicalDecl())
- << Base << BI->getType() << BaseSpec->getSourceRange();
+ BI.getType()->getAsCXXRecordDecl()->getCanonicalDecl())
+ << Base << BI.getType() << BaseSpec->getSourceRange();
// Only diagnose each vbase once.
Existing = 0;
@@ -9714,10 +9759,8 @@
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);
+ for (auto &BI : Base->bases())
+ Worklist.push_back(&BI);
}
}
}
@@ -9779,8 +9822,7 @@
// Assign base classes.
bool Invalid = false;
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- E = ClassDecl->bases_end(); Base != E; ++Base) {
+ for (auto &Base : ClassDecl->bases()) {
// 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
@@ -9791,14 +9833,14 @@
// Form the assignment:
// static_cast<Base*>(this)->Base::operator=(static_cast<Base&&>(other));
- QualType BaseType = Base->getType().getUnqualifiedType();
+ QualType BaseType = Base.getType().getUnqualifiedType();
if (!BaseType->isRecordType()) {
Invalid = true;
continue;
}
CXXCastPath BasePath;
- BasePath.push_back(Base);
+ BasePath.push_back(&Base);
// Construct the "from" expression, which is an implicit cast to the
// appropriately-qualified base type.
@@ -9830,9 +9872,7 @@
}
// Assign non-static members.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
+ for (auto *Field : ClassDecl->fields()) {
if (Field->isUnnamedBitfield())
continue;
@@ -9878,7 +9918,7 @@
// Build references to the field in the object we're copying from and to.
LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
LookupMemberName);
- MemberLookup.addDecl(*Field);
+ MemberLookup.addDecl(Field);
MemberLookup.resolveKind();
MemberBuilder From(MoveOther, OtherRefType,
/*IsArrow=*/false, MemberLookup);
@@ -9951,40 +9991,31 @@
return ExceptSpec;
const FunctionProtoType *T = MD->getType()->castAs<FunctionProtoType>();
- assert(T->getNumArgs() >= 1 && "not a copy ctor");
- unsigned Quals = T->getArgType(0).getNonReferenceType().getCVRQualifiers();
+ assert(T->getNumParams() >= 1 && "not a copy ctor");
+ unsigned Quals = T->getParamType(0).getNonReferenceType().getCVRQualifiers();
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have an
// exception-specification. [...]
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
- BaseEnd = ClassDecl->bases_end();
- Base != BaseEnd;
- ++Base) {
+ for (const auto &Base : ClassDecl->bases()) {
// Virtual bases are handled below.
- if (Base->isVirtual())
+ if (Base.isVirtual())
continue;
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
if (CXXConstructorDecl *CopyConstructor =
LookupCopyingConstructor(BaseClassDecl, Quals))
- ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
+ ExceptSpec.CalledDecl(Base.getLocStart(), CopyConstructor);
}
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
- BaseEnd = ClassDecl->vbases_end();
- Base != BaseEnd;
- ++Base) {
+ for (const auto &Base : ClassDecl->vbases()) {
CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
if (CXXConstructorDecl *CopyConstructor =
LookupCopyingConstructor(BaseClassDecl, Quals))
- ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
+ ExceptSpec.CalledDecl(Base.getLocStart(), CopyConstructor);
}
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd;
- ++Field) {
+ for (const auto *Field : ClassDecl->fields()) {
QualType FieldType = Context.getBaseElementType(Field->getType());
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
if (CXXConstructorDecl *CopyConstructor =
@@ -10117,42 +10148,36 @@
return ExceptSpec;
// Direct base-class constructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
- BEnd = ClassDecl->bases_end();
- B != BEnd; ++B) {
- if (B->isVirtual()) // Handled below.
+ for (const auto &B : ClassDecl->bases()) {
+ if (B.isVirtual()) // Handled below.
continue;
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
CXXConstructorDecl *Constructor =
LookupMovingConstructor(BaseClassDecl, 0);
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+ ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
}
}
// Virtual base-class constructors.
- for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
- BEnd = ClassDecl->vbases_end();
- B != BEnd; ++B) {
- if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ for (const auto &B : ClassDecl->vbases()) {
+ if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
CXXConstructorDecl *Constructor =
LookupMovingConstructor(BaseClassDecl, 0);
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+ ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
}
}
// Field constructors.
- for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
- FEnd = ClassDecl->field_end();
- F != FEnd; ++F) {
+ for (const auto *F : ClassDecl->fields()) {
QualType FieldType = Context.getBaseElementType(F->getType());
if (CXXRecordDecl *FieldRecDecl = FieldType->getAsCXXRecordDecl()) {
CXXConstructorDecl *Constructor =
@@ -10309,7 +10334,7 @@
SynthesizedFunctionScope Scope(*this, Conv);
DiagnosticErrorTrap Trap(Diags);
- // Retreive the static invoker...
+ // Retrieve the static invoker...
CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker();
// ... and get the corresponding specialization for a generic lambda.
if (Lambda->isGenericLambda()) {
@@ -10495,6 +10520,7 @@
<< VD->getType());
DiagnoseUseOfDecl(Destructor, VD->getLocation());
+ if (Destructor->isTrivial()) return;
if (!VD->hasGlobalStorage()) return;
// Emit warning for non-trivial dtor in global scope (a real global,
@@ -10525,11 +10551,11 @@
const FunctionProtoType *Proto
= Constructor->getType()->getAs<FunctionProtoType>();
assert(Proto && "Constructor without a prototype?");
- unsigned NumArgsInProto = Proto->getNumArgs();
-
+ unsigned NumParams = Proto->getNumParams();
+
// If too few arguments are available, we'll fill in the rest with defaults.
- if (NumArgs < NumArgsInProto)
- ConvertedArgs.reserve(NumArgsInProto);
+ if (NumArgs < NumParams)
+ ConvertedArgs.reserve(NumParams);
else
ConvertedArgs.reserve(NumArgs);
@@ -10580,8 +10606,8 @@
CanQualType ExpectedFirstParamType,
unsigned DependentParamTypeDiag,
unsigned InvalidParamTypeDiag) {
- QualType ResultType =
- FnDecl->getType()->getAs<FunctionType>()->getResultType();
+ QualType ResultType =
+ FnDecl->getType()->getAs<FunctionType>()->getReturnType();
// Check that the result type is not dependent.
if (ResultType->isDependentType())
@@ -10706,10 +10732,8 @@
diag::err_operator_overload_static) << FnDecl->getDeclName();
} else {
bool ClassOrEnumParam = false;
- for (FunctionDecl::param_iterator Param = FnDecl->param_begin(),
- ParamEnd = FnDecl->param_end();
- Param != ParamEnd; ++Param) {
- QualType ParamType = (*Param)->getType().getNonReferenceType();
+ for (auto Param : FnDecl->params()) {
+ QualType ParamType = Param->getType().getNonReferenceType();
if (ParamType->isDependentType() || ParamType->isRecordType() ||
ParamType->isEnumeralType()) {
ClassOrEnumParam = true;
@@ -10730,12 +10754,11 @@
// Only the function-call operator allows default arguments
// (C++ [over.call]p1).
if (Op != OO_Call) {
- for (FunctionDecl::param_iterator Param = FnDecl->param_begin();
- Param != FnDecl->param_end(); ++Param) {
- if ((*Param)->hasDefaultArg())
- return Diag((*Param)->getLocation(),
+ for (auto Param : FnDecl->params()) {
+ if (Param->hasDefaultArg())
+ return Diag(Param->getLocation(),
diag::err_operator_overload_default_arg)
- << FnDecl->getDeclName() << (*Param)->getDefaultArgRange();
+ << FnDecl->getDeclName() << Param->getDefaultArgRange();
}
}
@@ -10802,11 +10825,10 @@
// increment operator ++ for objects of that type.
if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) {
ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1);
- bool ParamIsInt = false;
- if (const BuiltinType *BT = LastParam->getType()->getAs<BuiltinType>())
- ParamIsInt = BT->getKind() == BuiltinType::Int;
+ QualType ParamType = LastParam->getType();
- if (!ParamIsInt)
+ if (!ParamType->isSpecificBuiltinType(BuiltinType::Int) &&
+ !ParamType->isDependentType())
return Diag(LastParam->getLocation(),
diag::err_operator_overload_post_incdec_must_be_int)
<< LastParam->getType() << (Op == OO_MinusMinus);
@@ -10939,13 +10961,11 @@
// A parameter-declaration-clause containing a default argument is not
// equivalent to any of the permitted forms.
- for (FunctionDecl::param_iterator Param = FnDecl->param_begin(),
- ParamEnd = FnDecl->param_end();
- Param != ParamEnd; ++Param) {
- if ((*Param)->hasDefaultArg()) {
- Diag((*Param)->getDefaultArgRange().getBegin(),
+ for (auto Param : FnDecl->params()) {
+ if (Param->hasDefaultArg()) {
+ Diag(Param->getDefaultArgRange().getBegin(),
diag::err_literal_operator_default_argument)
- << (*Param)->getDefaultArgRange();
+ << Param->getDefaultArgRange();
break;
}
}
@@ -10965,29 +10985,36 @@
/// ActOnStartLinkageSpecification - Parsed the beginning of a C++
/// linkage specification, including the language and (if present)
-/// the '{'. ExternLoc is the location of the 'extern', LangLoc is
-/// the location of the language string literal, which is provided
-/// by Lang/StrSize. LBraceLoc, if valid, provides the location of
+/// the '{'. ExternLoc is the location of the 'extern', Lang is the
+/// language string literal. LBraceLoc, if valid, provides the location of
/// the '{' brace. Otherwise, this linkage specification does not
/// have any braces.
Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,
- SourceLocation LangLoc,
- StringRef Lang,
+ Expr *LangStr,
SourceLocation LBraceLoc) {
+ StringLiteral *Lit = cast<StringLiteral>(LangStr);
+ if (!Lit->isAscii()) {
+ Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_not_ascii)
+ << LangStr->getSourceRange();
+ return 0;
+ }
+
+ StringRef Lang = Lit->getString();
LinkageSpecDecl::LanguageIDs Language;
- if (Lang == "\"C\"")
+ if (Lang == "C")
Language = LinkageSpecDecl::lang_c;
- else if (Lang == "\"C++\"")
+ else if (Lang == "C++")
Language = LinkageSpecDecl::lang_cxx;
else {
- Diag(LangLoc, diag::err_bad_language);
+ Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_unknown)
+ << LangStr->getSourceRange();
return 0;
}
// FIXME: Add all the various semantics of linkage specifications
- LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext,
- ExternLoc, LangLoc, Language,
+ LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, ExternLoc,
+ LangStr->getExprLoc(), Language,
LBraceLoc.isValid());
CurContext->addDecl(D);
PushDeclContext(S, D);
@@ -11001,13 +11028,11 @@
Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
Decl *LinkageSpec,
SourceLocation RBraceLoc) {
- if (LinkageSpec) {
- if (RBraceLoc.isValid()) {
- LinkageSpecDecl* LSDecl = cast<LinkageSpecDecl>(LinkageSpec);
- LSDecl->setRBraceLoc(RBraceLoc);
- }
- PopDeclContext();
+ if (RBraceLoc.isValid()) {
+ LinkageSpecDecl* LSDecl = cast<LinkageSpecDecl>(LinkageSpec);
+ LSDecl->setRBraceLoc(RBraceLoc);
}
+ PopDeclContext();
return LinkageSpec;
}
@@ -11374,14 +11399,15 @@
bool Owned = false;
bool IsDependent = false;
return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc,
- Attr, AS_public,
+ Attr, AS_public,
/*ModulePrivateLoc=*/SourceLocation(),
- MultiTemplateParamsArg(), Owned, IsDependent,
+ MultiTemplateParamsArg(), Owned, IsDependent,
/*ScopedEnumKWLoc=*/SourceLocation(),
/*ScopedEnumUsesClassTag=*/false,
- /*UnderlyingType=*/TypeResult());
+ /*UnderlyingType=*/TypeResult(),
+ /*IsTypeSpecifier=*/false);
}
-
+
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
ElaboratedTypeKeyword Keyword
= TypeWithKeyword::getKeywordForTagTypeKind(Kind);
@@ -11841,10 +11867,13 @@
if (const FunctionDecl *Prev = Fn->getPreviousDecl()) {
// Don't consider the implicit declaration we generate for explicit
// specializations. FIXME: Do not generate these implicit declarations.
- if ((Prev->getTemplateSpecializationKind() != TSK_ExplicitSpecialization
- || Prev->getPreviousDecl()) && !Prev->isDefined()) {
+ if ((Prev->getTemplateSpecializationKind() != TSK_ExplicitSpecialization ||
+ Prev->getPreviousDecl()) &&
+ !Prev->isDefined()) {
Diag(DelLoc, diag::err_deleted_decl_not_first);
- Diag(Prev->getLocation(), diag::note_previous_declaration);
+ Diag(Prev->getLocation().isInvalid() ? DelLoc : Prev->getLocation(),
+ Prev->isImplicit() ? diag::note_previous_implicit_declaration
+ : diag::note_previous_declaration);
}
// If the declaration wasn't the first, we delete the function anyway for
// recovery.
@@ -11871,6 +11900,11 @@
}
}
+ // C++11 [basic.start.main]p3:
+ // A program that defines main as deleted [...] is ill-formed.
+ if (Fn->isMain())
+ Diag(DelLoc, diag::err_deleted_main);
+
Fn->setDeletedAsWritten();
}
@@ -11977,6 +12011,13 @@
if (NewCC == OldCC)
return false;
+ // If the calling conventions mismatch because the new function is static,
+ // suppress the calling convention mismatch error; the error about static
+ // function override (err_static_overrides_virtual from
+ // Sema::CheckFunctionDeclaration) is more clear.
+ if (New->getStorageClass() == SC_Static)
+ return false;
+
Diag(New->getLocation(),
diag::err_conflicting_overriding_cc_attributes)
<< New->getDeclName() << New->getType() << Old->getType();
@@ -11986,8 +12027,8 @@
bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
const CXXMethodDecl *Old) {
- QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType();
- QualType OldTy = Old->getType()->getAs<FunctionType>()->getResultType();
+ QualType NewTy = New->getType()->getAs<FunctionType>()->getReturnType();
+ QualType OldTy = Old->getType()->getAs<FunctionType>()->getReturnType();
if (Context.hasSameType(NewTy, OldTy) ||
NewTy->isDependentType() || OldTy->isDependentType())
@@ -12120,11 +12161,13 @@
// If there is no declaration, there was an error parsing it.
if (D == 0 || D->isInvalidDecl()) return;
- // We should only get called for declarations with scope specifiers, like:
- // int foo::bar;
- assert(D->isOutOfLine());
- EnterDeclaratorContext(S, D->getDeclContext());
-
+ // We will always have a nested name specifier here, but this declaration
+ // might not be out of line if the specifier names the current namespace:
+ // extern int n;
+ // int ::n = 0;
+ if (D->isOutOfLine())
+ EnterDeclaratorContext(S, D->getDeclContext());
+
// If we are parsing the initializer for a static data member, push a
// new expression evaluation context that is associated with this static
// data member.
@@ -12139,10 +12182,10 @@
if (D == 0 || D->isInvalidDecl()) return;
if (isStaticDataMember(D))
- PopExpressionEvaluationContext();
+ PopExpressionEvaluationContext();
- assert(D->isOutOfLine());
- ExitDeclaratorContext(S);
+ if (D->isOutOfLine())
+ ExitDeclaratorContext(S);
}
/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
@@ -12216,6 +12259,18 @@
// Otherwise, we can early exit.
return;
}
+ } else {
+ // The Microsoft ABI requires that we perform the destructor body
+ // checks (i.e. operator delete() lookup) when the vtable is marked used, as
+ // the deleting destructor is emitted with the vtable, not with the
+ // destructor definition as in the Itanium ABI.
+ // If it has a definition, we do the check at that point instead.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ Class->hasUserDeclaredDestructor() &&
+ !Class->getDestructor()->isDefined() &&
+ !Class->getDestructor()->isDeleted()) {
+ CheckDestructor(Class->getDestructor());
+ }
}
// Local classes need to have their virtual members marked
@@ -12267,11 +12322,9 @@
bool IsExplicitInstantiationDeclaration
= Class->getTemplateSpecializationKind()
== TSK_ExplicitInstantiationDeclaration;
- for (TagDecl::redecl_iterator R = Class->redecls_begin(),
- REnd = Class->redecls_end();
- R != REnd; ++R) {
+ for (auto R : Class->redecls()) {
TemplateSpecializationKind TSK
- = cast<CXXRecordDecl>(*R)->getTemplateSpecializationKind();
+ = cast<CXXRecordDecl>(R)->getTemplateSpecializationKind();
if (TSK == TSK_ExplicitInstantiationDeclaration)
IsExplicitInstantiationDeclaration = true;
else if (TSK == TSK_ExplicitInstantiationDefinition) {
@@ -12320,10 +12373,9 @@
void Sema::MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
const CXXRecordDecl *RD) {
- for (CXXRecordDecl::method_iterator I = RD->method_begin(),
- E = RD->method_end(); I != E; ++I)
- if ((*I)->isVirtual() && !(*I)->isPure())
- ResolveExceptionSpec(Loc, (*I)->getType()->castAs<FunctionProtoType>());
+ for (const auto *I : RD->methods())
+ if (I->isVirtual() && !I->isPure())
+ ResolveExceptionSpec(Loc, I->getType()->castAs<FunctionProtoType>());
}
void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
@@ -12351,10 +12403,9 @@
if (RD->getNumVBases() == 0)
return;
- for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
- e = RD->bases_end(); i != e; ++i) {
+ for (const auto &I : RD->bases()) {
const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
if (Base->getNumVBases() == 0)
continue;
MarkVirtualMembersReferenced(Loc, Base);
@@ -12534,7 +12585,7 @@
// If the return type came after the cv-qualifier-seq, check it now.
if (Proto->hasTrailingReturn() &&
- !Finder.TraverseTypeLoc(ProtoTL.getResultLoc()))
+ !Finder.TraverseTypeLoc(ProtoTL.getReturnLoc()))
return true;
// Check the exception specification.
@@ -12571,10 +12622,8 @@
return true;
case EST_Dynamic:
- for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
- EEnd = Proto->exception_end();
- E != EEnd; ++E) {
- if (!Finder.TraverseType(*E))
+ for (const auto &E : Proto->exceptions()) {
+ if (!Finder.TraverseType(E))
return true;
}
break;
@@ -12587,45 +12636,36 @@
FindCXXThisExpr Finder(*this);
// Check attributes.
- for (Decl::attr_iterator A = Method->attr_begin(), AEnd = Method->attr_end();
- A != AEnd; ++A) {
+ for (const auto *A : Method->attrs()) {
// FIXME: This should be emitted by tblgen.
Expr *Arg = 0;
ArrayRef<Expr *> Args;
- if (GuardedByAttr *G = dyn_cast<GuardedByAttr>(*A))
+ if (const auto *G = dyn_cast<GuardedByAttr>(A))
Arg = G->getArg();
- else if (PtGuardedByAttr *G = dyn_cast<PtGuardedByAttr>(*A))
+ else if (const auto *G = dyn_cast<PtGuardedByAttr>(A))
Arg = G->getArg();
- else if (AcquiredAfterAttr *AA = dyn_cast<AcquiredAfterAttr>(*A))
+ else if (const auto *AA = dyn_cast<AcquiredAfterAttr>(A))
Args = ArrayRef<Expr *>(AA->args_begin(), AA->args_size());
- else if (AcquiredBeforeAttr *AB = dyn_cast<AcquiredBeforeAttr>(*A))
+ else if (const auto *AB = dyn_cast<AcquiredBeforeAttr>(A))
Args = ArrayRef<Expr *>(AB->args_begin(), AB->args_size());
- else if (ExclusiveLockFunctionAttr *ELF
- = dyn_cast<ExclusiveLockFunctionAttr>(*A))
- Args = ArrayRef<Expr *>(ELF->args_begin(), ELF->args_size());
- else if (SharedLockFunctionAttr *SLF
- = dyn_cast<SharedLockFunctionAttr>(*A))
- Args = ArrayRef<Expr *>(SLF->args_begin(), SLF->args_size());
- else if (ExclusiveTrylockFunctionAttr *ETLF
- = dyn_cast<ExclusiveTrylockFunctionAttr>(*A)) {
+ else if (const auto *ETLF = dyn_cast<ExclusiveTrylockFunctionAttr>(A)) {
Arg = ETLF->getSuccessValue();
Args = ArrayRef<Expr *>(ETLF->args_begin(), ETLF->args_size());
- } else if (SharedTrylockFunctionAttr *STLF
- = dyn_cast<SharedTrylockFunctionAttr>(*A)) {
+ } else if (const auto *STLF = dyn_cast<SharedTrylockFunctionAttr>(A)) {
Arg = STLF->getSuccessValue();
Args = ArrayRef<Expr *>(STLF->args_begin(), STLF->args_size());
- } else if (UnlockFunctionAttr *UF = dyn_cast<UnlockFunctionAttr>(*A))
- Args = ArrayRef<Expr *>(UF->args_begin(), UF->args_size());
- else if (LockReturnedAttr *LR = dyn_cast<LockReturnedAttr>(*A))
+ } else if (const auto *LR = dyn_cast<LockReturnedAttr>(A))
Arg = LR->getArg();
- else if (LocksExcludedAttr *LE = dyn_cast<LocksExcludedAttr>(*A))
+ else if (const auto *LE = dyn_cast<LocksExcludedAttr>(A))
Args = ArrayRef<Expr *>(LE->args_begin(), LE->args_size());
- else if (ExclusiveLocksRequiredAttr *ELR
- = dyn_cast<ExclusiveLocksRequiredAttr>(*A))
- Args = ArrayRef<Expr *>(ELR->args_begin(), ELR->args_size());
- else if (SharedLocksRequiredAttr *SLR
- = dyn_cast<SharedLocksRequiredAttr>(*A))
- Args = ArrayRef<Expr *>(SLR->args_begin(), SLR->args_size());
+ else if (const auto *RC = dyn_cast<RequiresCapabilityAttr>(A))
+ Args = ArrayRef<Expr *>(RC->args_begin(), RC->args_size());
+ else if (const auto *AC = dyn_cast<AcquireCapabilityAttr>(A))
+ Args = ArrayRef<Expr *>(AC->args_begin(), AC->args_size());
+ else if (const auto *AC = dyn_cast<TryAcquireCapabilityAttr>(A))
+ Args = ArrayRef<Expr *>(AC->args_begin(), AC->args_size());
+ else if (const auto *RC = dyn_cast<ReleaseCapabilityAttr>(A))
+ Args = ArrayRef<Expr *>(RC->args_begin(), RC->args_size());
if (Arg && !Finder.TraverseStmt(Arg))
return true;
@@ -12801,11 +12841,9 @@
PrevDecl = 0;
SourceLocation TSSL = D.getLocStart();
- MSPropertyDecl *NewPD;
const AttributeList::PropertyData &Data = MSPropertyAttr->getPropertyData();
- NewPD = new (Context) MSPropertyDecl(Record, Loc,
- II, T, TInfo, TSSL,
- Data.GetterId, Data.SetterId);
+ MSPropertyDecl *NewPD = MSPropertyDecl::Create(
+ Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId);
ProcessDeclAttributes(TUScope, NewPD, D);
NewPD->setAccess(AS);
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index f44fb32..d59dd8b 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/DataRecursiveASTVisitor.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
@@ -48,8 +49,8 @@
// We ignore protocols here. Should we? What about Class?
- const ObjCObjectType *result = method->getResultType()
- ->castAs<ObjCObjectPointerType>()->getObjectType();
+ const ObjCObjectType *result =
+ method->getReturnType()->castAs<ObjCObjectPointerType>()->getObjectType();
if (result->isObjCId()) {
return false;
@@ -97,8 +98,9 @@
// If we're in a system header, and this is not a call, just make
// the method unusable.
if (receiverTypeIfCall.isNull() && getSourceManager().isInSystemHeader(loc)) {
- method->addAttr(new (Context) UnavailableAttr(loc, Context,
- "init method returns a type unrelated to its receiver type"));
+ method->addAttr(UnavailableAttr::CreateImplicit(Context,
+ "init method returns a type unrelated to its receiver type",
+ loc));
return true;
}
@@ -116,10 +118,10 @@
// implies a related result type, and the original (overridden) method has
// a suitable return type, but the new (overriding) method does not have
// a suitable return type.
- QualType ResultType = NewMethod->getResultType();
+ QualType ResultType = NewMethod->getReturnType();
SourceRange ResultTypeRange;
- if (const TypeSourceInfo *ResultTypeInfo
- = NewMethod->getResultTypeSourceInfo())
+ if (const TypeSourceInfo *ResultTypeInfo =
+ NewMethod->getReturnTypeSourceInfo())
ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange();
// Figure out which class this method is part of, if any.
@@ -207,19 +209,19 @@
return false;
case OMF_dealloc:
- if (!Context.hasSameType(method->getResultType(), Context.VoidTy)) {
+ if (!Context.hasSameType(method->getReturnType(), Context.VoidTy)) {
SourceRange ResultTypeRange;
- if (const TypeSourceInfo *ResultTypeInfo
- = method->getResultTypeSourceInfo())
+ if (const TypeSourceInfo *ResultTypeInfo =
+ method->getReturnTypeSourceInfo())
ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange();
if (ResultTypeRange.isInvalid())
- Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
- << method->getResultType()
- << FixItHint::CreateInsertion(method->getSelectorLoc(0), "(void)");
+ Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
+ << method->getReturnType()
+ << FixItHint::CreateInsertion(method->getSelectorLoc(0), "(void)");
else
- Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
- << method->getResultType()
- << FixItHint::CreateReplacement(ResultTypeRange, "void");
+ Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
+ << method->getReturnType()
+ << FixItHint::CreateReplacement(ResultTypeRange, "void");
return true;
}
return false;
@@ -229,8 +231,7 @@
if (checkInitMethod(method, QualType()))
return true;
- method->addAttr(new (Context) NSConsumesSelfAttr(SourceLocation(),
- Context));
+ method->addAttr(NSConsumesSelfAttr::CreateImplicit(Context));
// Don't add a second copy of this attribute, but otherwise don't
// let it be suppressed.
@@ -249,8 +250,7 @@
break;
}
- method->addAttr(new (Context) NSReturnsRetainedAttr(SourceLocation(),
- Context));
+ method->addAttr(NSReturnsRetainedAttr::CreateImplicit(Context));
return false;
}
@@ -329,17 +329,15 @@
/*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);
+ for (auto *Param : MDecl->params()) {
if (!Param->isInvalidDecl() &&
getLangOpts().ObjCAutoRefCount &&
!HasExplicitOwnershipAttr(*this, Param))
Diag(Param->getLocation(), diag::warn_arc_strong_pointer_objc_pointer) <<
Param->getType();
- if ((*PI)->getIdentifier())
- PushOnScopeChains(*PI, FnBodyScope);
+ if (Param->getIdentifier())
+ PushOnScopeChains(Param, FnBodyScope);
}
// In ARC, disallow definition of retain/release/autorelease/retainCount
@@ -381,8 +379,13 @@
ObjCImplDecl *ImplDeclOfMethodDecl = 0;
if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ContDeclOfMethodDecl))
ImplDeclOfMethodDecl = OID->getImplementation();
- else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContDeclOfMethodDecl))
- ImplDeclOfMethodDecl = CD->getImplementation();
+ else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContDeclOfMethodDecl)) {
+ if (CD->IsClassExtension()) {
+ if (ObjCInterfaceDecl *OID = CD->getClassInterface())
+ ImplDeclOfMethodDecl = OID->getImplementation();
+ } else
+ ImplDeclOfMethodDecl = CD->getImplementation();
+ }
// No need to issue deprecated warning if deprecated mehod in class/category
// is being implemented in its own implementation (no overriding is involved).
if (!ImplDeclOfMethodDecl || ImplDeclOfMethodDecl != ImplDeclOfMethodDef)
@@ -391,6 +394,17 @@
MDecl->getLocation(), 0);
}
+ if (MDecl->getMethodFamily() == OMF_init) {
+ if (MDecl->isDesignatedInitializerForTheInterface()) {
+ getCurFunction()->ObjCIsDesignatedInit = true;
+ getCurFunction()->ObjCWarnForNoDesignatedInitChain =
+ IC->getSuperClass() != 0;
+ } else if (IC->hasDesignatedInitializers()) {
+ getCurFunction()->ObjCIsSecondaryInit = true;
+ getCurFunction()->ObjCWarnForNoInitDelegation = true;
+ }
+ }
+
// If this is "dealloc" or "finalize", set some bit here.
// Then in ActOnSuperMessage() (SemaExprObjC), set it back to false.
// Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set.
@@ -428,7 +442,7 @@
explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl)
: CurrentIDecl(IDecl) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
ObjCInterfaceDecl *ID = candidate.getCorrectionDeclAs<ObjCInterfaceDecl>();
return ID && !declaresSameEntity(ID, CurrentIDecl);
}
@@ -607,9 +621,8 @@
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);
+ for (auto *I : OPT->quals())
+ ProtocolRefs.push_back(I);
}
}
@@ -751,6 +764,21 @@
return ActOnObjCContainerStartDefinition(PDecl);
}
+static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl,
+ ObjCProtocolDecl *&UndefinedProtocol) {
+ if (!PDecl->hasDefinition() || PDecl->getDefinition()->isHidden()) {
+ UndefinedProtocol = PDecl;
+ return true;
+ }
+
+ for (auto *PI : PDecl->protocols())
+ if (NestedProtocolHasNoDefinition(PI, UndefinedProtocol)) {
+ UndefinedProtocol = PI;
+ return true;
+ }
+ return false;
+}
+
/// FindProtocolDeclaration - This routine looks up protocols and
/// issues an error if they are not declared. It returns list of
/// protocol declarations in its 'Protocols' argument.
@@ -786,10 +814,15 @@
// If this is a forward declaration and we are supposed to warn in this
// case, do it.
// FIXME: Recover nicely in the hidden case.
+ ObjCProtocolDecl *UndefinedProtocol;
+
if (WarnOnDeclarations &&
- (!PDecl->hasDefinition() || PDecl->getDefinition()->isHidden()))
+ NestedProtocolHasNoDefinition(PDecl, UndefinedProtocol)) {
Diag(ProtocolId[i].second, diag::warn_undef_protocolref)
<< ProtocolId[i].first;
+ Diag(UndefinedProtocol->getLocation(), diag::note_protocol_decl_undefined)
+ << UndefinedProtocol;
+ }
Protocols.push_back(PDecl);
}
}
@@ -803,19 +836,16 @@
return; // Possibly due to previous error
llvm::DenseMap<Selector, const ObjCMethodDecl*> MethodMap;
- for (ObjCInterfaceDecl::method_iterator i = ID->meth_begin(),
- e = ID->meth_end(); i != e; ++i) {
- ObjCMethodDecl *MD = *i;
+ for (auto *MD : ID->methods())
MethodMap[MD->getSelector()] = MD;
- }
if (MethodMap.empty())
return;
- for (ObjCCategoryDecl::method_iterator i = CAT->meth_begin(),
- e = CAT->meth_end(); i != e; ++i) {
- ObjCMethodDecl *Method = *i;
+ for (const auto *Method : CAT->methods()) {
const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()];
- if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) {
+ if (PrevMethod &&
+ (PrevMethod->isInstanceMethod() == Method->isInstanceMethod()) &&
+ !MatchTwoMethodDeclarations(Method, PrevMethod)) {
Diag(Method->getLocation(), diag::err_duplicate_method_decl)
<< Method->getDeclName();
Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
@@ -1154,11 +1184,7 @@
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;
+ for (const auto *CDecl : IDecl->visible_extensions()) {
if (const ObjCIvarDecl *ClsExtIvar =
CDecl->getIvarDecl(ImplIvar->getIdentifier())) {
Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);
@@ -1209,13 +1235,16 @@
}
if (numIvars > 0)
- Diag(ivars[j]->getLocation(), diag::err_inconsistant_ivar_count);
+ Diag(ivars[j]->getLocation(), diag::err_inconsistent_ivar_count);
else if (IVI != IVE)
- Diag(IVI->getLocation(), diag::err_inconsistant_ivar_count);
+ Diag(IVI->getLocation(), diag::err_inconsistent_ivar_count);
}
-void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
- bool &IncompleteImpl, unsigned DiagID) {
+static void WarnUndefinedMethod(Sema &S, SourceLocation ImpLoc,
+ ObjCMethodDecl *method,
+ bool &IncompleteImpl,
+ unsigned DiagID,
+ NamedDecl *NeededFor = 0) {
// No point warning no definition of method which is 'unavailable'.
switch (method->getAvailability()) {
case AR_Available:
@@ -1233,13 +1262,17 @@
// warning, but some users strongly voiced that they would prefer
// separate warnings. We will give that approach a try, as that
// matches what we do with protocols.
-
- Diag(ImpLoc, DiagID) << method->getDeclName();
+ {
+ const Sema::SemaDiagnosticBuilder &B = S.Diag(ImpLoc, DiagID);
+ B << method;
+ if (NeededFor)
+ B << NeededFor;
+ }
// Issue a note to the original declaration.
SourceLocation MethodLoc = method->getLocStart();
if (MethodLoc.isValid())
- Diag(MethodLoc, diag::note_method_declared_at) << method;
+ S.Diag(MethodLoc, diag::note_method_declared_at) << method;
}
/// Determines if type B can be substituted for type A. Returns true if we can
@@ -1323,21 +1356,21 @@
(MethodDecl->getObjCDeclQualifier() !=
MethodImpl->getObjCDeclQualifier())) {
if (Warn) {
- S.Diag(MethodImpl->getLocation(),
- (IsOverridingMode ?
- diag::warn_conflicting_overriding_ret_type_modifiers
- : diag::warn_conflicting_ret_type_modifiers))
+ S.Diag(MethodImpl->getLocation(),
+ (IsOverridingMode
+ ? diag::warn_conflicting_overriding_ret_type_modifiers
+ : diag::warn_conflicting_ret_type_modifiers))
<< MethodImpl->getDeclName()
- << getTypeRange(MethodImpl->getResultTypeSourceInfo());
- S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)
- << getTypeRange(MethodDecl->getResultTypeSourceInfo());
+ << getTypeRange(MethodImpl->getReturnTypeSourceInfo());
+ S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)
+ << getTypeRange(MethodDecl->getReturnTypeSourceInfo());
}
else
return false;
}
-
- if (S.Context.hasSameUnqualifiedType(MethodImpl->getResultType(),
- MethodDecl->getResultType()))
+
+ if (S.Context.hasSameUnqualifiedType(MethodImpl->getReturnType(),
+ MethodDecl->getReturnType()))
return true;
if (!Warn)
return false;
@@ -1349,9 +1382,9 @@
// Mismatches between ObjC pointers go into a different warning
// category, and sometimes they're even completely whitelisted.
if (const ObjCObjectPointerType *ImplPtrTy =
- MethodImpl->getResultType()->getAs<ObjCObjectPointerType>()) {
+ MethodImpl->getReturnType()->getAs<ObjCObjectPointerType>()) {
if (const ObjCObjectPointerType *IfacePtrTy =
- MethodDecl->getResultType()->getAs<ObjCObjectPointerType>()) {
+ MethodDecl->getReturnType()->getAs<ObjCObjectPointerType>()) {
// Allow non-matching return types as long as they don't violate
// the principle of substitutability. Specifically, we permit
// return types that are subclasses of the declared return type,
@@ -1366,14 +1399,13 @@
}
S.Diag(MethodImpl->getLocation(), DiagID)
- << MethodImpl->getDeclName()
- << MethodDecl->getResultType()
- << MethodImpl->getResultType()
- << getTypeRange(MethodImpl->getResultTypeSourceInfo());
- S.Diag(MethodDecl->getLocation(),
- IsOverridingMode ? diag::note_previous_declaration
- : diag::note_previous_definition)
- << getTypeRange(MethodDecl->getResultTypeSourceInfo());
+ << MethodImpl->getDeclName() << MethodDecl->getReturnType()
+ << MethodImpl->getReturnType()
+ << getTypeRange(MethodImpl->getReturnTypeSourceInfo());
+ S.Diag(MethodDecl->getLocation(), IsOverridingMode
+ ? diag::note_previous_declaration
+ : diag::note_previous_definition)
+ << getTypeRange(MethodDecl->getReturnTypeSourceInfo());
return false;
}
@@ -1505,7 +1537,7 @@
// The only reason these methods don't fall within their families is
// due to unusual result types.
- if (unmatched->getResultType()->isObjCObjectPointerType()) {
+ if (unmatched->getReturnType()->isObjCObjectPointerType()) {
reasonSelector = R_UnrelatedReturn;
} else {
reasonSelector = R_NonObjectReturn;
@@ -1615,14 +1647,41 @@
/// we used an immutable set to keep the table then it wouldn't add significant
/// memory cost and it would be handy for lookups.
+typedef llvm::DenseSet<IdentifierInfo*> ProtocolNameSet;
+typedef std::unique_ptr<ProtocolNameSet> LazyProtocolNameSet;
+
+static void findProtocolsWithExplicitImpls(const ObjCProtocolDecl *PDecl,
+ ProtocolNameSet &PNS) {
+ if (PDecl->hasAttr<ObjCExplicitProtocolImplAttr>())
+ PNS.insert(PDecl->getIdentifier());
+ for (const auto *PI : PDecl->protocols())
+ findProtocolsWithExplicitImpls(PI, PNS);
+}
+
+/// Recursively populates a set with all conformed protocols in a class
+/// hierarchy that have the 'objc_protocol_requires_explicit_implementation'
+/// attribute.
+static void findProtocolsWithExplicitImpls(const ObjCInterfaceDecl *Super,
+ ProtocolNameSet &PNS) {
+ if (!Super)
+ return;
+
+ for (const auto *I : Super->all_referenced_protocols())
+ findProtocolsWithExplicitImpls(I, PNS);
+
+ findProtocolsWithExplicitImpls(Super->getSuperClass(), PNS);
+}
+
/// CheckProtocolMethodDefs - This routine checks unimplemented methods
/// Declared in protocol, and those referenced by it.
-void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
- ObjCProtocolDecl *PDecl,
- bool& IncompleteImpl,
- const SelectorSet &InsMap,
- const SelectorSet &ClsMap,
- ObjCContainerDecl *CDecl) {
+static void CheckProtocolMethodDefs(Sema &S,
+ SourceLocation ImpLoc,
+ ObjCProtocolDecl *PDecl,
+ bool& IncompleteImpl,
+ const Sema::SelectorSet &InsMap,
+ const Sema::SelectorSet &ClsMap,
+ ObjCContainerDecl *CDecl,
+ LazyProtocolNameSet &ProtocolsExplictImpl) {
ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
ObjCInterfaceDecl *IDecl = C ? C->getClassInterface()
: dyn_cast<ObjCInterfaceDecl>(CDecl);
@@ -1630,7 +1689,33 @@
ObjCInterfaceDecl *Super = IDecl->getSuperClass();
ObjCInterfaceDecl *NSIDecl = 0;
- if (getLangOpts().ObjCRuntime.isNeXTFamily()) {
+
+ // If this protocol is marked 'objc_protocol_requires_explicit_implementation'
+ // then we should check if any class in the super class hierarchy also
+ // conforms to this protocol, either directly or via protocol inheritance.
+ // If so, we can skip checking this protocol completely because we
+ // know that a parent class already satisfies this protocol.
+ //
+ // Note: we could generalize this logic for all protocols, and merely
+ // add the limit on looking at the super class chain for just
+ // specially marked protocols. This may be a good optimization. This
+ // change is restricted to 'objc_protocol_requires_explicit_implementation'
+ // protocols for now for controlled evaluation.
+ if (PDecl->hasAttr<ObjCExplicitProtocolImplAttr>()) {
+ if (!ProtocolsExplictImpl) {
+ ProtocolsExplictImpl.reset(new ProtocolNameSet);
+ findProtocolsWithExplicitImpls(Super, *ProtocolsExplictImpl);
+ }
+ if (ProtocolsExplictImpl->find(PDecl->getIdentifier()) !=
+ ProtocolsExplictImpl->end())
+ return;
+
+ // If no super class conforms to the protocol, we should not search
+ // for methods in the super class to implicitly satisfy the protocol.
+ Super = NULL;
+ }
+
+ if (S.getLangOpts().ObjCRuntime.isNeXTFamily()) {
// check to see if class implements forwardInvocation method and objects
// of this class are derived from 'NSProxy' so that to forward requests
// from one object to another.
@@ -1638,12 +1723,12 @@
// implemented in the class, we should not issue "Method definition not
// found" warnings.
// FIXME: Use a general GetUnarySelector method for this.
- IdentifierInfo* II = &Context.Idents.get("forwardInvocation");
- Selector fISelector = Context.Selectors.getSelector(1, &II);
+ IdentifierInfo* II = &S.Context.Idents.get("forwardInvocation");
+ Selector fISelector = S.Context.Selectors.getSelector(1, &II);
if (InsMap.count(fISelector))
// Is IDecl derived from 'NSProxy'? If so, no instance methods
// need be implemented in the implementation.
- NSIDecl = IDecl->lookupInheritedClass(&Context.Idents.get("NSProxy"));
+ NSIDecl = IDecl->lookupInheritedClass(&S.Context.Idents.get("NSProxy"));
}
// If this is a forward protocol declaration, get its definition.
@@ -1658,13 +1743,15 @@
// check unimplemented instance methods.
if (!NSIDecl)
- for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
- E = PDecl->instmeth_end(); I != E; ++I) {
- ObjCMethodDecl *method = *I;
+ for (auto *method : PDecl->instance_methods()) {
if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
!method->isPropertyAccessor() &&
!InsMap.count(method->getSelector()) &&
- (!Super || !Super->lookupInstanceMethod(method->getSelector()))) {
+ (!Super || !Super->lookupMethod(method->getSelector(),
+ true /* instance */,
+ false /* shallowCategory */,
+ true /* followsSuper */,
+ NULL /* category */))) {
// If a method is not implemented in the category implementation but
// has been declared in its primary class, superclass,
// or in one of their protocols, no need to issue the warning.
@@ -1675,44 +1762,47 @@
// have been synthesized due to a property declared in the class which
// uses the protocol.
if (ObjCMethodDecl *MethodInClass =
- IDecl->lookupInstanceMethod(method->getSelector(),
- true /*shallowCategoryLookup*/))
+ IDecl->lookupMethod(method->getSelector(),
+ true /* instance */,
+ true /* shallowCategoryLookup */,
+ false /* followSuper */))
if (C || MethodInClass->isPropertyAccessor())
continue;
unsigned DIAG = diag::warn_unimplemented_protocol_method;
- if (Diags.getDiagnosticLevel(DIAG, ImpLoc)
+ if (S.Diags.getDiagnosticLevel(DIAG, ImpLoc)
!= DiagnosticsEngine::Ignored) {
- WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG);
- Diag(CDecl->getLocation(), diag::note_required_for_protocol_at)
- << PDecl->getDeclName();
+ WarnUndefinedMethod(S, ImpLoc, method, IncompleteImpl, DIAG,
+ PDecl);
}
}
}
// check unimplemented class methods
- for (ObjCProtocolDecl::classmeth_iterator
- I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
- I != E; ++I) {
- ObjCMethodDecl *method = *I;
+ for (auto *method : PDecl->class_methods()) {
if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
!ClsMap.count(method->getSelector()) &&
- (!Super || !Super->lookupClassMethod(method->getSelector()))) {
+ (!Super || !Super->lookupMethod(method->getSelector(),
+ false /* class method */,
+ false /* shallowCategoryLookup */,
+ true /* followSuper */,
+ NULL /* category */))) {
// See above comment for instance method lookups.
- if (C && IDecl->lookupClassMethod(method->getSelector(),
- true /*shallowCategoryLookup*/))
+ if (C && IDecl->lookupMethod(method->getSelector(),
+ false /* class */,
+ true /* shallowCategoryLookup */,
+ false /* followSuper */))
continue;
+
unsigned DIAG = diag::warn_unimplemented_protocol_method;
- if (Diags.getDiagnosticLevel(DIAG, ImpLoc) !=
+ if (S.Diags.getDiagnosticLevel(DIAG, ImpLoc) !=
DiagnosticsEngine::Ignored) {
- WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG);
- Diag(IDecl->getLocation(), diag::note_required_for_protocol_at) <<
- PDecl->getDeclName();
+ WarnUndefinedMethod(S, ImpLoc, method, IncompleteImpl, DIAG, PDecl);
}
}
}
// Check on this protocols's referenced protocols, recursively.
- for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
- E = PDecl->protocol_end(); PI != E; ++PI)
- CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, CDecl);
+ for (auto *PI : PDecl->protocols())
+ CheckProtocolMethodDefs(S, ImpLoc, PI, IncompleteImpl, InsMap, ClsMap,
+ CDecl, ProtocolsExplictImpl);
}
/// MatchAllMethodDeclarations - Check methods declared in interface
@@ -1729,56 +1819,50 @@
bool WarnCategoryMethodImpl) {
// Check and see if instance methods in class interface have been
// 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.insert((*I)->getSelector()))
+ for (auto *I : CDecl->instance_methods()) {
+ if (!InsMapSeen.insert(I->getSelector()))
continue;
- if (!(*I)->isPropertyAccessor() &&
- !InsMap.count((*I)->getSelector())) {
+ if (!I->isPropertyAccessor() &&
+ !InsMap.count(I->getSelector())) {
if (ImmediateClass)
- WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl,
+ WarnUndefinedMethod(*this, IMPDecl->getLocation(), I, IncompleteImpl,
diag::warn_undef_method_impl);
continue;
} else {
ObjCMethodDecl *ImpMethodDecl =
- IMPDecl->getInstanceMethod((*I)->getSelector());
- assert(CDecl->getInstanceMethod((*I)->getSelector()) &&
+ IMPDecl->getInstanceMethod(I->getSelector());
+ assert(CDecl->getInstanceMethod(I->getSelector()) &&
"Expected to find the method through lookup as well");
- ObjCMethodDecl *MethodDecl = *I;
// ImpMethodDecl may be null as in a @dynamic property.
if (ImpMethodDecl) {
if (!WarnCategoryMethodImpl)
- WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl,
+ WarnConflictingTypedMethods(ImpMethodDecl, I,
isa<ObjCProtocolDecl>(CDecl));
- else if (!MethodDecl->isPropertyAccessor())
- WarnExactTypedMethods(ImpMethodDecl, MethodDecl,
- isa<ObjCProtocolDecl>(CDecl));
+ else if (!I->isPropertyAccessor())
+ WarnExactTypedMethods(ImpMethodDecl, I, isa<ObjCProtocolDecl>(CDecl));
}
}
}
// 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.insert((*I)->getSelector()))
+ for (auto *I : CDecl->class_methods()) {
+ if (!ClsMapSeen.insert(I->getSelector()))
continue;
- if (!ClsMap.count((*I)->getSelector())) {
+ if (!ClsMap.count(I->getSelector())) {
if (ImmediateClass)
- WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl,
+ WarnUndefinedMethod(*this, IMPDecl->getLocation(), I, IncompleteImpl,
diag::warn_undef_method_impl);
} else {
ObjCMethodDecl *ImpMethodDecl =
- IMPDecl->getClassMethod((*I)->getSelector());
- assert(CDecl->getClassMethod((*I)->getSelector()) &&
+ IMPDecl->getClassMethod(I->getSelector());
+ assert(CDecl->getClassMethod(I->getSelector()) &&
"Expected to find the method through lookup as well");
- ObjCMethodDecl *MethodDecl = *I;
if (!WarnCategoryMethodImpl)
- WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl,
+ WarnConflictingTypedMethods(ImpMethodDecl, I,
isa<ObjCProtocolDecl>(CDecl));
else
- WarnExactTypedMethods(ImpMethodDecl, MethodDecl,
+ WarnExactTypedMethods(ImpMethodDecl, I,
isa<ObjCProtocolDecl>(CDecl));
}
}
@@ -1786,10 +1870,9 @@
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)
+ for (auto *PI : PD->protocols())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
- IMPDecl, (*PI), IncompleteImpl, false,
+ IMPDecl, PI, IncompleteImpl, false,
WarnCategoryMethodImpl);
}
@@ -1798,35 +1881,24 @@
// i.e. when WarnCategoryMethodImpl is false, check declarations in class
// extension; as well as those in categories.
if (!WarnCategoryMethodImpl) {
- for (ObjCInterfaceDecl::visible_categories_iterator
- Cat = I->visible_categories_begin(),
- CatEnd = I->visible_categories_end();
- Cat != CatEnd; ++Cat) {
+ for (auto *Cat : I->visible_categories())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
- IMPDecl, *Cat, IncompleteImpl, false,
+ IMPDecl, Cat, IncompleteImpl, false,
WarnCategoryMethodImpl);
- }
} else {
// Also methods in class extensions need be looked at next.
- for (ObjCInterfaceDecl::visible_extensions_iterator
- Ext = I->visible_extensions_begin(),
- ExtEnd = I->visible_extensions_end();
- Ext != ExtEnd; ++Ext) {
+ for (auto *Ext : I->visible_extensions())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
- IMPDecl, *Ext, IncompleteImpl, false,
+ IMPDecl, Ext, IncompleteImpl, false,
WarnCategoryMethodImpl);
- }
}
// Check for any implementation of a methods declared in protocol.
- for (ObjCInterfaceDecl::all_protocol_iterator
- PI = I->all_referenced_protocol_begin(),
- E = I->all_referenced_protocol_end(); PI != E; ++PI)
+ for (auto *PI : I->all_referenced_protocols())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
- IMPDecl,
- (*PI), IncompleteImpl, false,
+ IMPDecl, PI, IncompleteImpl, false,
WarnCategoryMethodImpl);
-
+
// FIXME. For now, we are not checking for extact match of methods
// in category implementation and its primary class's super class.
if (!WarnCategoryMethodImpl && I->getSuperClass())
@@ -1841,20 +1913,6 @@
/// warns each time an exact match is found.
void Sema::CheckCategoryVsClassMethodMatches(
ObjCCategoryImplDecl *CatIMPDecl) {
- SelectorSet InsMap, ClsMap;
-
- for (ObjCImplementationDecl::instmeth_iterator
- I = CatIMPDecl->instmeth_begin(),
- E = CatIMPDecl->instmeth_end(); I!=E; ++I)
- InsMap.insert((*I)->getSelector());
-
- for (ObjCImplementationDecl::classmeth_iterator
- I = CatIMPDecl->classmeth_begin(),
- E = CatIMPDecl->classmeth_end(); I != E; ++I)
- ClsMap.insert((*I)->getSelector());
- if (InsMap.empty() && ClsMap.empty())
- return;
-
// Get category's primary class.
ObjCCategoryDecl *CatDecl = CatIMPDecl->getCategoryDecl();
if (!CatDecl)
@@ -1862,6 +1920,28 @@
ObjCInterfaceDecl *IDecl = CatDecl->getClassInterface();
if (!IDecl)
return;
+ ObjCInterfaceDecl *SuperIDecl = IDecl->getSuperClass();
+ SelectorSet InsMap, ClsMap;
+
+ for (const auto *I : CatIMPDecl->instance_methods()) {
+ Selector Sel = I->getSelector();
+ // When checking for methods implemented in the category, skip over
+ // those declared in category class's super class. This is because
+ // the super class must implement the method.
+ if (SuperIDecl && SuperIDecl->lookupMethod(Sel, true))
+ continue;
+ InsMap.insert(Sel);
+ }
+
+ for (const auto *I : CatIMPDecl->class_methods()) {
+ Selector Sel = I->getSelector();
+ if (SuperIDecl && SuperIDecl->lookupMethod(Sel, false))
+ continue;
+ ClsMap.insert(Sel);
+ }
+ if (InsMap.empty() && ClsMap.empty())
+ return;
+
SelectorSet InsMapSeen, ClsMapSeen;
bool IncompleteImpl = false;
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
@@ -1876,24 +1956,22 @@
SelectorSet InsMap;
// Check and see if instance methods in class interface have been
// implemented in the implementation class.
- for (ObjCImplementationDecl::instmeth_iterator
- I = IMPDecl->instmeth_begin(), E = IMPDecl->instmeth_end(); I!=E; ++I)
- InsMap.insert((*I)->getSelector());
+ for (const auto *I : IMPDecl->instance_methods())
+ InsMap.insert(I->getSelector());
// Check and see if properties declared in the interface have either 1)
// an implementation or 2) there is a @synthesize/@dynamic implementation
// of the property in the @implementation.
- if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl))
- if (!(LangOpts.ObjCDefaultSynthProperties &&
- LangOpts.ObjCRuntime.isNonFragile()) ||
- IDecl->isObjCRequiresPropertyDefs())
- DiagnoseUnimplementedProperties(S, IMPDecl, CDecl);
-
+ if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+ bool SynthesizeProperties = LangOpts.ObjCDefaultSynthProperties &&
+ LangOpts.ObjCRuntime.isNonFragile() &&
+ !IDecl->isObjCRequiresPropertyDefs();
+ DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, SynthesizeProperties);
+ }
+
SelectorSet ClsMap;
- for (ObjCImplementationDecl::classmeth_iterator
- I = IMPDecl->classmeth_begin(),
- E = IMPDecl->classmeth_end(); I != E; ++I)
- ClsMap.insert((*I)->getSelector());
+ for (const auto *I : IMPDecl->class_methods())
+ ClsMap.insert(I->getSelector());
// Check for type conflict of methods declared in a class/protocol and
// its implementation; if any.
@@ -1913,28 +1991,25 @@
// Check and see if class methods in class interface have been
// implemented in the implementation class.
+ LazyProtocolNameSet ExplicitImplProtocols;
+
if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
- for (ObjCInterfaceDecl::all_protocol_iterator
- PI = I->all_referenced_protocol_begin(),
- E = I->all_referenced_protocol_end(); PI != E; ++PI)
- CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
- InsMap, ClsMap, I);
+ for (auto *PI : I->all_referenced_protocols())
+ CheckProtocolMethodDefs(*this, IMPDecl->getLocation(), PI, IncompleteImpl,
+ InsMap, ClsMap, I, ExplicitImplProtocols);
// Check class extensions (unnamed categories)
- for (ObjCInterfaceDecl::visible_extensions_iterator
- Ext = I->visible_extensions_begin(),
- ExtEnd = I->visible_extensions_end();
- Ext != ExtEnd; ++Ext) {
- ImplMethodsVsClassMethods(S, IMPDecl, *Ext, IncompleteImpl);
- }
+ for (auto *Ext : I->visible_extensions())
+ ImplMethodsVsClassMethods(S, IMPDecl, Ext, IncompleteImpl);
} else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
// For extended class, unimplemented methods in its protocols will
// be reported in the primary class.
if (!C->IsClassExtension()) {
- for (ObjCCategoryDecl::protocol_iterator PI = C->protocol_begin(),
- E = C->protocol_end(); PI != E; ++PI)
- CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
- InsMap, ClsMap, CDecl);
- DiagnoseUnimplementedProperties(S, IMPDecl, CDecl);
+ for (auto *P : C->protocols())
+ CheckProtocolMethodDefs(*this, IMPDecl->getLocation(), P,
+ IncompleteImpl, InsMap, ClsMap, CDecl,
+ ExplicitImplProtocols);
+ DiagnoseUnimplementedProperties(S, IMPDecl, CDecl,
+ /* SynthesizeProperties */ false);
}
} else
llvm_unreachable("invalid ObjCContainerDecl type.");
@@ -2103,8 +2178,8 @@
bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left,
const ObjCMethodDecl *right,
MethodMatchStrategy strategy) {
- if (!matchTypes(Context, strategy,
- left->getResultType(), right->getResultType()))
+ if (!matchTypes(Context, strategy, left->getReturnType(),
+ right->getReturnType()))
return false;
// If either is hidden, it is not considered to match.
@@ -2233,7 +2308,7 @@
// Don't complain about mismatches for -length if the method we
// chose has an integral result type.
- return (chosen->getResultType()->isIntegerType());
+ return (chosen->getReturnType()->isIntegerType());
}
ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
@@ -2327,11 +2402,15 @@
return 0;
GlobalMethods &Methods = Pos->second;
-
- if (Methods.first.Method && Methods.first.Method->isDefined())
- return Methods.first.Method;
- if (Methods.second.Method && Methods.second.Method->isDefined())
- return Methods.second.Method;
+ for (const ObjCMethodList *Method = &Methods.first; Method;
+ Method = Method->getNext())
+ if (Method->Method && Method->Method->isDefined())
+ return Method->Method;
+
+ for (const ObjCMethodList *Method = &Methods.second; Method;
+ Method = Method->getNext())
+ if (Method->Method && Method->Method->isDefined())
+ return Method->Method;
return 0;
}
@@ -2423,51 +2502,6 @@
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
@@ -2475,9 +2509,7 @@
/// class's \@implementation is seen.
void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,
ObjCInterfaceDecl *SID) {
- for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(),
- IVE = ID->ivar_end(); IVI != IVE; ++IVI) {
- ObjCIvarDecl* Ivar = *IVI;
+ for (auto *Ivar : ID->ivars()) {
if (Ivar->isInvalidDecl())
continue;
if (IdentifierInfo *II = Ivar->getIdentifier()) {
@@ -2603,10 +2635,8 @@
// ProcessPropertyDecl is responsible for diagnosing conflicts with any
// user-defined setter/getter. It also synthesizes setter/getter methods
// and adds them to the DeclContext and global method pools.
- for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(),
- E = CDecl->prop_end();
- I != E; ++I)
- ProcessPropertyDecl(*I, CDecl);
+ for (auto *I : CDecl->properties())
+ ProcessPropertyDecl(I, CDecl);
CDecl->setAtEndRange(AtEnd);
}
if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
@@ -2617,13 +2647,8 @@
// of the other class extensions. Mark them as synthesized as
// property will be synthesized when property with same name is
// seen in the @implementation.
- for (ObjCInterfaceDecl::visible_extensions_iterator
- Ext = IDecl->visible_extensions_begin(),
- ExtEnd = IDecl->visible_extensions_end();
- Ext != ExtEnd; ++Ext) {
- for (ObjCContainerDecl::prop_iterator I = Ext->prop_begin(),
- E = Ext->prop_end(); I != E; ++I) {
- ObjCPropertyDecl *Property = *I;
+ for (const auto *Ext : IDecl->visible_extensions()) {
+ for (const auto *Property : Ext->properties()) {
// Skip over properties declared @dynamic
if (const ObjCPropertyImplDecl *PIDecl
= IC->FindPropertyImplDecl(Property->getIdentifier()))
@@ -2631,10 +2656,7 @@
== ObjCPropertyImplDecl::Dynamic)
continue;
- for (ObjCInterfaceDecl::visible_extensions_iterator
- Ext = IDecl->visible_extensions_begin(),
- ExtEnd = IDecl->visible_extensions_end();
- Ext != ExtEnd; ++Ext) {
+ for (const auto *Ext : IDecl->visible_extensions()) {
if (ObjCMethodDecl *GetterMethod
= Ext->getInstanceMethod(Property->getGetterName()))
GetterMethod->setPropertyAccessor(true);
@@ -2648,7 +2670,10 @@
ImplMethodsVsClassMethods(S, IC, IDecl);
AtomicPropertySetterGetterRules(IC, IDecl);
DiagnoseOwningPropertyGetterSynthesis(IC);
-
+ DiagnoseUnusedBackingIvarInAccessor(S, IC);
+ if (IDecl->hasDesignatedInitializers())
+ DiagnoseMissingDesignatedInitOverrides(IC, IDecl);
+
bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>();
if (IDecl->getSuperClass() == NULL) {
// This class has no superclass, so check that it has been marked with
@@ -2729,72 +2754,14 @@
return (Decl::ObjCDeclQualifier) (unsigned) PQTVal;
}
-static inline
-unsigned countAlignAttr(const AttrVec &A) {
- unsigned count=0;
- for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i)
- if ((*i)->getKind() == attr::Aligned)
- ++count;
- return count;
-}
-
-static inline
-bool containsInvalidMethodImplAttribute(ObjCMethodDecl *IMD,
- const AttrVec &A) {
- // If method is only declared in implementation (private method),
- // No need to issue any diagnostics on method definition with attributes.
- if (!IMD)
- return false;
-
- // method declared in interface has no attribute.
- // But implementation has attributes. This is invalid.
- // Except when implementation has 'Align' attribute which is
- // immaterial to method declared in interface.
- if (!IMD->hasAttrs())
- return (A.size() > countAlignAttr(A));
-
- const AttrVec &D = IMD->getAttrs();
-
- unsigned countAlignOnImpl = countAlignAttr(A);
- if (!countAlignOnImpl && (A.size() != D.size()))
- return true;
- else if (countAlignOnImpl) {
- unsigned countAlignOnDecl = countAlignAttr(D);
- if (countAlignOnDecl && (A.size() != D.size()))
- return true;
- else if (!countAlignOnDecl &&
- ((A.size()-countAlignOnImpl) != D.size()))
- return true;
- }
-
- // attributes on method declaration and definition must match exactly.
- // Note that we have at most a couple of attributes on methods, so this
- // n*n search is good enough.
- for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i) {
- if ((*i)->getKind() == attr::Aligned)
- continue;
- bool match = false;
- for (AttrVec::const_iterator i1 = D.begin(), e1 = D.end(); i1 != e1; ++i1) {
- if ((*i)->getKind() == (*i1)->getKind()) {
- match = true;
- break;
- }
- }
- if (!match)
- return true;
- }
-
- return false;
-}
-
/// \brief Check whether the declared result type of the given Objective-C
/// method declaration is compatible with the method's class.
///
static Sema::ResultTypeCompatibilityKind
CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method,
ObjCInterfaceDecl *CurrentClass) {
- QualType ResultType = Method->getResultType();
-
+ QualType ResultType = Method->getReturnType();
+
// If an Objective-C method inherits its related result type, then its
// declared result type must be compatible with its own class type. The
// declared result type is compatible if:
@@ -2928,12 +2895,8 @@
return;
// - categories,
- for (ObjCInterfaceDecl::known_categories_iterator
- cat = iface->known_categories_begin(),
- catEnd = iface->known_categories_end();
- cat != catEnd; ++cat) {
- search(*cat);
- }
+ for (auto *Cat : iface->known_categories())
+ search(Cat);
// - the super class, and
if (ObjCInterfaceDecl *super = iface->getSuperClass())
@@ -3102,9 +3065,9 @@
QualType resultDeclType;
bool HasRelatedResultType = false;
- TypeSourceInfo *ResultTInfo = 0;
+ TypeSourceInfo *ReturnTInfo = 0;
if (ReturnType) {
- resultDeclType = GetTypeFromParser(ReturnType, &ResultTInfo);
+ resultDeclType = GetTypeFromParser(ReturnType, &ReturnTInfo);
if (CheckFunctionReturnType(resultDeclType, MethodLoc))
return 0;
@@ -3116,18 +3079,14 @@
<< FixItHint::CreateInsertion(SelectorLocs.front(), "(id)");
}
- ObjCMethodDecl* ObjCMethod =
- ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel,
- resultDeclType,
- ResultTInfo,
- CurContext,
- MethodType == tok::minus, isVariadic,
- /*isPropertyAccessor=*/false,
- /*isImplicitlyDeclared=*/false, /*isDefined=*/false,
- MethodDeclKind == tok::objc_optional
- ? ObjCMethodDecl::Optional
- : ObjCMethodDecl::Required,
- HasRelatedResultType);
+ ObjCMethodDecl *ObjCMethod = ObjCMethodDecl::Create(
+ Context, MethodLoc, EndLoc, Sel, resultDeclType, ReturnTInfo, CurContext,
+ MethodType == tok::minus, isVariadic,
+ /*isPropertyAccessor=*/false,
+ /*isImplicitlyDeclared=*/false, /*isDefined=*/false,
+ MethodDeclKind == tok::objc_optional ? ObjCMethodDecl::Optional
+ : ObjCMethodDecl::Required,
+ HasRelatedResultType);
SmallVector<ParmVarDecl*, 16> Params;
@@ -3221,17 +3180,15 @@
if (IMD && IMD->hasAttr<ObjCRequiresSuperAttr>() &&
!ObjCMethod->hasAttr<ObjCRequiresSuperAttr>()) {
// merge the attribute into implementation.
- ObjCMethod->addAttr(
- new (Context) ObjCRequiresSuperAttr(ObjCMethod->getLocation(), Context));
+ ObjCMethod->addAttr(ObjCRequiresSuperAttr::CreateImplicit(Context,
+ ObjCMethod->getLocation()));
}
- if (ObjCMethod->hasAttrs() &&
- containsInvalidMethodImplAttribute(IMD, ObjCMethod->getAttrs())) {
- SourceLocation MethodLoc = IMD->getLocation();
- if (!getSourceManager().isInSystemHeader(MethodLoc)) {
- Diag(EndLoc, diag::warn_attribute_method_def);
- Diag(MethodLoc, diag::note_method_declared_at)
+ if (isa<ObjCCategoryImplDecl>(ImpDecl)) {
+ ObjCMethodFamily family =
+ ObjCMethod->getSelector().getMethodFamily();
+ if (family == OMF_dealloc && IMD && IMD->isOverriding())
+ Diag(ObjCMethod->getLocation(), diag::warn_dealloc_in_category)
<< ObjCMethod->getDeclName();
- }
}
} else {
cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod);
@@ -3482,8 +3439,6 @@
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.
@@ -3503,39 +3458,93 @@
ObjCIvarDecl *
Sema::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
const ObjCPropertyDecl *&PDecl) const {
-
+ if (Method->isClassMethod())
+ return 0;
const ObjCInterfaceDecl *IDecl = Method->getClassInterface();
if (!IDecl)
return 0;
- Method = IDecl->lookupMethod(Method->getSelector(), true);
+ Method = IDecl->lookupMethod(Method->getSelector(), /*isInstance=*/true,
+ /*shallowCategoryLookup=*/false,
+ /*followSuper=*/false);
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();
- }
+ if ((PDecl = Method->findPropertyDecl()))
+ if (ObjCIvarDecl *IV = PDecl->getPropertyIvarDecl()) {
+ // property backing ivar must belong to property's class
+ // or be a private ivar in class's implementation.
+ // FIXME. fix the const-ness issue.
+ IV = const_cast<ObjCInterfaceDecl *>(IDecl)->lookupInstanceVariable(
+ IV->getIdentifier());
+ return IV;
+ }
return 0;
}
-void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S) {
- if (S->hasUnrecoverableErrorOccurred() || !S->isInObjcMethodScope())
+namespace {
+ /// Used by Sema::DiagnoseUnusedBackingIvarInAccessor to check if a property
+ /// accessor references the backing ivar.
+ class UnusedBackingIvarChecker :
+ public DataRecursiveASTVisitor<UnusedBackingIvarChecker> {
+ public:
+ Sema &S;
+ const ObjCMethodDecl *Method;
+ const ObjCIvarDecl *IvarD;
+ bool AccessedIvar;
+ bool InvokedSelfMethod;
+
+ UnusedBackingIvarChecker(Sema &S, const ObjCMethodDecl *Method,
+ const ObjCIvarDecl *IvarD)
+ : S(S), Method(Method), IvarD(IvarD),
+ AccessedIvar(false), InvokedSelfMethod(false) {
+ assert(IvarD);
+ }
+
+ bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+ if (E->getDecl() == IvarD) {
+ AccessedIvar = true;
+ return false;
+ }
+ return true;
+ }
+
+ bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ if (E->getReceiverKind() == ObjCMessageExpr::Instance &&
+ S.isSelfExpr(E->getInstanceReceiver(), Method)) {
+ InvokedSelfMethod = true;
+ }
+ return true;
+ }
+ };
+}
+
+void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S,
+ const ObjCImplementationDecl *ImplD) {
+ if (S->hasUnrecoverableErrorOccurred())
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);
+
+ for (const auto *CurMethod : ImplD->instance_methods()) {
+ unsigned DIAG = diag::warn_unused_property_backing_ivar;
+ SourceLocation Loc = CurMethod->getLocation();
+ if (Diags.getDiagnosticLevel(DIAG, Loc) == DiagnosticsEngine::Ignored)
+ continue;
+
+ const ObjCPropertyDecl *PDecl;
+ const ObjCIvarDecl *IV = GetIvarBackingPropertyAccessor(CurMethod, PDecl);
+ if (!IV)
+ continue;
+
+ UnusedBackingIvarChecker Checker(*this, CurMethod, IV);
+ Checker.TraverseStmt(CurMethod->getBody());
+ if (Checker.AccessedIvar)
+ continue;
+
+ // Do not issue this warning if backing ivar is used somewhere and accessor
+ // implementation makes a self call. This is to prevent false positive in
+ // cases where the ivar is accessed by another method that the accessor
+ // delegates to.
+ if (!IV->isReferenced() || !Checker.InvokedSelfMethod) {
+ Diag(Loc, DIAG) << IV;
+ Diag(PDecl->getLocation(), diag::note_property_declare);
+ }
}
}
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 3e8f324..59fd85e 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
@@ -132,6 +133,25 @@
return SourceDecl->getType()->castAs<FunctionProtoType>();
}
+void Sema::UpdateExceptionSpec(FunctionDecl *FD,
+ const FunctionProtoType::ExtProtoInfo &EPI) {
+ const FunctionProtoType *Proto = FD->getType()->castAs<FunctionProtoType>();
+
+ // Overwrite the exception spec and rebuild the function type.
+ FunctionProtoType::ExtProtoInfo NewEPI = Proto->getExtProtoInfo();
+ NewEPI.ExceptionSpecType = EPI.ExceptionSpecType;
+ NewEPI.NumExceptions = EPI.NumExceptions;
+ NewEPI.Exceptions = EPI.Exceptions;
+ NewEPI.NoexceptExpr = EPI.NoexceptExpr;
+ FD->setType(Context.getFunctionType(Proto->getReturnType(),
+ Proto->getParamTypes(), NewEPI));
+
+ // If we've fully resolved the exception specification, notify listeners.
+ if (!isUnresolvedExceptionSpec(EPI.ExceptionSpecType))
+ if (auto *Listener = getASTMutationListener())
+ Listener->ResolvedExceptionSpec(FD);
+}
+
/// Determine whether a function has an implicitly-generated exception
/// specification.
static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
@@ -140,10 +160,13 @@
Decl->getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
return false;
- // If the user didn't declare the function, its exception specification must
- // be implicit.
+ // For a function that the user didn't declare:
+ // - if this is a destructor, its exception specification is implicit.
+ // - if this is 'operator delete' or 'operator delete[]', the exception
+ // specification is as-if an explicit exception specification was given
+ // (per [basic.stc.dynamic]p2).
if (!Decl->getTypeSourceInfo())
- return true;
+ return isa<CXXDestructorDecl>(Decl);
const FunctionProtoType *Ty =
Decl->getTypeSourceInfo()->getType()->getAs<FunctionProtoType>();
@@ -155,9 +178,13 @@
bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
bool MissingExceptionSpecification = false;
bool MissingEmptyExceptionSpecification = false;
+
unsigned DiagID = diag::err_mismatched_exception_spec;
- if (getLangOpts().MicrosoftExt)
+ bool ReturnValueOnError = true;
+ if (getLangOpts().MicrosoftExt) {
DiagID = diag::warn_mismatched_exception_spec;
+ ReturnValueOnError = false;
+ }
// Check the types as written: they must match before any exception
// specification adjustment is applied.
@@ -182,9 +209,9 @@
}
// The failure was something other than an missing exception
- // specification; return an error.
+ // specification; return an error, except in MS mode where this is a warning.
if (!MissingExceptionSpecification)
- return true;
+ return ReturnValueOnError;
const FunctionProtoType *NewProto =
New->getType()->castAs<FunctionProtoType>();
@@ -203,8 +230,8 @@
Old->isExternC()) {
FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
EPI.ExceptionSpecType = EST_DynamicNone;
- QualType NewType = Context.getFunctionType(NewProto->getResultType(),
- NewProto->getArgTypes(), EPI);
+ QualType NewType = Context.getFunctionType(NewProto->getReturnType(),
+ NewProto->getParamTypes(), EPI);
New->setType(NewType);
return false;
}
@@ -224,8 +251,8 @@
// Update the type of the function with the appropriate exception
// specification.
- QualType NewType = Context.getFunctionType(NewProto->getResultType(),
- NewProto->getArgTypes(), EPI);
+ QualType NewType = Context.getFunctionType(NewProto->getReturnType(),
+ NewProto->getParamTypes(), EPI);
New->setType(NewType);
// Warn about the lack of exception specification.
@@ -239,16 +266,13 @@
case EST_Dynamic: {
OS << "throw(";
bool OnFirstException = true;
- for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(),
- EEnd = OldProto->exception_end();
- E != EEnd;
- ++E) {
+ for (const auto &E : OldProto->exceptions()) {
if (OnFirstException)
OnFirstException = false;
else
OS << ", ";
- OS << E->getAsString(getPrintingPolicy());
+ OS << E.getAsString(getPrintingPolicy());
}
OS << ")";
break;
@@ -302,10 +326,14 @@
const FunctionProtoType *New, SourceLocation NewLoc) {
unsigned DiagID = diag::err_mismatched_exception_spec;
if (getLangOpts().MicrosoftExt)
- DiagID = diag::warn_mismatched_exception_spec;
- return CheckEquivalentExceptionSpec(PDiag(DiagID),
- PDiag(diag::note_previous_declaration),
- Old, OldLoc, New, NewLoc);
+ DiagID = diag::warn_mismatched_exception_spec;
+ bool Result = CheckEquivalentExceptionSpec(PDiag(DiagID),
+ PDiag(diag::note_previous_declaration), Old, OldLoc, New, NewLoc);
+
+ // In Microsoft mode, mismatching exception specifications just cause a warning.
+ if (getLangOpts().MicrosoftExt)
+ return false;
+ return Result;
}
/// CheckEquivalentExceptionSpec - Check if the two types have compatible
@@ -488,13 +516,11 @@
// Both have a dynamic exception spec. Collect the first set, then compare
// to the second.
llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
- for (FunctionProtoType::exception_iterator I = Old->exception_begin(),
- E = Old->exception_end(); I != E; ++I)
- OldTypes.insert(Context.getCanonicalType(*I).getUnqualifiedType());
+ for (const auto &I : Old->exceptions())
+ OldTypes.insert(Context.getCanonicalType(I).getUnqualifiedType());
- for (FunctionProtoType::exception_iterator I = New->exception_begin(),
- E = New->exception_end(); I != E && Success; ++I) {
- CanQualType TypePtr = Context.getCanonicalType(*I).getUnqualifiedType();
+ for (const auto &I : New->exceptions()) {
+ CanQualType TypePtr = Context.getCanonicalType(I).getUnqualifiedType();
if(OldTypes.count(TypePtr))
NewTypes.insert(TypePtr);
else
@@ -602,10 +628,9 @@
"Exception spec subset: non-dynamic case slipped through.");
// Neither contains everything or nothing. Do a proper comparison.
- for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(),
- SubE = Subset->exception_end(); SubI != SubE; ++SubI) {
+ for (const auto &SubI : Subset->exceptions()) {
// Take one type from the subset.
- QualType CanonicalSubT = Context.getCanonicalType(*SubI);
+ QualType CanonicalSubT = Context.getCanonicalType(SubI);
// Unwrap pointers and references so that we can do checks within a class
// hierarchy. Don't unwrap member pointers; they don't have hierarchy
// conversions on the pointee.
@@ -624,10 +649,8 @@
bool Contained = false;
// Make sure it's in the superset.
- for (FunctionProtoType::exception_iterator SuperI =
- Superset->exception_begin(), SuperE = Superset->exception_end();
- SuperI != SuperE; ++SuperI) {
- QualType CanonicalSuperT = Context.getCanonicalType(*SuperI);
+ for (const auto &SuperI : Superset->exceptions()) {
+ QualType CanonicalSuperT = Context.getCanonicalType(SuperI);
// SubT must be SuperT or derived from it, or pointer or reference to
// such types.
if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>())
@@ -711,23 +734,21 @@
const FunctionProtoType *Target, SourceLocation TargetLoc,
const FunctionProtoType *Source, SourceLocation SourceLoc)
{
- if (CheckSpecForTypesEquivalent(*this,
- PDiag(diag::err_deep_exception_specs_differ) << 0,
- PDiag(),
- Target->getResultType(), TargetLoc,
- Source->getResultType(), SourceLoc))
+ if (CheckSpecForTypesEquivalent(
+ *this, PDiag(diag::err_deep_exception_specs_differ) << 0, PDiag(),
+ Target->getReturnType(), TargetLoc, Source->getReturnType(),
+ SourceLoc))
return true;
// We shouldn't even be testing this unless the arguments are otherwise
// compatible.
- assert(Target->getNumArgs() == Source->getNumArgs() &&
+ assert(Target->getNumParams() == Source->getNumParams() &&
"Functions have different argument counts.");
- for (unsigned i = 0, E = Target->getNumArgs(); i != E; ++i) {
- if (CheckSpecForTypesEquivalent(*this,
- PDiag(diag::err_deep_exception_specs_differ) << 1,
- PDiag(),
- Target->getArgType(i), TargetLoc,
- Source->getArgType(i), SourceLoc))
+ for (unsigned i = 0, E = Target->getNumParams(); i != E; ++i) {
+ if (CheckSpecForTypesEquivalent(
+ *this, PDiag(diag::err_deep_exception_specs_differ) << 1, PDiag(),
+ Target->getParamType(i), TargetLoc, Source->getParamType(i),
+ SourceLoc))
return true;
}
return false;
@@ -1063,7 +1084,6 @@
case Expr::AddrLabelExprClass:
case Expr::ArrayTypeTraitExprClass:
case Expr::AtomicExprClass:
- case Expr::BinaryTypeTraitExprClass:
case Expr::TypeTraitExprClass:
case Expr::CXXBoolLiteralExprClass:
case Expr::CXXNoexceptExprClass:
@@ -1086,7 +1106,6 @@
case Expr::PredefinedExprClass:
case Expr::SizeOfPackExprClass:
case Expr::StringLiteralClass:
- case Expr::UnaryTypeTraitExprClass:
// These expressions can never throw.
return CT_Cannot;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index e1f65f4..7894682 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -59,8 +59,8 @@
// If the function has a deduced return type, and we can't deduce it,
// then we can't use it either.
- if (getLangOpts().CPlusPlus1y && FD->getResultType()->isUndeducedType() &&
- DeduceReturnType(FD, SourceLocation(), /*Diagnose*/false))
+ if (getLangOpts().CPlusPlus1y && FD->getReturnType()->isUndeducedType() &&
+ DeduceReturnType(FD, SourceLocation(), /*Diagnose*/ false))
return false;
}
@@ -111,32 +111,17 @@
break;
case AR_Deprecated:
- S.EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass, ObjCPDecl);
+ if (S.getCurContextAvailability() != AR_Deprecated)
+ S.EmitAvailabilityWarning(Sema::AD_Deprecation,
+ D, Message, Loc, UnknownObjCClass, ObjCPDecl);
break;
-
+
case AR_Unavailable:
- if (S.getCurContextAvailability() != AR_Unavailable) {
- if (Message.empty()) {
- if (!UnknownObjCClass) {
- S.Diag(Loc, diag::err_unavailable) << D->getDeclName();
- if (ObjCPDecl)
- S.Diag(ObjCPDecl->getLocation(), diag::note_property_attribute)
- << ObjCPDecl->getDeclName() << 1;
- }
- else
- S.Diag(Loc, diag::warn_unavailable_fwdclass_message)
- << D->getDeclName();
- }
- else
- S.Diag(Loc, diag::err_unavailable_message)
- << D->getDeclName() << Message;
- S.Diag(D->getLocation(), diag::note_unavailable_here)
- << isa<FunctionDecl>(D) << false;
- if (ObjCPDecl)
- S.Diag(ObjCPDecl->getLocation(), diag::note_property_attribute)
- << ObjCPDecl->getDeclName() << 1;
- }
+ if (S.getCurContextAvailability() != AR_Unavailable)
+ S.EmitAvailabilityWarning(Sema::AD_Unavailable,
+ D, Message, Loc, UnknownObjCClass, ObjCPDecl);
break;
+
}
return Result;
}
@@ -176,16 +161,14 @@
}
}
- Diag(Decl->getLocation(), diag::note_unavailable_here)
- << 1 << true;
+ Diag(Decl->getLocation(), diag::note_availability_specified_here)
+ << Decl << true;
}
/// \brief Determine whether a FunctionDecl was ever declared with an
/// explicit storage class.
static bool hasAnyExplicitStorageClass(const FunctionDecl *D) {
- for (FunctionDecl::redecl_iterator I = D->redecls_begin(),
- E = D->redecls_end();
- I != E; ++I) {
+ for (auto I : D->redecls()) {
if (I->getStorageClass() != SC_None)
return true;
}
@@ -279,13 +262,18 @@
SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second;
for (unsigned I = 0, N = Suppressed.size(); I != N; ++I)
Diag(Suppressed[I].first, Suppressed[I].second);
-
+
// Clear out the list of suppressed diagnostics, so that we don't emit
// them again for this specialization. However, we don't obsolete this
// entry from the table, because we want to avoid ever emitting these
// diagnostics again.
Suppressed.clear();
}
+
+ // C++ [basic.start.main]p3:
+ // The function 'main' shall not be used within a program.
+ if (cast<FunctionDecl>(D)->isMain())
+ Diag(Loc, diag::ext_main_used);
}
// See if this is an auto-typed variable whose initializer we are parsing.
@@ -305,7 +293,7 @@
// If the function has a deduced return type, and we can't deduce it,
// then we can't use it either.
- if (getLangOpts().CPlusPlus1y && FD->getResultType()->isUndeducedType() &&
+ if (getLangOpts().CPlusPlus1y && FD->getReturnType()->isUndeducedType() &&
DeduceReturnType(FD, Loc))
return true;
}
@@ -367,7 +355,7 @@
}
if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fn)) {
- numFormalParams = proto->getNumArgs();
+ numFormalParams = proto->getNumParams();
} else {
numFormalParams = 0;
}
@@ -444,10 +432,16 @@
QualType Ty = E->getType();
assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");
- if (Ty->isFunctionType())
+ if (Ty->isFunctionType()) {
+ // If we are here, we are not calling a function but taking
+ // its address (which is not allowed in OpenCL v1.0 s6.8.a.3).
+ if (getLangOpts().OpenCL) {
+ Diag(E->getExprLoc(), diag::err_opencl_taking_function_address);
+ return ExprError();
+ }
E = ImpCastExprToType(E, Context.getPointerType(Ty),
CK_FunctionToPointerDecay).take();
- else if (Ty->isArrayType()) {
+ } else if (Ty->isArrayType()) {
// In C90 mode, arrays only promote to pointers if the array expression is
// an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has
// type 'array of type' is converted to an expression that has type 'pointer
@@ -643,6 +637,24 @@
return Res;
}
+/// CallExprUnaryConversions - a special case of an unary conversion
+/// performed on a function designator of a call expression.
+ExprResult Sema::CallExprUnaryConversions(Expr *E) {
+ QualType Ty = E->getType();
+ ExprResult Res = E;
+ // Only do implicit cast for a function type, but not for a pointer
+ // to function type.
+ if (Ty->isFunctionType()) {
+ Res = ImpCastExprToType(E, Context.getPointerType(Ty),
+ CK_FunctionToPointerDecay).take();
+ if (Res.isInvalid())
+ return ExprError();
+ }
+ Res = DefaultLvalueConversion(Res.take());
+ if (Res.isInvalid())
+ return ExprError();
+ return Owned(Res.take());
+}
/// UsualUnaryConversions - Performs various conversions that are common to most
/// operators (C99 6.3). The conversions of array and function types are
@@ -792,14 +804,20 @@
// Complain about passing non-POD types through varargs.
switch (VAK) {
- case VAK_Valid:
- break;
-
case VAK_ValidInCXX11:
DiagRuntimeBehavior(
E->getLocStart(), 0,
PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg)
- << E->getType() << CT);
+ << Ty << CT);
+ // Fall through.
+ case VAK_Valid:
+ if (Ty->isRecordType()) {
+ // This is unlikely to be what the user intended. If the class has a
+ // 'c_str' member function, the user probably meant to call that.
+ DiagRuntimeBehavior(E->getLocStart(), 0,
+ PDiag(diag::warn_pass_class_arg_to_vararg)
+ << Ty << CT << hasCStrMethod(E) << ".c_str()");
+ }
break;
case VAK_Undefined:
@@ -1643,7 +1661,7 @@
NameInfo.getLoc(), Ty, VK, FoundD, TemplateArgs);
} else {
assert(!TemplateArgs && "No template arguments for non-variable"
- " template specialization referrences");
+ " template specialization references");
E = DeclRefExpr::Create(
Context,
SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
@@ -1748,7 +1766,7 @@
// Give a code modification hint to insert 'this->'.
// TODO: fixit for inserting 'Base<T>::' in the other cases.
// Actually quite difficult!
- if (getLangOpts().MicrosoftMode)
+ if (getLangOpts().MSVCCompat)
diagnostic = diag::warn_found_via_dependent_bases_lookup;
if (isInstance) {
Diag(R.getNameLoc(), diagnostic) << Name
@@ -1814,7 +1832,7 @@
// function definition declared at class scope then we must set
// DC to the lexical parent to be able to search into the parent
// class.
- if (getLangOpts().MicrosoftMode && isa<FunctionDecl>(DC) &&
+ if (getLangOpts().MSVCCompat && isa<FunctionDecl>(DC) &&
cast<FunctionDecl>(DC)->getFriendObjectKind() &&
DC->getLexicalParent()->isRecord())
DC = DC->getLexicalParent();
@@ -2026,17 +2044,17 @@
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 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.
+ // an unqualified 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) {
+ if (SS.isEmpty() && getLangOpts().MSVCCompat) {
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext);
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.
@@ -2263,15 +2281,7 @@
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 &&
!IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV))
@@ -2755,7 +2765,7 @@
// If we're referring to a function with an __unknown_anytype
// result type, make the entire expression __unknown_anytype.
- if (fty->getResultType() == Context.UnknownAnyTy) {
+ if (fty->getReturnType() == Context.UnknownAnyTy) {
type = Context.UnknownAnyTy;
valueKind = VK_RValue;
break;
@@ -2774,7 +2784,7 @@
// type.
if (!cast<FunctionDecl>(VD)->hasPrototype() &&
isa<FunctionProtoType>(fty))
- type = Context.getFunctionNoProtoType(fty->getResultType(),
+ type = Context.getFunctionNoProtoType(fty->getReturnType(),
fty->getExtInfo());
// Functions are r-values in C.
@@ -2792,7 +2802,7 @@
// This should only be possible with a type written directly.
if (const FunctionProtoType *proto
= dyn_cast<FunctionProtoType>(VD->getType()))
- if (proto->getResultType() == Context.UnknownAnyTy) {
+ if (proto->getReturnType() == Context.UnknownAnyTy) {
type = Context.UnknownAnyTy;
valueKind = VK_RValue;
break;
@@ -3200,7 +3210,7 @@
// If we still couldn't decide a type, we probably have something that
// does not fit in a signed long long, but has no U suffix.
if (Ty.isNull()) {
- Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
+ Diag(Tok.getLocation(), diag::ext_integer_too_large_for_signed);
Ty = Context.UnsignedLongLongTy;
Width = Context.getTargetInfo().getLongLongWidth();
}
@@ -3259,9 +3269,12 @@
return false;
}
- // Allow sizeof(void)/alignof(void) as an extension.
+ // Allow sizeof(void)/alignof(void) as an extension, unless in OpenCL where
+ // this is an error (OpenCL v1.1 s6.3.k)
if (T->isVoidType()) {
- S.Diag(Loc, diag::ext_sizeof_alignof_void_type) << TraitKind << ArgRange;
+ unsigned DiagID = S.LangOpts.OpenCL ? diag::err_opencl_sizeof_alignof_type
+ : diag::ext_sizeof_alignof_void_type;
+ S.Diag(Loc, DiagID) << TraitKind << ArgRange;
return false;
}
@@ -3302,7 +3315,7 @@
<< ICE->getSubExpr()->getType();
}
-/// \brief Check the constrains on expression operands to unary type expression
+/// \brief Check the constraints on expression operands to unary type expression
/// and type traits.
///
/// Completes any types necessary and validates the constraints on the operand
@@ -3460,7 +3473,7 @@
// delayed parsing --- except for trailing return types in C++11.
// And if an id-expression referring to a field occurs in a
// context that lacks a 'this' value, it's ill-formed --- except,
- // agian, in C++11, where such references are allowed in an
+ // again, in C++11, where such references are allowed in an
// unevaluated context. So C++11 introduces some new complexity.
//
// For the record, since __alignof__ on expressions is a GCC
@@ -3965,7 +3978,7 @@
: FunctionCallFilterCCC(SemaRef, NumArgs, HasExplicitTemplateArgs),
FunctionName(FuncName) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
if (!candidate.getCorrectionSpecifier() ||
candidate.getCorrectionAsIdentifierInfo() != FunctionName) {
return false;
@@ -4037,9 +4050,9 @@
// C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
// assignment, to the types of the corresponding parameter, ...
- unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumParams = Proto->getNumParams();
bool Invalid = false;
- unsigned MinArgs = FDecl ? FDecl->getMinRequiredArguments() : NumArgsInProto;
+ unsigned MinArgs = FDecl ? FDecl->getMinRequiredArguments() : NumParams;
unsigned FnKind = Fn->getType()->isBlockPointerType()
? 1 /* block */
: (IsExecConfig ? 3 /* kernel function (exec config) */
@@ -4047,7 +4060,7 @@
// If too few arguments are available (and we don't have default
// arguments for the remaining parameters), don't make the call.
- if (Args.size() < NumArgsInProto) {
+ if (Args.size() < NumParams) {
if (Args.size() < MinArgs) {
MemberExpr *ME = dyn_cast<MemberExpr>(Fn);
TypoCorrection TC;
@@ -4057,25 +4070,24 @@
: Fn->getLocStart())),
Args))) {
unsigned diag_id =
- MinArgs == NumArgsInProto && !Proto->isVariadic()
+ MinArgs == NumParams && !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());
+ << TC.getCorrectionRange());
} 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)
- << FnKind
- << FDecl->getParamDecl(0) << Fn->getSourceRange();
+ Diag(RParenLoc,
+ MinArgs == NumParams && !Proto->isVariadic()
+ ? diag::err_typecheck_call_too_few_args_one
+ : diag::err_typecheck_call_too_few_args_at_least_one)
+ << FnKind << FDecl->getParamDecl(0) << Fn->getSourceRange();
else
- Diag(RParenLoc, MinArgs == NumArgsInProto && !Proto->isVariadic()
- ? diag::err_typecheck_call_too_few_args
- : diag::err_typecheck_call_too_few_args_at_least)
- << FnKind
- << MinArgs << static_cast<unsigned>(Args.size())
- << Fn->getSourceRange();
+ Diag(RParenLoc, MinArgs == NumParams && !Proto->isVariadic()
+ ? diag::err_typecheck_call_too_few_args
+ : diag::err_typecheck_call_too_few_args_at_least)
+ << FnKind << MinArgs << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange();
// Emit the location of the prototype.
if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
@@ -4084,46 +4096,46 @@
return true;
}
- Call->setNumArgs(Context, NumArgsInProto);
+ Call->setNumArgs(Context, NumParams);
}
// If too many are passed and not variadic, error on the extras and drop
// them.
- if (Args.size() > NumArgsInProto) {
+ if (Args.size() > NumParams) {
if (!Proto->isVariadic()) {
+ MemberExpr *ME = dyn_cast<MemberExpr>(Fn);
TypoCorrection TC;
if (FDecl && (TC = TryTypoCorrectionForCall(
*this, DeclarationNameInfo(FDecl->getDeclName(),
- Fn->getLocStart()),
+ (ME ? ME->getMemberLoc()
+ : Fn->getLocStart())),
Args))) {
unsigned diag_id =
- MinArgs == NumArgsInProto && !Proto->isVariadic()
+ MinArgs == NumParams && !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
+ diagnoseTypo(TC, PDiag(diag_id) << FnKind << NumParams
<< static_cast<unsigned>(Args.size())
- << Fn->getSourceRange());
- } else if (NumArgsInProto == 1 && FDecl &&
+ << TC.getCorrectionRange());
+ } else if (NumParams == 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) << static_cast<unsigned>(Args.size())
- << Fn->getSourceRange()
- << SourceRange(Args[NumArgsInProto]->getLocStart(),
- Args.back()->getLocEnd());
+ Diag(Args[NumParams]->getLocStart(),
+ MinArgs == NumParams
+ ? diag::err_typecheck_call_too_many_args_one
+ : diag::err_typecheck_call_too_many_args_at_most_one)
+ << FnKind << FDecl->getParamDecl(0)
+ << static_cast<unsigned>(Args.size()) << Fn->getSourceRange()
+ << SourceRange(Args[NumParams]->getLocStart(),
+ 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 << static_cast<unsigned>(Args.size())
- << Fn->getSourceRange()
- << SourceRange(Args[NumArgsInProto]->getLocStart(),
- Args.back()->getLocEnd());
+ Diag(Args[NumParams]->getLocStart(),
+ MinArgs == NumParams
+ ? diag::err_typecheck_call_too_many_args
+ : diag::err_typecheck_call_too_many_args_at_most)
+ << FnKind << NumParams << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange()
+ << SourceRange(Args[NumParams]->getLocStart(),
+ Args.back()->getLocEnd());
// Emit the location of the prototype.
if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
@@ -4131,7 +4143,7 @@
<< FDecl;
// This deletes the extra arguments.
- Call->setNumArgs(Context, NumArgsInProto);
+ Call->setNumArgs(Context, NumParams);
return true;
}
}
@@ -4149,25 +4161,22 @@
return false;
}
-bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
- FunctionDecl *FDecl,
+bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
const FunctionProtoType *Proto,
- unsigned FirstProtoArg,
- ArrayRef<Expr *> Args,
+ unsigned FirstParam, ArrayRef<Expr *> Args,
SmallVectorImpl<Expr *> &AllArgs,
- VariadicCallType CallType,
- bool AllowExplicit,
+ VariadicCallType CallType, bool AllowExplicit,
bool IsListInitialization) {
- unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumParams = Proto->getNumParams();
unsigned NumArgsToCheck = Args.size();
bool Invalid = false;
- if (Args.size() != NumArgsInProto)
+ if (Args.size() != NumParams)
// Use default arguments for missing arguments
- NumArgsToCheck = NumArgsInProto;
+ NumArgsToCheck = NumParams;
unsigned ArgIx = 0;
// Continue to check argument types (even if we have too few/many args).
- for (unsigned i = FirstProtoArg; i != NumArgsToCheck; i++) {
- QualType ProtoArgType = Proto->getArgType(i);
+ for (unsigned i = FirstParam; i != NumArgsToCheck; i++) {
+ QualType ProtoArgType = Proto->getParamType(i);
Expr *Arg;
ParmVarDecl *Param;
@@ -4195,11 +4204,12 @@
(!Param || !Param->hasAttr<CFConsumedAttr>()))
CFAudited = true;
- InitializedEntity Entity = Param ?
- InitializedEntity::InitializeParameter(Context, Param, ProtoArgType)
- : InitializedEntity::InitializeParameter(Context, ProtoArgType,
- Proto->isArgConsumed(i));
-
+ InitializedEntity Entity =
+ Param ? InitializedEntity::InitializeParameter(Context, Param,
+ ProtoArgType)
+ : InitializedEntity::InitializeParameter(
+ Context, ProtoArgType, Proto->isParamConsumed(i));
+
// Remember that parameter belongs to a CF audited API.
if (CFAudited)
Entity.setParameterCFAudited();
@@ -4240,8 +4250,8 @@
if (CallType != VariadicDoesNotApply) {
// Assume that extern "C" functions with variadic arguments that
// return __unknown_anytype aren't *really* variadic.
- if (Proto->getResultType() == Context.UnknownAnyTy &&
- FDecl && FDecl->isExternC()) {
+ if (Proto->getReturnType() == Context.UnknownAnyTy && FDecl &&
+ FDecl->isExternC()) {
for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) {
QualType paramType; // ignored
ExprResult arg = checkUnknownAnyArg(CallLoc, Args[i], paramType);
@@ -4494,6 +4504,21 @@
else if (isa<MemberExpr>(NakedFn))
NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
+ if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(NDecl)) {
+ if (FD->hasAttr<EnableIfAttr>()) {
+ if (const EnableIfAttr *Attr = CheckEnableIf(FD, ArgExprs, true)) {
+ Diag(Fn->getLocStart(),
+ isa<CXXMethodDecl>(FD) ?
+ diag::err_ovl_no_viable_member_function_in_call :
+ diag::err_ovl_no_viable_function_in_call)
+ << FD << FD->getSourceRange();
+ Diag(FD->getLocation(),
+ diag::note_ovl_candidate_disabled_by_enable_if_attr)
+ << Attr->getCond()->getSourceRange() << Attr->getMessage();
+ }
+ }
+ }
+
return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc,
ExecConfig, IsExecConfig);
}
@@ -4573,7 +4598,7 @@
Result = ImpCastExprToType(Fn, Context.getPointerType(FDecl->getType()),
CK_BuiltinFnToFnPtr).take();
} else {
- Result = UsualUnaryConversions(Fn);
+ Result = CallExprUnaryConversions(Fn);
}
if (Result.isInvalid())
return ExprError();
@@ -4629,7 +4654,7 @@
<< FDecl->getName() << Fn->getSourceRange());
// CUDA: Kernel function must have 'void' return type
- if (!FuncT->getResultType()->isVoidType())
+ if (!FuncT->getReturnType()->isVoidType())
return ExprError(Diag(LParenLoc, diag::err_kern_type_not_void_return)
<< Fn->getType() << Fn->getSourceRange());
} else {
@@ -4641,14 +4666,13 @@
}
// Check for a valid return type
- if (CheckCallReturnType(FuncT->getResultType(),
- Fn->getLocStart(), TheCall,
+ if (CheckCallReturnType(FuncT->getReturnType(), Fn->getLocStart(), TheCall,
FDecl))
return ExprError();
// We know the result type of the call, set it.
TheCall->setType(FuncT->getCallResultType(Context));
- TheCall->setValueKind(Expr::getValueKindForType(FuncT->getResultType()));
+ TheCall->setValueKind(Expr::getValueKindForType(FuncT->getReturnType()));
const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT);
if (Proto) {
@@ -4679,11 +4703,9 @@
for (unsigned i = 0, e = Args.size(); i != e; i++) {
Expr *Arg = Args[i];
- if (Proto && i < Proto->getNumArgs()) {
- InitializedEntity Entity
- = InitializedEntity::InitializeParameter(Context,
- Proto->getArgType(i),
- Proto->isArgConsumed(i));
+ if (Proto && i < Proto->getNumParams()) {
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ Context, Proto->getParamType(i), Proto->isParamConsumed(i));
ExprResult ArgE = PerformCopyInitialization(Entity,
SourceLocation(),
Owned(Arg));
@@ -4876,8 +4898,13 @@
case Type::STK_BlockPointer:
case Type::STK_ObjCObjectPointer:
switch (DestTy->getScalarTypeKind()) {
- case Type::STK_CPointer:
+ case Type::STK_CPointer: {
+ unsigned SrcAS = SrcTy->getPointeeType().getAddressSpace();
+ unsigned DestAS = DestTy->getPointeeType().getAddressSpace();
+ if (SrcAS != DestAS)
+ return CK_AddressSpaceConversion;
return CK_BitCast;
+ }
case Type::STK_BlockPointer:
return (SrcKind == Type::STK_BlockPointer
? CK_BitCast : CK_AnyPointerToBlockPointerCast);
@@ -5020,12 +5047,55 @@
llvm_unreachable("Unhandled scalar cast");
}
+static bool breakDownVectorType(QualType type, uint64_t &len,
+ QualType &eltType) {
+ // Vectors are simple.
+ if (const VectorType *vecType = type->getAs<VectorType>()) {
+ len = vecType->getNumElements();
+ eltType = vecType->getElementType();
+ assert(eltType->isScalarType());
+ return true;
+ }
+
+ // We allow lax conversion to and from non-vector types, but only if
+ // they're real types (i.e. non-complex, non-pointer scalar types).
+ if (!type->isRealType()) return false;
+
+ len = 1;
+ eltType = type;
+ return true;
+}
+
+static bool VectorTypesMatch(Sema &S, QualType srcTy, QualType destTy) {
+ uint64_t srcLen, destLen;
+ QualType srcElt, destElt;
+ if (!breakDownVectorType(srcTy, srcLen, srcElt)) return false;
+ if (!breakDownVectorType(destTy, destLen, destElt)) return false;
+
+ // ASTContext::getTypeSize will return the size rounded up to a
+ // power of 2, so instead of using that, we need to use the raw
+ // element size multiplied by the element count.
+ uint64_t srcEltSize = S.Context.getTypeSize(srcElt);
+ uint64_t destEltSize = S.Context.getTypeSize(destElt);
+
+ return (srcLen * srcEltSize == destLen * destEltSize);
+}
+
+/// Is this a legal conversion between two known vector types?
+bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) {
+ assert(destTy->isVectorType() || srcTy->isVectorType());
+
+ if (!Context.getLangOpts().LaxVectorConversions)
+ return false;
+ return VectorTypesMatch(*this, srcTy, destTy);
+}
+
bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
CastKind &Kind) {
assert(VectorTy->isVectorType() && "Not a vector type!");
if (Ty->isVectorType() || Ty->isIntegerType()) {
- if (Context.getTypeSize(VectorTy) != Context.getTypeSize(Ty))
+ if (!VectorTypesMatch(*this, Ty, VectorTy))
return Diag(R.getBegin(),
Ty->isVectorType() ?
diag::err_invalid_conversion_between_vectors :
@@ -5051,7 +5121,7 @@
// In OpenCL, casts between vectors of different types are not allowed.
// (See OpenCL 6.2).
if (SrcTy->isVectorType()) {
- if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy)
+ if (!VectorTypesMatch(*this, SrcTy, DestTy)
|| (getLangOpts().OpenCL &&
(DestTy.getCanonicalType() != SrcTy.getCanonicalType()))) {
Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
@@ -5137,6 +5207,10 @@
CastExpr = Result.take();
}
+ if (getLangOpts().CPlusPlus && !castType->isVoidType() &&
+ !getSourceManager().isInSystemMacro(LParenLoc))
+ Diag(LParenLoc, diag::warn_old_style_cast) << CastExpr->getSourceRange();
+
return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, CastExpr);
}
@@ -5971,15 +6045,16 @@
// get the "pointed to" type (ignoring qualifiers at the top level)
const Type *lhptee, *rhptee;
Qualifiers lhq, rhq;
- llvm::tie(lhptee, lhq) = cast<PointerType>(LHSType)->getPointeeType().split();
- llvm::tie(rhptee, rhq) = cast<PointerType>(RHSType)->getPointeeType().split();
+ std::tie(lhptee, lhq) =
+ cast<PointerType>(LHSType)->getPointeeType().split().asPair();
+ std::tie(rhptee, rhq) =
+ cast<PointerType>(RHSType)->getPointeeType().split().asPair();
Sema::AssignConvertType ConvTy = Sema::Compatible;
// C99 6.5.16.1p1: This following citation is common to constraints
// 3 & 4 (below). ...and the type *pointed to* by the left has all the
// qualifiers of the type *pointed to* by the right;
- Qualifiers lq;
// As a special case, 'non-__weak A *' -> 'non-__weak const *' is okay.
if (lhq.getObjCLifetime() != rhq.getObjCLifetime() &&
@@ -6257,8 +6332,7 @@
// If we are allowing lax vector conversions, and LHS and RHS are both
// vectors, the total size only needs to be the same. This is a bitcast;
// no bits are changed but the result type is different.
- if (getLangOpts().LaxVectorConversions &&
- (Context.getTypeSize(LHSType) == Context.getTypeSize(RHSType))) {
+ if (isLaxVectorConversion(RHSType, LHSType)) {
Kind = CK_BitCast;
return IncompatibleVectors;
}
@@ -6480,9 +6554,7 @@
RecordDecl *UD = UT->getDecl();
FieldDecl *InitField = 0;
// It's compatible if the expression matches any of the fields.
- for (RecordDecl::field_iterator it = UD->field_begin(),
- itend = UD->field_end();
- it != itend; ++it) {
+ for (auto *it : UD->fields()) {
if (it->getType()->isPointerType()) {
// If the transparent union contains a pointer type, we allow:
// 1) void pointer
@@ -6490,7 +6562,7 @@
if (RHSType->isPointerType())
if (RHSType->castAs<PointerType>()->getPointeeType()->isVoidType()) {
RHS = ImpCastExprToType(RHS.take(), it->getType(), CK_BitCast);
- InitField = *it;
+ InitField = it;
break;
}
@@ -6498,7 +6570,7 @@
Expr::NPC_ValueDependentIsNull)) {
RHS = ImpCastExprToType(RHS.take(), it->getType(),
CK_NullToPointer);
- InitField = *it;
+ InitField = it;
break;
}
}
@@ -6507,7 +6579,7 @@
if (CheckAssignmentConstraints(it->getType(), RHS, Kind)
== Compatible) {
RHS = ImpCastExprToType(RHS.take(), it->getType(), Kind);
- InitField = *it;
+ InitField = it;
break;
}
}
@@ -6603,6 +6675,14 @@
if (getLangOpts().ObjCAutoRefCount)
CheckObjCARCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion,
DiagnoseCFAudited);
+ if (getLangOpts().ObjC1 &&
+ (CheckObjCBridgeRelatedConversions(E->getLocStart(),
+ LHSType, E->getType(), E) ||
+ ConversionToObjCStringLiteralCheck(LHSType, E))) {
+ RHS = Owned(E);
+ return Compatible;
+ }
+
RHS = ImpCastExprToType(E, Ty, Kind);
}
return result;
@@ -6616,6 +6696,53 @@
return QualType();
}
+/// Try to convert a value of non-vector type to a vector type by converting
+/// the type to the element type of the vector and then performing a splat.
+/// If the language is OpenCL, we only use conversions that promote scalar
+/// rank; for C, Obj-C, and C++ we allow any real scalar conversion except
+/// for float->int.
+///
+/// \param scalar - if non-null, actually perform the conversions
+/// \return true if the operation fails (but without diagnosing the failure)
+static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar,
+ QualType scalarTy,
+ QualType vectorEltTy,
+ QualType vectorTy) {
+ // The conversion to apply to the scalar before splatting it,
+ // if necessary.
+ CastKind scalarCast = CK_Invalid;
+
+ if (vectorEltTy->isIntegralType(S.Context)) {
+ if (!scalarTy->isIntegralType(S.Context))
+ return true;
+ if (S.getLangOpts().OpenCL &&
+ S.Context.getIntegerTypeOrder(vectorEltTy, scalarTy) < 0)
+ return true;
+ scalarCast = CK_IntegralCast;
+ } else if (vectorEltTy->isRealFloatingType()) {
+ if (scalarTy->isRealFloatingType()) {
+ if (S.getLangOpts().OpenCL &&
+ S.Context.getFloatingTypeOrder(vectorEltTy, scalarTy) < 0)
+ return true;
+ scalarCast = CK_FloatingCast;
+ }
+ else if (scalarTy->isIntegralType(S.Context))
+ scalarCast = CK_IntegralToFloating;
+ else
+ return true;
+ } else {
+ return true;
+ }
+
+ // Adjust scalar if desired.
+ if (scalar) {
+ if (scalarCast != CK_Invalid)
+ *scalar = S.ImpCastExprToType(scalar->take(), vectorEltTy, scalarCast);
+ *scalar = S.ImpCastExprToType(scalar->take(), vectorTy, CK_VectorSplat);
+ }
+ return false;
+}
+
QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, bool IsCompAssign) {
if (!IsCompAssign) {
@@ -6629,19 +6756,21 @@
// For conversion purposes, we ignore any qualifiers.
// For example, "const float" and "float" are equivalent.
- QualType LHSType =
- Context.getCanonicalType(LHS.get()->getType()).getUnqualifiedType();
- QualType RHSType =
- Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType();
+ QualType LHSType = LHS.get()->getType().getUnqualifiedType();
+ QualType RHSType = RHS.get()->getType().getUnqualifiedType();
// If the vector types are identical, return.
- if (LHSType == RHSType)
+ if (Context.hasSameType(LHSType, RHSType))
return LHSType;
- // Handle the case of equivalent AltiVec and GCC vector types
- if (LHSType->isVectorType() && RHSType->isVectorType() &&
+ const VectorType *LHSVecType = LHSType->getAs<VectorType>();
+ const VectorType *RHSVecType = RHSType->getAs<VectorType>();
+ assert(LHSVecType || RHSVecType);
+
+ // If we have compatible AltiVec and GCC vector types, use the AltiVec type.
+ if (LHSVecType && RHSVecType &&
Context.areCompatibleVectorTypes(LHSType, RHSType)) {
- if (LHSType->isExtVectorType()) {
+ if (isa<ExtVectorType>(LHSVecType)) {
RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
return LHSType;
}
@@ -6651,62 +6780,43 @@
return RHSType;
}
- if (getLangOpts().LaxVectorConversions &&
- Context.getTypeSize(LHSType) == Context.getTypeSize(RHSType)) {
- // If we are allowing lax vector conversions, and LHS and RHS are both
- // vectors, the total size only needs to be the same. This is a
- // bitcast; no bits are changed but the result type is different.
- // FIXME: Should we really be allowing this?
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
- return LHSType;
+ // If there's an ext-vector type and a scalar, try to convert the scalar to
+ // the vector element type and splat.
+ if (!RHSVecType && isa<ExtVectorType>(LHSVecType)) {
+ if (!tryVectorConvertAndSplat(*this, &RHS, RHSType,
+ LHSVecType->getElementType(), LHSType))
+ return LHSType;
+ }
+ if (!LHSVecType && isa<ExtVectorType>(RHSVecType)) {
+ if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? 0 : &LHS), LHSType,
+ RHSVecType->getElementType(), RHSType))
+ return RHSType;
}
- // Canonicalize the ExtVector to the LHS, remember if we swapped so we can
- // swap back (so that we don't reverse the inputs to a subtract, for instance.
- bool swapped = false;
- if (RHSType->isExtVectorType() && !IsCompAssign) {
- swapped = true;
- std::swap(RHS, LHS);
- std::swap(RHSType, LHSType);
+ // If we're allowing lax vector conversions, only the total (data) size
+ // needs to be the same.
+ // FIXME: Should we really be allowing this?
+ // FIXME: We really just pick the LHS type arbitrarily?
+ if (isLaxVectorConversion(RHSType, LHSType)) {
+ QualType resultType = LHSType;
+ RHS = ImpCastExprToType(RHS.take(), resultType, CK_BitCast);
+ return resultType;
}
- // Handle the case of an ext vector and scalar.
- if (const ExtVectorType *LV = LHSType->getAs<ExtVectorType>()) {
- QualType EltTy = LV->getElementType();
- if (EltTy->isIntegralType(Context) && RHSType->isIntegralType(Context)) {
- int order = Context.getIntegerTypeOrder(EltTy, RHSType);
- if (order > 0)
- RHS = ImpCastExprToType(RHS.take(), EltTy, CK_IntegralCast);
- if (order >= 0) {
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat);
- if (swapped) std::swap(RHS, LHS);
- return LHSType;
- }
- }
- 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;
- }
- }
+ // Okay, the expression is invalid.
+
+ // If there's a non-vector, non-real operand, diagnose that.
+ if ((!RHSVecType && !RHSType->isRealType()) ||
+ (!LHSVecType && !LHSType->isRealType())) {
+ Diag(Loc, diag::err_typecheck_vector_not_convertable_non_scalar)
+ << LHSType << RHSType
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ return QualType();
}
- // Vectors of different size or scalar and non-ext-vector are errors.
- if (swapped) std::swap(RHS, LHS);
+ // Otherwise, use the generic diagnostic.
Diag(Loc, diag::err_typecheck_vector_not_convertable)
- << LHS.get()->getType() << RHS.get()->getType()
+ << LHSType << RHSType
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
@@ -7491,8 +7601,8 @@
QualType T = Method->param_begin()[0]->getType();
if (!T->isObjCObjectPointerType())
return false;
-
- QualType R = Method->getResultType();
+
+ QualType R = Method->getReturnType();
if (!R->isScalarType())
return false;
@@ -7769,10 +7879,22 @@
return ResultTy;
}
- bool LHSIsNull = LHS.get()->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNull);
- bool RHSIsNull = RHS.get()->isNullPointerConstant(Context,
- Expr::NPC_ValueDependentIsNull);
+ const Expr::NullPointerConstantKind LHSNullKind =
+ LHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull);
+ const Expr::NullPointerConstantKind RHSNullKind =
+ RHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull);
+ bool LHSIsNull = LHSNullKind != Expr::NPCK_NotNull;
+ bool RHSIsNull = RHSNullKind != Expr::NPCK_NotNull;
+
+ if (!IsRelational && LHSIsNull != RHSIsNull) {
+ bool IsEquality = Opc == BO_EQ;
+ if (RHSIsNull)
+ DiagnoseAlwaysNonNullPointer(LHS.get(), RHSNullKind, IsEquality,
+ RHS.get()->getSourceRange());
+ else
+ DiagnoseAlwaysNonNullPointer(RHS.get(), LHSNullKind, IsEquality,
+ LHS.get()->getSourceRange());
+ }
// All of the following pointer-related warnings are GCC extensions, except
// when handling null pointer constants.
@@ -7830,10 +7952,14 @@
diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, /*isError*/false);
}
if (LCanPointeeTy != RCanPointeeTy) {
+ unsigned AddrSpaceL = LCanPointeeTy.getAddressSpace();
+ unsigned AddrSpaceR = RCanPointeeTy.getAddressSpace();
+ CastKind Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion
+ : CK_BitCast;
if (LHSIsNull && !RHSIsNull)
- LHS = ImpCastExprToType(LHS.take(), RHSType, CK_BitCast);
+ LHS = ImpCastExprToType(LHS.take(), RHSType, Kind);
else
- RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
+ RHS = ImpCastExprToType(RHS.take(), LHSType, Kind);
}
return ResultTy;
}
@@ -8730,6 +8856,12 @@
// Make sure to ignore parentheses in subsequent checks
Expr *op = OrigOp.get()->IgnoreParens();
+ // OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
+ if (LangOpts.OpenCL && op->getType()->isFunctionType()) {
+ Diag(op->getExprLoc(), diag::err_opencl_taking_function_address);
+ return QualType();
+ }
+
if (getLangOpts().C99) {
// Implement C99-only parts of addressof rules.
if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
@@ -8793,8 +8925,11 @@
if (isa<CXXDestructorDecl>(MD))
Diag(OpLoc, diag::err_typecheck_addrof_dtor) << op->getSourceRange();
- return Context.getMemberPointerType(op->getType(),
- Context.getTypeDeclType(MD->getParent()).getTypePtr());
+ QualType MPTy = Context.getMemberPointerType(
+ op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr());
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ RequireCompleteType(OpLoc, MPTy, 0);
+ return MPTy;
} 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
@@ -8842,8 +8977,13 @@
while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion())
Ctx = Ctx->getParent();
- return Context.getMemberPointerType(op->getType(),
- Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+
+ QualType MPTy = Context.getMemberPointerType(
+ op->getType(),
+ Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ RequireCompleteType(OpLoc, MPTy, 0);
+ return MPTy;
}
}
} else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl))
@@ -9641,7 +9781,7 @@
if (resultType->isDependentType())
break;
- if (resultType->isScalarType()) {
+ if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) {
// C99 6.5.3.3p1: ok, fallthrough;
if (Context.getLangOpts().CPlusPlus) {
// C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9:
@@ -9872,7 +10012,7 @@
// example, it is not possible to goto into a stmt expression apparently.
// More semantic analysis is needed.
- // If there are sub stmts in the compound stmt, take the type of the last one
+ // If there are sub-stmts in the compound stmt, take the type of the last one
// as the type of the stmtexpr.
QualType Ty = Context.VoidTy;
bool StmtExprMayBindToTemp = false;
@@ -10092,12 +10232,10 @@
}
if (IndirectMemberDecl) {
- for (IndirectFieldDecl::chain_iterator FI =
- IndirectMemberDecl->chain_begin(),
- FEnd = IndirectMemberDecl->chain_end(); FI != FEnd; FI++) {
- assert(isa<FieldDecl>(*FI));
+ for (auto *FI : IndirectMemberDecl->chain()) {
+ assert(isa<FieldDecl>(FI));
Comps.push_back(OffsetOfNode(OC.LocStart,
- cast<FieldDecl>(*FI), OC.LocEnd));
+ cast<FieldDecl>(FI), OC.LocEnd));
}
} else
Comps.push_back(OffsetOfNode(OC.LocStart, MemberDecl, OC.LocEnd));
@@ -10241,7 +10379,7 @@
ExplicitSignature.getLocalRangeEnd()) {
// This would be much cheaper if we stored TypeLocs instead of
// TypeSourceInfos.
- TypeLoc Result = ExplicitSignature.getResultLoc();
+ TypeLoc Result = ExplicitSignature.getReturnLoc();
unsigned Size = Result.getFullDataSize();
Sig = Context.CreateTypeSourceInfo(Result.getType(), Size);
Sig->getTypeLoc().initializeFullCopy(Result, Size);
@@ -10254,7 +10392,7 @@
CurBlock->FunctionType = T;
const FunctionType *Fn = T->getAs<FunctionType>();
- QualType RetTy = Fn->getResultType();
+ QualType RetTy = Fn->getReturnType();
bool isVariadic =
(isa<FunctionProtoType>(Fn) && cast<FunctionProtoType>(Fn)->isVariadic());
@@ -10273,8 +10411,8 @@
// Push block parameters from the declarator if we had them.
SmallVector<ParmVarDecl*, 8> Params;
if (ExplicitSignature) {
- for (unsigned I = 0, E = ExplicitSignature.getNumArgs(); I != E; ++I) {
- ParmVarDecl *Param = ExplicitSignature.getArg(I);
+ for (unsigned I = 0, E = ExplicitSignature.getNumParams(); I != E; ++I) {
+ ParmVarDecl *Param = ExplicitSignature.getParam(I);
if (Param->getIdentifier() == 0 &&
!Param->isImplicit() &&
!Param->isInvalidDecl() &&
@@ -10286,12 +10424,9 @@
// Fake up parameter variables if we have a typedef, like
// ^ fntype { ... }
} else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) {
- for (FunctionProtoType::arg_type_iterator
- I = Fn->arg_type_begin(), E = Fn->arg_type_end(); I != E; ++I) {
- ParmVarDecl *Param =
- BuildParmVarDeclForTypedef(CurBlock->TheDecl,
- ParamInfo.getLocStart(),
- *I);
+ for (const auto &I : Fn->param_types()) {
+ ParmVarDecl *Param = BuildParmVarDeclForTypedef(
+ CurBlock->TheDecl, ParamInfo.getLocStart(), I);
Params.push_back(Param);
}
}
@@ -10308,15 +10443,14 @@
ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
// 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);
+ for (auto AI : CurBlock->TheDecl->params()) {
+ AI->setOwningFunction(CurBlock->TheDecl);
// If this has an identifier, add it to the scope stack.
- if ((*AI)->getIdentifier()) {
- CheckShadow(CurBlock->TheScope, *AI);
+ if (AI->getIdentifier()) {
+ CheckShadow(CurBlock->TheScope, AI);
- PushOnScopeChains(*AI, CurBlock->TheScope);
+ PushOnScopeChains(AI, CurBlock->TheScope);
}
}
}
@@ -10358,7 +10492,7 @@
if (!BSI->ReturnType.isNull())
RetTy = BSI->ReturnType;
- bool NoReturn = BSI->TheDecl->getAttr<NoReturnAttr>();
+ bool NoReturn = BSI->TheDecl->hasAttr<NoReturnAttr>();
QualType BlockTy;
// Set the captured variables on the block.
@@ -10390,7 +10524,7 @@
// Otherwise, if we don't need to change anything about the function type,
// preserve its sugar structure.
- } else if (FTy->getResultType() == RetTy &&
+ } else if (FTy->getReturnType() == RetTy &&
(!NoReturn || FTy->getNoReturnAttr())) {
BlockTy = BSI->FunctionType;
@@ -10400,7 +10534,7 @@
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals = 0; // FIXME: silently?
EPI.ExtInfo = Ext;
- BlockTy = Context.getFunctionType(RetTy, FPT->getArgTypes(), EPI);
+ BlockTy = Context.getFunctionType(RetTy, FPT->getParamTypes(), EPI);
}
// If we don't have a function type, just build one from nothing.
@@ -10442,10 +10576,8 @@
// It also gets a branch-protected scope if any of the captured
// variables needs destruction.
- for (BlockDecl::capture_const_iterator
- ci = Result->getBlockDecl()->capture_begin(),
- ce = Result->getBlockDecl()->capture_end(); ci != ce; ++ci) {
- const VarDecl *var = ci->getVariable();
+ for (const auto &CI : Result->getBlockDecl()->captures()) {
+ const VarDecl *var = CI.getVariable();
if (var->getType().isDestructedType() != QualType::DK_none) {
getCurFunction()->setHasBranchProtectedScope();
break;
@@ -10567,38 +10699,37 @@
return Owned(new (Context) GNUNullExpr(Ty, TokenLoc));
}
-static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
- Expr *SrcExpr, FixItHint &Hint,
- bool &IsNSString) {
- if (!SemaRef.getLangOpts().ObjC1)
- return;
+bool
+Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp) {
+ if (!getLangOpts().ObjC1)
+ return false;
const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();
if (!PT)
- return;
+ return false;
- // Check if the destination is of type 'id'.
if (!PT->isObjCIdType()) {
// Check if the destination is the 'NSString' interface.
const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
if (!ID || !ID->getIdentifier()->isStr("NSString"))
- return;
- IsNSString = true;
+ return false;
}
-
+
// Ignore any parens, implicit casts (should only be
// array-to-pointer decays), and not-so-opaque values. The last is
// important for making this trigger for property assignments.
- SrcExpr = SrcExpr->IgnoreParenImpCasts();
+ Expr *SrcExpr = Exp->IgnoreParenImpCasts();
if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(SrcExpr))
if (OV->getSourceExpr())
SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts();
StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr);
if (!SL || !SL->isAscii())
- return;
-
- Hint = FixItHint::CreateInsertion(SL->getLocStart(), "@");
+ return false;
+ Diag(SL->getLocStart(), diag::err_missing_atsign_prefix)
+ << FixItHint::CreateInsertion(SL->getLocStart(), "@");
+ Exp = BuildObjCStringLiteral(SL->getLocStart(), SL).take();
+ return true;
}
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
@@ -10617,7 +10748,6 @@
ConversionFixItGenerator ConvHints;
bool MayHaveConvFixit = false;
bool MayHaveFunctionDiff = false;
- bool IsNSString = false;
switch (ConvTy) {
case Compatible:
@@ -10635,7 +10765,6 @@
MayHaveConvFixit = true;
break;
case IncompatiblePointer:
- MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint, IsNSString);
DiagKind =
(Action == AA_Passing_CFAudited ?
diag::err_arc_typecheck_convert_incompatible_pointer :
@@ -10649,8 +10778,6 @@
SrcType = SrcType.getUnqualifiedType();
DstType = DstType.getUnqualifiedType();
}
- else if (IsNSString && !Hint.isNull())
- DiagKind = diag::warn_missing_atsign_prefix;
MayHaveConvFixit = true;
break;
case IncompatiblePointerSign:
@@ -10784,7 +10911,7 @@
llvm::APSInt *Result) {
class SimpleICEDiagnoser : public VerifyICEDiagnoser {
public:
- virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) {
+ void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
S.Diag(Loc, diag::err_expr_not_ice) << S.LangOpts.CPlusPlus << SR;
}
} Diagnoser;
@@ -10803,7 +10930,7 @@
IDDiagnoser(unsigned DiagID)
: VerifyICEDiagnoser(DiagID == 0), DiagID(DiagID) { }
- virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) {
+ void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
S.Diag(Loc, DiagID) << SR;
}
} Diagnoser(DiagID);
@@ -10835,40 +10962,40 @@
: ICEConvertDiagnoser(/*AllowScopedEnumerations*/false,
Silent, true) {}
- virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
- QualType T) {
+ SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) override {
return S.Diag(Loc, diag::err_ice_not_integral) << T;
}
- virtual SemaDiagnosticBuilder diagnoseIncomplete(
- Sema &S, SourceLocation Loc, QualType T) {
+ SemaDiagnosticBuilder diagnoseIncomplete(
+ Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_ice_incomplete_type) << T;
}
- virtual SemaDiagnosticBuilder diagnoseExplicitConv(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
return S.Diag(Loc, diag::err_ice_explicit_conversion) << T << ConvTy;
}
- virtual SemaDiagnosticBuilder noteExplicitConv(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ SemaDiagnosticBuilder noteExplicitConv(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
<< ConvTy->isEnumeralType() << ConvTy;
}
- virtual SemaDiagnosticBuilder diagnoseAmbiguous(
- Sema &S, SourceLocation Loc, QualType T) {
+ SemaDiagnosticBuilder diagnoseAmbiguous(
+ Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T;
}
- virtual SemaDiagnosticBuilder noteAmbiguous(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ SemaDiagnosticBuilder noteAmbiguous(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
<< ConvTy->isEnumeralType() << ConvTy;
}
- virtual SemaDiagnosticBuilder diagnoseConversion(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ SemaDiagnosticBuilder diagnoseConversion(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
llvm_unreachable("conversion functions are permitted");
}
} ConvertDiagnoser(Diagnoser.Suppress);
@@ -11174,37 +11301,34 @@
// Note that this declaration has been used.
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Func)) {
+ Constructor = cast<CXXConstructorDecl>(Constructor->getFirstDecl());
if (Constructor->isDefaulted() && !Constructor->isDeleted()) {
if (Constructor->isDefaultConstructor()) {
if (Constructor->isTrivial())
return;
- if (!Constructor->isUsed(false))
- DefineImplicitDefaultConstructor(Loc, Constructor);
+ DefineImplicitDefaultConstructor(Loc, Constructor);
} else if (Constructor->isCopyConstructor()) {
- if (!Constructor->isUsed(false))
- DefineImplicitCopyConstructor(Loc, Constructor);
+ DefineImplicitCopyConstructor(Loc, Constructor);
} else if (Constructor->isMoveConstructor()) {
- if (!Constructor->isUsed(false))
- DefineImplicitMoveConstructor(Loc, Constructor);
+ DefineImplicitMoveConstructor(Loc, Constructor);
}
} else if (Constructor->getInheritedConstructor()) {
- if (!Constructor->isUsed(false))
- DefineInheritingConstructor(Loc, Constructor);
+ DefineInheritingConstructor(Loc, Constructor);
}
MarkVTableUsed(Loc, Constructor->getParent());
} else if (CXXDestructorDecl *Destructor =
dyn_cast<CXXDestructorDecl>(Func)) {
- if (Destructor->isDefaulted() && !Destructor->isDeleted() &&
- !Destructor->isUsed(false))
+ Destructor = cast<CXXDestructorDecl>(Destructor->getFirstDecl());
+ if (Destructor->isDefaulted() && !Destructor->isDeleted())
DefineImplicitDestructor(Loc, Destructor);
if (Destructor->isVirtual())
MarkVTableUsed(Loc, Destructor->getParent());
} else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(Func)) {
- if (MethodDecl->isDefaulted() && !MethodDecl->isDeleted() &&
- MethodDecl->isOverloadedOperator() &&
+ if (MethodDecl->isOverloadedOperator() &&
MethodDecl->getOverloadedOperator() == OO_Equal) {
- if (!MethodDecl->isUsed(false)) {
+ MethodDecl = cast<CXXMethodDecl>(MethodDecl->getFirstDecl());
+ if (MethodDecl->isDefaulted() && !MethodDecl->isDeleted()) {
if (MethodDecl->isCopyAssignmentOperator())
DefineImplicitCopyAssignment(Loc, MethodDecl);
else
@@ -11212,7 +11336,8 @@
}
} else if (isa<CXXConversionDecl>(MethodDecl) &&
MethodDecl->getParent()->isLambda()) {
- CXXConversionDecl *Conversion = cast<CXXConversionDecl>(MethodDecl);
+ CXXConversionDecl *Conversion =
+ cast<CXXConversionDecl>(MethodDecl->getFirstDecl());
if (Conversion->isLambdaToBlockPointerConversion())
DefineImplicitLambdaToBlockPointerConversion(Loc, Conversion);
else
@@ -11276,10 +11401,9 @@
}
} else {
// Walk redefinitions, as some of them may be instantiable.
- for (FunctionDecl::redecl_iterator i(Func->redecls_begin()),
- e(Func->redecls_end()); i != e; ++i) {
+ for (auto i : Func->redecls()) {
if (!i->isUsed(false) && i->isImplicitlyInstantiable())
- MarkFunctionReferenced(Loc, *i);
+ MarkFunctionReferenced(Loc, i);
}
}
@@ -11778,9 +11902,18 @@
return false;
}
- if (S.RequireNonAbstractType(Loc, CaptureType,
- diag::err_capture_of_abstract_type))
- return false;
+ // Make sure that by-copy captures are of a complete and non-abstract type.
+ if (BuildAndDiagnose) {
+ if (!CaptureType->isDependentType() &&
+ S.RequireCompleteType(Loc, CaptureType,
+ diag::err_capture_of_incomplete_type,
+ Var->getDeclName()))
+ return false;
+
+ if (S.RequireNonAbstractType(Loc, CaptureType,
+ diag::err_capture_of_abstract_type))
+ return false;
+ }
}
// Capture this variable in the lambda.
@@ -12069,42 +12202,39 @@
"Invalid Expr argument to DoMarkVarDeclReferenced");
Var->setReferenced();
- // 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 the context is not potentially evaluated, this is not an odr-use and
+ // does not trigger instantiation.
if (!IsPotentiallyEvaluatedContext(SemaRef)) {
+ if (SemaRef.isUnevaluatedContext())
+ return;
- if (SemaRef.isUnevaluatedContext()) return;
+ // If we don't yet know whether this context is going to end up being an
+ // evaluated context, and we're referencing a variable from an enclosing
+ // scope, add a potential capture.
+ //
+ // FIXME: Is this necessary? These contexts are only used for default
+ // arguments, where local variables can't be used.
+ const bool RefersToEnclosingScope =
+ (SemaRef.CurContext != Var->getDeclContext() &&
+ Var->getDeclContext()->isFunctionOrMethod() &&
+ Var->hasLocalStorage());
+ if (!RefersToEnclosingScope)
+ 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
+ // 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;
+ if (!Var->getType()->isReferenceType() ||
+ !IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context))
+ LSI->addPotentialCapture(E->IgnoreParens());
+ }
+ return;
}
VarTemplateSpecializationDecl *VarSpec =
@@ -12112,10 +12242,10 @@
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.
+ // Perform 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;
@@ -12155,6 +12285,7 @@
}
}
}
+
// 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)
@@ -12164,14 +12295,11 @@
// 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.
if (E && IsVariableAConstantExpression(Var, SemaRef.Context)) {
- // A reference initialized by a constant expression can never be
+ // 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
+ } else
MarkVarDeclODRUsed(Var, Loc, SemaRef, /*MaxFunctionScopeIndex ptr*/0);
}
@@ -12447,8 +12575,8 @@
public:
CallReturnIncompleteDiagnoser(FunctionDecl *FD, CallExpr *CE)
: FD(FD), CE(CE) { }
-
- virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
if (!FD) {
S.Diag(Loc, diag::err_call_incomplete_return)
<< T << CE->getSourceRange();
@@ -12825,7 +12953,7 @@
// 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();
+ ArrayRef<QualType> ParamTypes = Proto->getParamTypes();
SmallVector<QualType, 8> ArgTypes;
if (ParamTypes.empty() && Proto->isVariadic()) { // the special case
ArgTypes.reserve(E->getNumArgs());
@@ -12882,8 +13010,8 @@
// Rewrite the method result type if available.
if (ObjCMethodDecl *Method = E->getMethodDecl()) {
- assert(Method->getResultType() == S.Context.UnknownAnyTy);
- Method->setResultType(DestType);
+ assert(Method->getReturnType() == S.Context.UnknownAnyTy);
+ Method->setReturnType(DestType);
}
// Change the type of the message.
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 07e4657..8b9c0e2 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -117,7 +117,7 @@
SearchType = GetTypeFromParser(ObjectTypePtr);
if (SS.isSet()) {
- NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+ NestedNameSpecifier *NNS = SS.getScopeRep();
bool AlreadySearched = false;
bool LookAtPrefix = true;
@@ -209,7 +209,8 @@
Context.hasSameUnqualifiedType(T, SearchType)) {
// We found our type!
- return ParsedType::make(T);
+ return CreateParsedType(T,
+ Context.getTrivialTypeSourceInfo(T, NameLoc));
}
if (!SearchType.isNull())
@@ -245,7 +246,9 @@
= dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
if (Spec->getSpecializedTemplate()->getCanonicalDecl() ==
Template->getCanonicalDecl())
- return ParsedType::make(MemberOfType);
+ return CreateParsedType(
+ MemberOfType,
+ Context.getTrivialTypeSourceInfo(MemberOfType, NameLoc));
}
continue;
@@ -264,7 +267,9 @@
// specialized.
if (TemplateDecl *SpecTemplate = SpecName.getAsTemplateDecl()) {
if (SpecTemplate->getCanonicalDecl() == Template->getCanonicalDecl())
- return ParsedType::make(MemberOfType);
+ return CreateParsedType(
+ MemberOfType,
+ Context.getTrivialTypeSourceInfo(MemberOfType, NameLoc));
continue;
}
@@ -275,7 +280,9 @@
= SpecName.getAsDependentTemplateName()) {
if (DepTemplate->isIdentifier() &&
DepTemplate->getIdentifier() == Template->getIdentifier())
- return ParsedType::make(MemberOfType);
+ return CreateParsedType(
+ MemberOfType,
+ Context.getTrivialTypeSourceInfo(MemberOfType, NameLoc));
continue;
}
@@ -333,6 +340,34 @@
return ParsedType();
}
+bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
+ const UnqualifiedId &Name) {
+ assert(Name.getKind() == UnqualifiedId::IK_LiteralOperatorId);
+
+ if (!SS.isValid())
+ return false;
+
+ switch (SS.getScopeRep()->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ // Per C++11 [over.literal]p2, literal operators can only be declared at
+ // namespace scope. Therefore, this unqualified-id cannot name anything.
+ // Reject it early, because we have no AST representation for this in the
+ // case where the scope is dependent.
+ Diag(Name.getLocStart(), diag::err_literal_operator_id_outside_namespace)
+ << SS.getScopeRep();
+ return true;
+
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ return false;
+ }
+
+ llvm_unreachable("unknown nested name specifier kind");
+}
+
/// \brief Build a C++ typeid expression with a type operand.
ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
SourceLocation TypeidLoc,
@@ -426,7 +461,7 @@
CXXTypeInfoDecl = R.getAsSingle<RecordDecl>();
// Microsoft's typeinfo doesn't have type_info in std but in the global
// namespace if _HAS_EXCEPTIONS is defined to 0. See PR13153.
- if (!CXXTypeInfoDecl && LangOpts.MicrosoftMode) {
+ if (!CXXTypeInfoDecl && LangOpts.MSVCCompat) {
LookupQualifiedName(R, Context.getTranslationUnitDecl());
CXXTypeInfoDecl = R.getAsSingle<RecordDecl>();
}
@@ -1153,14 +1188,15 @@
else if (Initializer && isa<ImplicitValueInitExpr>(Initializer))
HaveCompleteInit = true;
- // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
+ // C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && AllocType->isUndeducedType()) {
if (initStyle == CXXNewExpr::NoInit || NumInits == 0)
return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
<< AllocType << TypeRange);
- if (initStyle == CXXNewExpr::ListInit)
+ if (initStyle == CXXNewExpr::ListInit ||
+ (NumInits == 1 && isa<InitListExpr>(Inits[0])))
return ExprError(Diag(Inits[0]->getLocStart(),
- diag::err_auto_new_requires_parens)
+ diag::err_auto_new_list_init)
<< AllocType << TypeRange);
if (NumInits > 1) {
Expr *FirstBad = Inits[1];
@@ -1225,9 +1261,8 @@
if (ArraySize && !ArraySize->isTypeDependent()) {
ExprResult ConvertedSize;
if (getLangOpts().CPlusPlus1y) {
- unsigned IntWidth = Context.getTargetInfo().getIntWidth();
- assert(IntWidth && "Builtin type of size 0?");
- llvm::APSInt Value(IntWidth);
+ assert(Context.getTargetInfo().getIntWidth() && "Builtin type of size 0?");
+
ConvertedSize = PerformImplicitConversion(ArraySize, Context.getSizeType(),
AA_Converting);
@@ -1245,43 +1280,43 @@
SizeConvertDiagnoser(Expr *ArraySize)
: ICEConvertDiagnoser(/*AllowScopedEnumerations*/false, false, false),
ArraySize(ArraySize) {}
-
- virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
- QualType T) {
+
+ SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) override {
return S.Diag(Loc, diag::err_array_size_not_integral)
<< S.getLangOpts().CPlusPlus11 << T;
}
-
- virtual SemaDiagnosticBuilder diagnoseIncomplete(
- Sema &S, SourceLocation Loc, QualType T) {
+
+ SemaDiagnosticBuilder diagnoseIncomplete(
+ Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_array_size_incomplete_type)
<< T << ArraySize->getSourceRange();
}
-
- virtual SemaDiagnosticBuilder diagnoseExplicitConv(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+
+ SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
return S.Diag(Loc, diag::err_array_size_explicit_conversion) << T << ConvTy;
}
-
- virtual SemaDiagnosticBuilder noteExplicitConv(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+
+ SemaDiagnosticBuilder noteExplicitConv(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_array_size_conversion)
<< ConvTy->isEnumeralType() << ConvTy;
}
-
- virtual SemaDiagnosticBuilder diagnoseAmbiguous(
- Sema &S, SourceLocation Loc, QualType T) {
+
+ SemaDiagnosticBuilder diagnoseAmbiguous(
+ Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_array_size_ambiguous_conversion) << T;
}
-
- virtual SemaDiagnosticBuilder noteAmbiguous(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+
+ SemaDiagnosticBuilder noteAmbiguous(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_array_size_conversion)
<< ConvTy->isEnumeralType() << ConvTy;
}
virtual SemaDiagnosticBuilder diagnoseConversion(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
return S.Diag(Loc,
S.getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_array_size_conversion
@@ -1623,7 +1658,7 @@
// Didn't find a member overload. Look for a global one.
DeclareGlobalNewDelete();
DeclContext *TUDecl = Context.getTranslationUnitDecl();
- bool FallbackEnabled = IsArray && Context.getLangOpts().MicrosoftMode;
+ bool FallbackEnabled = IsArray && Context.getLangOpts().MSVCCompat;
if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, TUDecl,
/*AllowMissing=*/FallbackEnabled, OperatorNew,
/*Diagnose=*/!FallbackEnabled)) {
@@ -1708,8 +1743,8 @@
SmallVector<QualType, 4> ArgTypes;
ArgTypes.push_back(Context.VoidPtrTy);
- for (unsigned I = 1, N = Proto->getNumArgs(); I < N; ++I)
- ArgTypes.push_back(Proto->getArgType(I));
+ for (unsigned I = 1, N = Proto->getNumParams(); I < N; ++I)
+ ArgTypes.push_back(Proto->getParamType(I));
FunctionProtoType::ExtProtoInfo EPI;
EPI.Variadic = Proto->isVariadic();
@@ -1763,7 +1798,7 @@
else
Matches.erase(Matches.begin() + 1);
assert(Matches[0].second->getNumParams() == 2 &&
- "found an unexpected uusal deallocation function");
+ "found an unexpected usual deallocation function");
}
}
@@ -2031,8 +2066,7 @@
if (InitialParam1Type == Param1 &&
(NumParams == 1 || InitialParam2Type == Param2)) {
if (AddMallocAttr && !Func->hasAttr<MallocAttr>())
- Func->addAttr(::new (Context) MallocAttr(SourceLocation(),
- Context));
+ Func->addAttr(MallocAttr::CreateImplicit(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.
@@ -2043,18 +2077,16 @@
}
}
+ FunctionProtoType::ExtProtoInfo EPI;
+
QualType BadAllocType;
bool HasBadAllocExceptionSpec
= (Name.getCXXOverloadedOperator() == OO_New ||
Name.getCXXOverloadedOperator() == OO_Array_New);
- if (HasBadAllocExceptionSpec && !getLangOpts().CPlusPlus11) {
- assert(StdBadAlloc && "Must have std::bad_alloc declared");
- BadAllocType = Context.getTypeDeclType(getStdBadAlloc());
- }
-
- FunctionProtoType::ExtProtoInfo EPI;
if (HasBadAllocExceptionSpec) {
if (!getLangOpts().CPlusPlus11) {
+ BadAllocType = Context.getTypeDeclType(getStdBadAlloc());
+ assert(StdBadAlloc && "Must have std::bad_alloc declared");
EPI.ExceptionSpecType = EST_Dynamic;
EPI.NumExceptions = 1;
EPI.Exceptions = &BadAllocType;
@@ -2075,14 +2107,16 @@
Alloc->setImplicit();
if (AddMallocAttr)
- Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
+ Alloc->addAttr(MallocAttr::CreateImplicit(Context));
ParmVarDecl *ParamDecls[2];
- for (unsigned I = 0; I != NumParams; ++I)
+ for (unsigned I = 0; I != NumParams; ++I) {
ParamDecls[I] = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
SourceLocation(), 0,
Params[I], /*TInfo=*/0,
SC_None, 0);
+ ParamDecls[I]->setImplicit();
+ }
Alloc->setParams(ArrayRef<ParmVarDecl*>(ParamDecls, NumParams));
// FIXME: Also add this declaration to the IdentifierResolver, but
@@ -2125,7 +2159,7 @@
else
Matches.erase(Matches.begin() + 1);
assert(Matches[0]->getNumParams() == NumArgs &&
- "found an unexpected uusal deallocation function");
+ "found an unexpected usual deallocation function");
}
assert(Matches.size() == 1 &&
@@ -2241,7 +2275,7 @@
public:
DeleteConverter() : ContextualImplicitConverter(false, true) {}
- bool match(QualType ConvType) {
+ bool match(QualType ConvType) override {
// FIXME: If we have an operator T* and an operator void*, we must pick
// the operator T*.
if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
@@ -2251,39 +2285,41 @@
}
SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc,
- QualType T) {
+ QualType T) override {
return S.Diag(Loc, diag::err_delete_operand) << T;
}
SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
- QualType T) {
+ QualType T) override {
return S.Diag(Loc, diag::err_delete_incomplete_class_type) << T;
}
SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
- QualType T, QualType ConvTy) {
+ QualType T,
+ QualType ConvTy) override {
return S.Diag(Loc, diag::err_delete_explicit_conversion) << T << ConvTy;
}
SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
- QualType ConvTy) {
+ QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_delete_conversion)
<< ConvTy;
}
SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
- QualType T) {
+ QualType T) override {
return S.Diag(Loc, diag::err_ambiguous_delete_operand) << T;
}
SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
- QualType ConvTy) {
+ QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_delete_conversion)
<< ConvTy;
}
SemaDiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,
- QualType T, QualType ConvTy) {
+ QualType T,
+ QualType ConvTy) override {
llvm_unreachable("conversion functions are permitted");
}
} Converter;
@@ -3032,9 +3068,12 @@
CK_NoOp, VK, /*BasePath=*/0, CCK).take();
if (SCS.DeprecatedStringLiteralToCharPtr &&
- !getLangOpts().WritableStrings)
- Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion)
+ !getLangOpts().WritableStrings) {
+ Diag(From->getLocStart(), getLangOpts().CPlusPlus11
+ ? diag::ext_deprecated_string_literal_conversion
+ : diag::warn_deprecated_string_literal_conversion)
<< ToType.getNonReferenceType();
+ }
break;
}
@@ -3055,26 +3094,13 @@
return Owned(From);
}
-ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT,
- SourceLocation KWLoc,
- ParsedType Ty,
- SourceLocation RParen) {
- TypeSourceInfo *TSInfo;
- QualType T = GetTypeFromParser(Ty, &TSInfo);
-
- if (!TSInfo)
- TSInfo = Context.getTrivialTypeSourceInfo(T);
- return BuildUnaryTypeTrait(UTT, KWLoc, TSInfo, RParen);
-}
-
/// \brief Check the completeness of a type in a unary type trait.
///
/// If the particular type trait requires a complete type, tries to complete
/// it. If completing the type fails, a diagnostic is emitted and false
/// returned. If completing the type succeeds or no completion was required,
/// returns true.
-static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
- UnaryTypeTrait UTT,
+static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
SourceLocation Loc,
QualType ArgTy) {
// C++0x [meta.unary.prop]p3:
@@ -3087,6 +3113,7 @@
// these class templates. We also try to follow any GCC documented behavior
// in these expressions to ensure portability of standard libraries.
switch (UTT) {
+ default: llvm_unreachable("not a UTT");
// is_complete_type somewhat obviously cannot require a complete type.
case UTT_IsCompleteType:
// Fall-through
@@ -3139,6 +3166,8 @@
case UTT_IsPolymorphic:
case UTT_IsAbstract:
case UTT_IsInterfaceClass:
+ case UTT_IsDestructible:
+ case UTT_IsNothrowDestructible:
// Fall-through
// These traits require a complete type.
@@ -3173,7 +3202,6 @@
return !S.RequireCompleteType(
Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr);
}
- llvm_unreachable("Type trait not handled by switch");
}
static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op,
@@ -3203,7 +3231,7 @@
const FunctionProtoType *CPT =
Operator->getType()->getAs<FunctionProtoType>();
CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
- if (!CPT || !CPT->isNothrow(Self.Context))
+ if (!CPT || !CPT->isNothrow(C))
return false;
}
}
@@ -3212,12 +3240,13 @@
return false;
}
-static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
+static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
SourceLocation KeyLoc, QualType T) {
assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");
ASTContext &C = Self.Context;
switch(UTT) {
+ default: llvm_unreachable("not a UTT");
// Type trait expressions corresponding to the primary type category
// predicates in C++0x [meta.unary.cat].
case UTT_IsVoid:
@@ -3404,8 +3433,12 @@
return RD->hasTrivialCopyAssignment() &&
!RD->hasNonTrivialCopyAssignment();
return false;
+ case UTT_IsDestructible:
+ case UTT_IsNothrowDestructible:
+ // FIXME: Implement UTT_IsDestructible and UTT_IsNothrowDestructible.
+ // For now, let's fall through.
case UTT_HasTrivialDestructor:
- // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
// If __is_pod (type) is true or type is a reference type
// then the trait is true, else if type is a cv class or union
// type (or array thereof) with a trivial destructor
@@ -3488,9 +3521,9 @@
CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
if (!CPT)
return false;
- // FIXME: check whether evaluating default arguments can throw.
+ // TODO: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1)
+ if (!CPT->isNothrow(Self.Context) || CPT->getNumParams() > 1)
return false;
}
}
@@ -3499,7 +3532,7 @@
}
return false;
case UTT_HasNothrowConstructor:
- // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
// If __has_trivial_constructor (type) is true then the trait is
// true, else if type is a cv class or union type (or array
// thereof) with a default constructor that is known not to
@@ -3511,6 +3544,7 @@
!RD->hasNonTrivialDefaultConstructor())
return true;
+ bool FoundConstructor = false;
DeclContext::lookup_const_result R = Self.LookupConstructors(RD);
for (DeclContext::lookup_const_iterator Con = R.begin(),
ConEnd = R.end(); Con != ConEnd; ++Con) {
@@ -3519,16 +3553,19 @@
continue;
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
if (Constructor->isDefaultConstructor()) {
+ FoundConstructor = true;
const FunctionProtoType *CPT
= Constructor->getType()->getAs<FunctionProtoType>();
CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
if (!CPT)
return false;
- // TODO: check whether evaluating default arguments can throw.
+ // FIXME: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0;
+ if (!CPT->isNothrow(Self.Context) || CPT->getNumParams() > 0)
+ return false;
}
}
+ return FoundConstructor;
}
return false;
case UTT_HasVirtualDestructor:
@@ -3549,41 +3586,6 @@
// function call.
return !T->isIncompleteType();
}
- llvm_unreachable("Type trait not covered by switch");
-}
-
-ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT,
- SourceLocation KWLoc,
- TypeSourceInfo *TSInfo,
- SourceLocation RParen) {
- QualType T = TSInfo->getType();
- if (!CheckUnaryTypeTraitTypeCompleteness(*this, UTT, KWLoc, T))
- return ExprError();
-
- bool Value = false;
- if (!T->isDependentType())
- Value = EvaluateUnaryTypeTrait(*this, UTT, KWLoc, T);
-
- return Owned(new (Context) UnaryTypeTraitExpr(KWLoc, UTT, TSInfo, Value,
- RParen, Context.BoolTy));
-}
-
-ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT,
- SourceLocation KWLoc,
- ParsedType LhsTy,
- ParsedType RhsTy,
- SourceLocation RParen) {
- TypeSourceInfo *LhsTSInfo;
- QualType LhsT = GetTypeFromParser(LhsTy, &LhsTSInfo);
- if (!LhsTSInfo)
- LhsTSInfo = Context.getTrivialTypeSourceInfo(LhsT);
-
- TypeSourceInfo *RhsTSInfo;
- QualType RhsT = GetTypeFromParser(RhsTy, &RhsTSInfo);
- if (!RhsTSInfo)
- RhsTSInfo = Context.getTrivialTypeSourceInfo(RhsT);
-
- return BuildBinaryTypeTrait(BTT, KWLoc, LhsTSInfo, RhsTSInfo, RParen);
}
/// \brief Determine whether T has a non-trivial Objective-C lifetime in
@@ -3605,10 +3607,22 @@
llvm_unreachable("Unknown ObjC lifetime qualifier");
}
+static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
+ QualType RhsT, SourceLocation KeyLoc);
+
static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc) {
+ if (Kind <= UTT_Last)
+ return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType());
+
+ if (Kind <= BTT_Last)
+ return EvaluateBinaryTypeTrait(S, Kind, Args[0]->getType(),
+ Args[1]->getType(), RParenLoc);
+
switch (Kind) {
+ case clang::TT_IsConstructible:
+ case clang::TT_IsNothrowConstructible:
case clang::TT_IsTriviallyConstructible: {
// C++11 [meta.unary.prop]:
// is_trivially_constructible is defined as:
@@ -3623,11 +3637,7 @@
// variable t:
//
// T t(create<Args>()...);
- if (Args.empty()) {
- S.Diag(KWLoc, diag::err_type_trait_arity)
- << 1 << 1 << 1 << (int)Args.size();
- return false;
- }
+ assert(!Args.empty());
// Precondition: T and all types in the parameter pack Args shall be
// complete types, (possibly cv-qualified) void, or arrays of
@@ -3671,21 +3681,33 @@
InitializationSequence Init(S, To, InitKind, ArgExprs);
if (Init.Failed())
return false;
-
+
ExprResult Result = Init.Perform(S, To, InitKind, ArgExprs);
if (Result.isInvalid() || SFINAE.hasErrorOccurred())
return false;
- // Under Objective-C ARC, if the destination has non-trivial Objective-C
- // lifetime, this is a non-trivial construction.
- if (S.getLangOpts().ObjCAutoRefCount &&
- hasNontrivialObjCLifetime(Args[0]->getType().getNonReferenceType()))
- return false;
+ if (Kind == clang::TT_IsConstructible)
+ return true;
- // The initialization succeeded; now make sure there are no non-trivial
- // calls.
- return !Result.get()->hasNonTrivialCall(S.Context);
+ if (Kind == clang::TT_IsNothrowConstructible)
+ return S.canThrow(Result.get()) == CT_Cannot;
+
+ if (Kind == clang::TT_IsTriviallyConstructible) {
+ // Under Objective-C ARC, if the destination has non-trivial Objective-C
+ // lifetime, this is a non-trivial construction.
+ if (S.getLangOpts().ObjCAutoRefCount &&
+ hasNontrivialObjCLifetime(Args[0]->getType().getNonReferenceType()))
+ return false;
+
+ // The initialization succeeded; now make sure there are no non-trivial
+ // calls.
+ return !Result.get()->hasNonTrivialCall(S.Context);
+ }
+
+ llvm_unreachable("unhandled type trait");
+ return false;
}
+ default: llvm_unreachable("not a TT");
}
return false;
@@ -3694,6 +3716,12 @@
ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc) {
+ QualType ResultType = Context.getLogicalOperationType();
+
+ if (Kind <= UTT_Last && !CheckUnaryTypeTraitTypeCompleteness(
+ *this, Kind, KWLoc, Args[0]->getType()))
+ return ExprError();
+
bool Dependent = false;
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
if (Args[I]->getType()->isDependentType()) {
@@ -3701,17 +3729,17 @@
break;
}
}
-
- bool Value = false;
+
+ bool Result = false;
if (!Dependent)
- Value = evaluateTypeTrait(*this, Kind, KWLoc, Args, RParenLoc);
-
- return TypeTraitExpr::Create(Context, Context.BoolTy, KWLoc, Kind,
- Args, RParenLoc, Value);
+ Result = evaluateTypeTrait(*this, Kind, KWLoc, Args, RParenLoc);
+
+ return TypeTraitExpr::Create(Context, ResultType, KWLoc, Kind, Args,
+ RParenLoc, Result);
}
-ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
- ArrayRef<ParsedType> Args,
+ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
+ ArrayRef<ParsedType> Args,
SourceLocation RParenLoc) {
SmallVector<TypeSourceInfo *, 4> ConvertedArgs;
ConvertedArgs.reserve(Args.size());
@@ -3724,13 +3752,12 @@
ConvertedArgs.push_back(TInfo);
}
-
+
return BuildTypeTrait(Kind, KWLoc, ConvertedArgs, RParenLoc);
}
-static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
- QualType LhsT, QualType RhsT,
- SourceLocation KeyLoc) {
+static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
+ QualType RhsT, SourceLocation KeyLoc) {
assert(!LhsT->isDependentType() && !RhsT->isDependentType() &&
"Cannot evaluate traits of dependent types");
@@ -3833,7 +3860,8 @@
ExprResult Result = Init.Perform(Self, To, Kind, FromPtr);
return !Result.isInvalid() && !SFINAE.hasErrorOccurred();
}
-
+
+ case BTT_IsNothrowAssignable:
case BTT_IsTriviallyAssignable: {
// C++11 [meta.unary.prop]p3:
// is_trivially_assignable is defined as:
@@ -3879,54 +3907,27 @@
if (Result.isInvalid() || SFINAE.hasErrorOccurred())
return false;
- // Under Objective-C ARC, if the destination has non-trivial Objective-C
- // lifetime, this is a non-trivial assignment.
- if (Self.getLangOpts().ObjCAutoRefCount &&
- hasNontrivialObjCLifetime(LhsT.getNonReferenceType()))
- return false;
+ if (BTT == BTT_IsNothrowAssignable)
+ return Self.canThrow(Result.get()) == CT_Cannot;
- return !Result.get()->hasNonTrivialCall(Self.Context);
+ if (BTT == BTT_IsTriviallyAssignable) {
+ // Under Objective-C ARC, if the destination has non-trivial Objective-C
+ // lifetime, this is a non-trivial assignment.
+ if (Self.getLangOpts().ObjCAutoRefCount &&
+ hasNontrivialObjCLifetime(LhsT.getNonReferenceType()))
+ return false;
+
+ return !Result.get()->hasNonTrivialCall(Self.Context);
+ }
+
+ llvm_unreachable("unhandled type trait");
+ return false;
}
+ default: llvm_unreachable("not a BTT");
}
llvm_unreachable("Unknown type trait or not implemented");
}
-ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT,
- SourceLocation KWLoc,
- TypeSourceInfo *LhsTSInfo,
- TypeSourceInfo *RhsTSInfo,
- SourceLocation RParen) {
- QualType LhsT = LhsTSInfo->getType();
- QualType RhsT = RhsTSInfo->getType();
-
- if (BTT == BTT_TypeCompatible) {
- if (getLangOpts().CPlusPlus) {
- Diag(KWLoc, diag::err_types_compatible_p_in_cplusplus)
- << SourceRange(KWLoc, RParen);
- return ExprError();
- }
- }
-
- bool Value = false;
- if (!LhsT->isDependentType() && !RhsT->isDependentType())
- Value = EvaluateBinaryTypeTrait(*this, BTT, LhsT, RhsT, KWLoc);
-
- // Select trait result type.
- QualType ResultType;
- switch (BTT) {
- case BTT_IsBaseOf: ResultType = Context.BoolTy; break;
- case BTT_IsConvertible: ResultType = Context.BoolTy; break;
- case BTT_IsSame: ResultType = Context.BoolTy; break;
- case BTT_TypeCompatible: ResultType = Context.IntTy; break;
- case BTT_IsConvertibleTo: ResultType = Context.BoolTy; break;
- case BTT_IsTriviallyAssignable: ResultType = Context.BoolTy;
- }
-
- return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, BTT, LhsTSInfo,
- RhsTSInfo, Value, RParen,
- ResultType));
-}
-
ExprResult Sema::ActOnArrayTypeTrait(ArrayTypeTrait ATT,
SourceLocation KWLoc,
ParsedType Ty,
@@ -4117,22 +4118,23 @@
OpSpelling, (int)isIndirect)) {
return QualType();
}
- CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
- /*DetectVirtual=*/false);
- // FIXME: Would it be useful to print full ambiguity paths, or is that
- // overkill?
- if (!IsDerivedFrom(LHSType, Class, Paths) ||
- Paths.isAmbiguous(Context.getCanonicalType(Class))) {
+
+ if (!IsDerivedFrom(LHSType, Class)) {
Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
<< (int)isIndirect << LHS.get()->getType();
return QualType();
}
+
+ CXXCastPath BasePath;
+ if (CheckDerivedToBaseConversion(LHSType, Class, Loc,
+ SourceRange(LHS.get()->getLocStart(),
+ RHS.get()->getLocEnd()),
+ &BasePath))
+ return QualType();
+
// Cast LHS to type of use.
QualType UseType = isIndirect ? Context.getPointerType(Class) : Class;
ExprValueKind VK = isIndirect ? VK_RValue : LHS.get()->getValueKind();
-
- CXXCastPath BasePath;
- BuildBasePathArray(Paths, BasePath);
LHS = ImpCastExprToType(LHS.take(), UseType, CK_DerivedToBase, VK,
&BasePath);
}
@@ -4400,42 +4402,21 @@
bool LVoid = LTy->isVoidType();
bool RVoid = RTy->isVoidType();
if (LVoid || RVoid) {
- // ... then the [l2r] conversions are performed on the second and third
- // operands ...
- LHS = DefaultFunctionArrayLvalueConversion(LHS.take());
- RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
- if (LHS.isInvalid() || RHS.isInvalid())
- return QualType();
-
- // Finish off the lvalue-to-rvalue conversion by copy-initializing a
- // temporary if necessary. DefaultFunctionArrayLvalueConversion doesn't
- // do this part for us.
- ExprResult &NonVoid = LVoid ? RHS : LHS;
- if (NonVoid.get()->getType()->isRecordType() &&
- NonVoid.get()->isGLValue()) {
- if (RequireNonAbstractType(QuestionLoc, NonVoid.get()->getType(),
- diag::err_allocation_of_abstract_type))
- return QualType();
- InitializedEntity Entity =
- InitializedEntity::InitializeTemporary(NonVoid.get()->getType());
- NonVoid = PerformCopyInitialization(Entity, SourceLocation(), NonVoid);
- if (NonVoid.isInvalid())
- return QualType();
+ // ... one of the following shall hold:
+ // -- The second or the third operand (but not both) is a (possibly
+ // parenthesized) throw-expression; the result is of the type
+ // and value category of the other.
+ bool LThrow = isa<CXXThrowExpr>(LHS.get()->IgnoreParenImpCasts());
+ bool RThrow = isa<CXXThrowExpr>(RHS.get()->IgnoreParenImpCasts());
+ if (LThrow != RThrow) {
+ Expr *NonThrow = LThrow ? RHS.get() : LHS.get();
+ VK = NonThrow->getValueKind();
+ // DR (no number yet): the result is a bit-field if the
+ // non-throw-expression operand is a bit-field.
+ OK = NonThrow->getObjectKind();
+ return NonThrow->getType();
}
- LTy = LHS.get()->getType();
- RTy = RHS.get()->getType();
-
- // ... and one of the following shall hold:
- // -- The second or the third operand (but not both) is a throw-
- // expression; the result is of the type of the other and is a prvalue.
- bool LThrow = isa<CXXThrowExpr>(LHS.get()->IgnoreParenCasts());
- bool RThrow = isa<CXXThrowExpr>(RHS.get()->IgnoreParenCasts());
- if (LThrow && !RThrow)
- return RTy;
- if (RThrow && !LThrow)
- return LTy;
-
// -- Both the second and third operands have type void; the result is of
// type void and is a prvalue.
if (LVoid && RVoid)
@@ -4456,7 +4437,6 @@
// those operands to the type of the other.
if (!Context.hasSameType(LTy, RTy) &&
(LTy->isRecordType() || RTy->isRecordType())) {
- ImplicitConversionSequence ICSLeftToRight, ICSRightToLeft;
// These return true if a single direction is already ambiguous.
QualType L2RType, R2LType;
bool HaveL2R, HaveR2L;
@@ -5023,7 +5003,7 @@
}
Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) {
- assert(SubExpr && "sub expression can't be null!");
+ assert(SubExpr && "subexpression can't be null!");
CleanupVarDeclMarking();
@@ -5044,7 +5024,7 @@
}
Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {
- assert(SubStmt && "sub statement can't be null!");
+ assert(SubStmt && "sub-statement can't be null!");
CleanupVarDeclMarking();
@@ -5105,19 +5085,21 @@
}
CXXBindTemporaryExpr *TopBind = dyn_cast<CXXBindTemporaryExpr>(E);
- if (TopBind)
- E = TopBind->getSubExpr();
+ CallExpr *TopCall = TopBind ? dyn_cast<CallExpr>(TopBind->getSubExpr()) : 0;
+ if (TopCall)
+ E = TopCall;
+ else
+ TopBind = 0;
// Disable the special decltype handling now.
ExprEvalContexts.back().IsDecltype = false;
// In MS mode, don't perform any extra checking of call return types within a
// decltype expression.
- if (getLangOpts().MicrosoftMode)
+ if (getLangOpts().MSVCCompat)
return Owned(E);
// Perform the semantic checks we delayed until this point.
- CallExpr *TopCall = dyn_cast<CallExpr>(E);
for (unsigned I = 0, N = ExprEvalContexts.back().DelayedDecltypeCalls.size();
I != N; ++I) {
CallExpr *Call = ExprEvalContexts.back().DelayedDecltypeCalls[I];
@@ -5388,7 +5370,7 @@
if (!ObjectType->isDependentType() && !ObjectType->isScalarType() &&
!ObjectType->isVectorType()) {
- if (getLangOpts().MicrosoftMode && ObjectType->isVoidType())
+ if (getLangOpts().MSVCCompat && ObjectType->isVoidType())
Diag(OpLoc, diag::ext_pseudo_dtor_on_void) << Base->getSourceRange();
else
Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar)
@@ -5677,7 +5659,7 @@
ME->setHadMultipleCandidates(true);
MarkMemberReferenced(ME);
- QualType ResultType = Method->getResultType();
+ QualType ResultType = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultType);
ResultType = ResultType.getNonLValueExprType(Context);
@@ -5836,56 +5818,71 @@
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.
+ // FIXME: Teach the constant evaluator to deal with the non-dependent parts
+ // of value-dependent expressions, and use it here to determine whether the
+ // initializer is a potential constant expression.
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.
+/// \brief Check if the current lambda has any potential captures
+/// that must be captured by any of its 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) {
-
+static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
+ 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
+ assert(CurrentLSI->CallOperator == S.CurContext &&
+ "The current call operator must be synchronized with Sema's CurContext");
+
+ const bool IsFullExprInstantiationDependent = FE->isInstantiationDependent();
+
+ ArrayRef<const FunctionScopeInfo *> FunctionScopesArrayRef(
+ S.FunctionScopes.data(), S.FunctionScopes.size());
+
+ // 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) {
+ const unsigned NumPotentialCaptures =
+ CurrentLSI->getNumPotentialVariableCaptures();
+ for (unsigned I = 0; I != NumPotentialCaptures; ++I) {
Expr *VarExpr = 0;
VarDecl *Var = 0;
CurrentLSI->getPotentialVariableCapture(I, Var, VarExpr);
- //
- if (CurrentLSI->isVariableExprMarkedAsNonODRUsed(VarExpr) &&
+ // If the variable is clearly identified as non-odr-used and the full
+ // expression is not instantiation dependent, only then do we not
+ // need to check enclosing lambda's for speculative captures.
+ // For e.g.:
+ // Even though 'x' is not odr-used, it should be captured.
+ // int test() {
+ // const int x = 10;
+ // auto L = [=](auto a) {
+ // (void) +x + a;
+ // };
+ // }
+ 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);
+ continue;
+
+ // If we have a capture-capable lambda for the variable, go ahead and
+ // capture the variable in that lambda (and all its enclosing lambdas).
+ if (const Optional<unsigned> Index =
+ getStackIndexOfNearestEnclosingCaptureCapableLambda(
+ FunctionScopesArrayRef, Var, S)) {
+ const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
+ MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(), S,
+ &FunctionScopeIndexOfCapturableLambda);
}
const bool IsVarNeverAConstantExpression =
VariableCanNeverBeAConstantExpression(Var, S.Context);
@@ -5912,16 +5909,21 @@
}
}
+ // Check if 'this' needs to be captured.
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);
+ // If we have a capture-capable lambda for 'this', go ahead and capture
+ // 'this' in that lambda (and all its enclosing lambdas).
+ if (const Optional<unsigned> Index =
+ getStackIndexOfNearestEnclosingCaptureCapableLambda(
+ FunctionScopesArrayRef, /*0 is 'this'*/ 0, S)) {
+ const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
+ S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation,
+ /*Explicit*/ false, /*BuildAndDiagnose*/ true,
+ &FunctionScopeIndexOfCapturableLambda);
}
}
+
+ // Reset all the potential captures at the end of each full-expression.
CurrentLSI->clearPotentialCaptures();
}
@@ -6018,11 +6020,12 @@
// 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 &&
+ // stop at the outermost enclosing lexical scope."
+ const bool IsInLambdaDeclContext = isLambdaCallOperator(CurContext);
+ if (IsInLambdaDeclContext && CurrentLSI &&
CurrentLSI->hasPotentialCaptures() && !FullExpr.isInvalid())
- CheckLambdaCaptures(FE, CurrentLSI, *this);
+ CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(FE, CurrentLSI,
+ *this);
return MaybeCreateExprWithCleanups(FullExpr);
}
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index 0807e8f..c4a1780 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -322,8 +322,6 @@
(Idx = vecType->getPointAccessorIdx(*compStr)) != -1) {
bool HasRGBA = IsRGBA(*compStr);
do {
- // If we mix/match rgba with xyzw, break to signal that we encountered
- // an illegal name.
if (HasRGBA != IsRGBA(*compStr))
break;
if (HasIndex[Idx]) HasRepeated = true;
@@ -403,9 +401,8 @@
if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel))
return OMD;
- for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(),
- E = PDecl->protocol_end(); I != E; ++I) {
- if (Decl *D = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel,
+ for (const auto *I : PDecl->protocols()) {
+ if (Decl *D = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel,
Context))
return D;
}
@@ -418,25 +415,22 @@
ASTContext &Context) {
// Check protocols on qualified interfaces.
Decl *GDecl = 0;
- for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
- E = QIdTy->qual_end(); I != E; ++I) {
+ for (const auto *I : QIdTy->quals()) {
if (Member)
- if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
+ if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(Member)) {
GDecl = PD;
break;
}
// Also must look for a getter or setter name which uses property syntax.
- if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) {
+ if (ObjCMethodDecl *OMD = I->getInstanceMethod(Sel)) {
GDecl = OMD;
break;
}
}
if (!GDecl) {
- for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
- E = QIdTy->qual_end(); I != E; ++I) {
+ for (const auto *I : QIdTy->quals()) {
// Search in the protocol-qualifier list of current protocol.
- GDecl = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel,
- Context);
+ GDecl = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel, Context);
if (GDecl)
return GDecl;
}
@@ -565,7 +559,7 @@
explicit RecordMemberExprValidatorCCC(const RecordType *RTy)
: Record(RTy->getDecl()) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
NamedDecl *ND = candidate.getCorrectionDecl();
// Don't accept candidates that cannot be member functions, constants,
// variables, or templates.
@@ -578,11 +572,9 @@
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) {
+ for (const auto &BS : RD->bases()) {
if (const RecordType *BSTy = dyn_cast_or_null<RecordType>(
- BS->getType().getTypePtrOrNull())) {
+ BS.getType().getTypePtrOrNull())) {
if (BSTy->getDecl()->containsDecl(ND))
return true;
}
@@ -830,8 +822,6 @@
if (!result)
return ExprError();
- baseObjectIsPointer = false;
-
// FIXME: check qualified member access
}
@@ -1647,8 +1637,7 @@
bool IsArrow = (OpKind == tok::arrow);
NamedDecl *FirstQualifierInScope
- = (!SS.isSet() ? 0 : FindFirstQualifierInScope(S,
- static_cast<NestedNameSpecifier*>(SS.getScopeRep())));
+ = (!SS.isSet() ? 0 : FindFirstQualifierInScope(S, SS.getScopeRep()));
// This is a postfix expression, so get rid of ParenListExprs.
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
@@ -1772,14 +1761,7 @@
assert(!R.empty() && !R.isAmbiguous());
SourceLocation loc = R.getNameLoc();
-
- // We may have found a field within an anonymous union or struct
- // (C++ [class.union]).
- // FIXME: template-ids inside anonymous structs?
- if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>())
- 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.
// 'this' expression now.
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index cc8eace..5bffdd1 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -67,10 +67,14 @@
// Create the aggregate string with the appropriate content and location
// information.
- S = StringLiteral::Create(Context, StrBuf,
- StringLiteral::Ascii, /*Pascal=*/false,
- Context.getPointerType(Context.CharTy),
- &StrLocs[0], StrLocs.size());
+ const ConstantArrayType *CAT = Context.getAsConstantArrayType(S->getType());
+ assert(CAT && "String literal not of constant array type!");
+ QualType StrTy = Context.getConstantArrayType(
+ CAT->getElementType(), llvm::APInt(32, StrBuf.size() + 1),
+ CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers());
+ S = StringLiteral::Create(Context, StrBuf, StringLiteral::Ascii,
+ /*Pascal=*/false, StrTy, &StrLocs[0],
+ StrLocs.size());
}
return BuildObjCStringLiteral(AtLocs[0], S);
@@ -152,7 +156,7 @@
}
// Make sure the return type is reasonable.
- QualType ReturnType = Method->getResultType();
+ QualType ReturnType = Method->getReturnType();
if (!ReturnType->isObjCObjectPointerType()) {
S.Diag(Loc, diag::err_objc_literal_method_sig)
<< Sel;
@@ -224,16 +228,15 @@
ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);
if (!Method && S.getLangOpts().DebuggerObjCLiteral) {
// create a stub definition this NSNumber factory method.
- TypeSourceInfo *ResultTInfo = 0;
- Method = ObjCMethodDecl::Create(CX, SourceLocation(), SourceLocation(), Sel,
- S.NSNumberPointer, ResultTInfo,
- S.NSNumberDecl,
- /*isInstance=*/false, /*isVariadic=*/false,
- /*isPropertyAccessor=*/false,
- /*isImplicitlyDeclared=*/true,
- /*isDefined=*/false,
- ObjCMethodDecl::Required,
- /*HasRelatedResultType=*/false);
+ TypeSourceInfo *ReturnTInfo = 0;
+ Method =
+ ObjCMethodDecl::Create(CX, SourceLocation(), SourceLocation(), Sel,
+ S.NSNumberPointer, ReturnTInfo, S.NSNumberDecl,
+ /*isInstance=*/false, /*isVariadic=*/false,
+ /*isPropertyAccessor=*/false,
+ /*isImplicitlyDeclared=*/true,
+ /*isDefined=*/false, ObjCMethodDecl::Required,
+ /*HasRelatedResultType=*/false);
ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method,
SourceLocation(), SourceLocation(),
&CX.Idents.get("value"),
@@ -492,17 +495,15 @@
BoxingMethod = NSStringDecl->lookupClassMethod(stringWithUTF8String);
if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {
// Debugger needs to work even if NSString hasn't been defined.
- TypeSourceInfo *ResultTInfo = 0;
- ObjCMethodDecl *M =
- ObjCMethodDecl::Create(Context, SourceLocation(), SourceLocation(),
- stringWithUTF8String, NSStringPointer,
- ResultTInfo, NSStringDecl,
- /*isInstance=*/false, /*isVariadic=*/false,
- /*isPropertyAccessor=*/false,
- /*isImplicitlyDeclared=*/true,
- /*isDefined=*/false,
- ObjCMethodDecl::Required,
- /*HasRelatedResultType=*/false);
+ TypeSourceInfo *ReturnTInfo = 0;
+ ObjCMethodDecl *M = ObjCMethodDecl::Create(
+ Context, SourceLocation(), SourceLocation(), stringWithUTF8String,
+ NSStringPointer, ReturnTInfo, NSStringDecl,
+ /*isInstance=*/false, /*isVariadic=*/false,
+ /*isPropertyAccessor=*/false,
+ /*isImplicitlyDeclared=*/true,
+ /*isDefined=*/false, ObjCMethodDecl::Required,
+ /*HasRelatedResultType=*/false);
QualType ConstCharType = Context.CharTy.withConst();
ParmVarDecl *value =
ParmVarDecl::Create(Context, M,
@@ -660,17 +661,14 @@
Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount);
ObjCMethodDecl *Method = NSArrayDecl->lookupClassMethod(Sel);
if (!Method && getLangOpts().DebuggerObjCLiteral) {
- TypeSourceInfo *ResultTInfo = 0;
- Method = ObjCMethodDecl::Create(Context,
- SourceLocation(), SourceLocation(), Sel,
- IdT,
- ResultTInfo,
- Context.getTranslationUnitDecl(),
- false /*Instance*/, false/*isVariadic*/,
- /*isPropertyAccessor=*/false,
- /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
- ObjCMethodDecl::Required,
- false);
+ TypeSourceInfo *ReturnTInfo = 0;
+ Method = ObjCMethodDecl::Create(
+ Context, SourceLocation(), SourceLocation(), Sel, IdT, ReturnTInfo,
+ Context.getTranslationUnitDecl(), false /*Instance*/,
+ false /*isVariadic*/,
+ /*isPropertyAccessor=*/false,
+ /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+ ObjCMethodDecl::Required, false);
SmallVector<ParmVarDecl *, 2> Params;
ParmVarDecl *objects = ParmVarDecl::Create(Context, Method,
SourceLocation(),
@@ -975,6 +973,58 @@
return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc);
}
+static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,
+ SourceLocation AtLoc,
+ ObjCMethodDecl *Method,
+ ObjCMethodList &MethList) {
+ ObjCMethodList *M = &MethList;
+ bool Warned = false;
+ for (M = M->getNext(); M; M=M->getNext()) {
+ ObjCMethodDecl *MatchingMethodDecl = M->Method;
+ if (MatchingMethodDecl == Method ||
+ isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext()) ||
+ MatchingMethodDecl->getSelector() != Method->getSelector())
+ continue;
+ if (!S.MatchTwoMethodDeclarations(Method,
+ MatchingMethodDecl, Sema::MMS_loose)) {
+ if (!Warned) {
+ Warned = true;
+ S.Diag(AtLoc, diag::warning_multiple_selectors)
+ << Method->getSelector();
+ S.Diag(Method->getLocation(), diag::note_method_declared_at)
+ << Method->getDeclName();
+ }
+ S.Diag(MatchingMethodDecl->getLocation(), diag::note_method_declared_at)
+ << MatchingMethodDecl->getDeclName();
+ }
+ }
+ return Warned;
+}
+
+static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc,
+ ObjCMethodDecl *Method) {
+ if (S.Diags.getDiagnosticLevel(diag::warning_multiple_selectors,
+ SourceLocation())
+ == DiagnosticsEngine::Ignored)
+ return;
+ bool Warned = false;
+ for (Sema::GlobalMethodPool::iterator b = S.MethodPool.begin(),
+ e = S.MethodPool.end(); b != e; b++) {
+ // first, instance methods
+ ObjCMethodList &InstMethList = b->second.first;
+ if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc,
+ Method, InstMethList))
+ Warned = true;
+
+ // second, class methods
+ ObjCMethodList &ClsMethList = b->second.second;
+ if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc,
+ Method, ClsMethList) ||
+ Warned)
+ return;
+ }
+}
+
ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
SourceLocation AtLoc,
SourceLocation SelLoc,
@@ -996,7 +1046,8 @@
} else
Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
- }
+ } else
+ DiagnoseMismatchedSelectors(*this, AtLoc, Method);
if (!Method ||
Method->getImplementationControl() != ObjCMethodDecl::Optional) {
@@ -1120,7 +1171,8 @@
static const ObjCMethodDecl *
findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD,
QualType instancetype) {
- if (MD->getResultType() == instancetype) return MD;
+ if (MD->getReturnType() == instancetype)
+ return MD;
// For these purposes, a method in an @implementation overrides a
// declaration in the @interface.
@@ -1155,7 +1207,7 @@
// type doesn't match the method's declared return type.
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurContext);
if (!MD || !MD->hasRelatedResultType() ||
- Context.hasSameUnqualifiedType(destType, MD->getResultType()))
+ Context.hasSameUnqualifiedType(destType, MD->getReturnType()))
return;
// Look for a method overridden by this method which explicitly uses
@@ -1164,7 +1216,7 @@
findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) {
SourceLocation loc;
SourceRange range;
- if (TypeSourceInfo *TSI = overridden->getResultTypeSourceInfo()) {
+ if (TypeSourceInfo *TSI = overridden->getReturnTypeSourceInfo()) {
range = TSI->getTypeLoc().getSourceRange();
loc = range.getBegin();
}
@@ -1195,13 +1247,12 @@
if (!Method->hasRelatedResultType())
return;
-
- if (Context.hasSameUnqualifiedType(Method->getResultType()
- .getNonReferenceType(),
- MsgSend->getType()))
+
+ if (Context.hasSameUnqualifiedType(
+ Method->getReturnType().getNonReferenceType(), MsgSend->getType()))
return;
-
- if (!Context.hasSameUnqualifiedType(Method->getResultType(),
+
+ if (!Context.hasSameUnqualifiedType(Method->getReturnType(),
Context.getObjCInstanceType()))
return;
@@ -1287,7 +1338,7 @@
ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage,
isSuperMessage);
- VK = Expr::getValueKindForType(Method->getResultType());
+ VK = Expr::getValueKindForType(Method->getReturnType());
unsigned NumNamedArgs = Sel.getNumArgs();
// Method might have more arguments than selector indicates. This is due
@@ -1380,10 +1431,14 @@
return IsError;
}
-bool Sema::isSelfExpr(Expr *receiver) {
+bool Sema::isSelfExpr(Expr *RExpr) {
// 'self' is objc 'self' in an objc method only.
- ObjCMethodDecl *method =
- dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor());
+ ObjCMethodDecl *Method =
+ dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor());
+ return isSelfExpr(RExpr, Method);
+}
+
+bool Sema::isSelfExpr(Expr *receiver, const ObjCMethodDecl *method) {
if (!method) return false;
receiver = receiver->IgnoreParenLValueCasts();
@@ -1409,9 +1464,8 @@
}
// Check qualifiers.
- for (ObjCObjectType::qual_iterator
- i = objType->qual_begin(), e = objType->qual_end(); i != e; ++i)
- if (ObjCMethodDecl *method = (*i)->lookupMethod(sel, isInstance))
+ for (const auto *I : objType->quals())
+ if (ObjCMethodDecl *method = I->lookupMethod(sel, isInstance))
return method;
return 0;
@@ -1424,9 +1478,7 @@
bool Instance)
{
ObjCMethodDecl *MD = 0;
- for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
- E = OPT->qual_end(); I != E; ++I) {
- ObjCProtocolDecl *PROTO = (*I);
+ for (const auto *PROTO : OPT->quals()) {
if ((MD = PROTO->lookupMethod(Sel, Instance))) {
return MD;
}
@@ -1452,7 +1504,7 @@
if (PRE->isImplicitProperty()) {
GDecl = PRE->getImplicitPropertyGetter();
if (GDecl) {
- T = GDecl->getResultType();
+ T = GDecl->getReturnType();
}
}
else {
@@ -1535,9 +1587,8 @@
MemberLoc, BaseExpr));
}
// Check protocols on qualified interfaces.
- for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
- E = OPT->qual_end(); I != E; ++I)
- if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
+ for (const auto *I : OPT->quals())
+ if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(Member)) {
// Check whether we can reference this property.
if (DiagnoseUseOfDecl(PD, MemberLoc))
return ExprError();
@@ -1699,7 +1750,8 @@
}
if (IFace == 0) {
- Diag(receiverNameLoc, diag::err_expected_ident_or_lparen);
+ Diag(receiverNameLoc, diag::err_expected_either) << tok::identifier
+ << tok::l_paren;
return ExprError();
}
}
@@ -1773,7 +1825,7 @@
WantObjCSuper = Method->getClassInterface()->getSuperClass();
}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() ||
candidate.isKeyword("super");
}
@@ -2110,8 +2162,8 @@
ReturnType, VK))
return ExprError();
- if (Method && !Method->getResultType()->isVoidType() &&
- RequireCompleteType(LBracLoc, Method->getResultType(),
+ if (Method && !Method->getReturnType()->isVoidType() &&
+ RequireCompleteType(LBracLoc, Method->getReturnType(),
diag::err_illegal_message_expr_incomplete_type))
return ExprError();
@@ -2447,6 +2499,52 @@
}
}
+ FunctionScopeInfo *DIFunctionScopeInfo =
+ (Method && Method->getMethodFamily() == OMF_init)
+ ? getEnclosingFunction() : 0;
+
+ if (DIFunctionScopeInfo &&
+ DIFunctionScopeInfo->ObjCIsDesignatedInit &&
+ (SuperLoc.isValid() || isSelfExpr(Receiver))) {
+ bool isDesignatedInitChain = false;
+ if (SuperLoc.isValid()) {
+ if (const ObjCObjectPointerType *
+ OCIType = ReceiverType->getAsObjCInterfacePointerType()) {
+ if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) {
+ // Either we know this is a designated initializer or we
+ // conservatively assume it because we don't know for sure.
+ if (!ID->declaresOrInheritsDesignatedInitializers() ||
+ ID->isDesignatedInitializer(Sel)) {
+ isDesignatedInitChain = true;
+ DIFunctionScopeInfo->ObjCWarnForNoDesignatedInitChain = false;
+ }
+ }
+ }
+ }
+ if (!isDesignatedInitChain) {
+ const ObjCMethodDecl *InitMethod = 0;
+ bool isDesignated =
+ getCurMethodDecl()->isDesignatedInitializerForTheInterface(&InitMethod);
+ assert(isDesignated && InitMethod);
+ (void)isDesignated;
+ Diag(SelLoc, SuperLoc.isValid() ?
+ diag::warn_objc_designated_init_non_designated_init_call :
+ diag::warn_objc_designated_init_non_super_designated_init_call);
+ Diag(InitMethod->getLocation(),
+ diag::note_objc_designated_init_marked_here);
+ }
+ }
+
+ if (DIFunctionScopeInfo &&
+ DIFunctionScopeInfo->ObjCIsSecondaryInit &&
+ (SuperLoc.isValid() || isSelfExpr(Receiver))) {
+ if (SuperLoc.isValid()) {
+ Diag(SelLoc, diag::warn_objc_secondary_init_super_init_call);
+ } else {
+ DIFunctionScopeInfo->ObjCWarnForNoInitDelegation = false;
+ }
+ }
+
// Check the message arguments.
unsigned NumArgs = ArgsIn.size();
Expr **Args = ArgsIn.data();
@@ -2459,9 +2557,9 @@
ClassMessage, SuperLoc.isValid(),
LBracLoc, RBracLoc, ReturnType, VK))
return ExprError();
-
- if (Method && !Method->getResultType()->isVoidType() &&
- RequireCompleteType(LBracLoc, Method->getResultType(),
+
+ if (Method && !Method->getReturnType()->isVoidType() &&
+ RequireCompleteType(LBracLoc, Method->getReturnType(),
diag::err_illegal_message_expr_incomplete_type))
return ExprError();
@@ -2600,7 +2698,7 @@
}
}
}
-
+
return MaybeBindToTemporary(Result);
}
@@ -2859,7 +2957,7 @@
ACCResult checkCallToFunction(FunctionDecl *fn) {
// Require a CF*Ref return type.
- if (!isCFType(fn->getResultType()))
+ if (!isCFType(fn->getReturnType()))
return ACC_invalid;
if (!isAnyRetainable(TargetClass))
@@ -2912,7 +3010,7 @@
// Check for message sends to functions returning CF types. We
// just obey the Cocoa conventions with these, even though the
// return type is CF.
- if (!isAnyRetainable(TargetClass) || !isCFType(method->getResultType()))
+ if (!isAnyRetainable(TargetClass) || !isCFType(method->getReturnType()))
return ACC_invalid;
// If the method is explicitly marked not-retained, it's +0.
@@ -3045,6 +3143,31 @@
}
}
+template <typename T>
+static inline T *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())
+ return RD->getAttr<T>();
+ }
+ return 0;
+}
+
+static ObjCBridgeRelatedAttr *ObjCBridgeRelatedAttrFromType(QualType T,
+ TypedefNameDecl *&TDNDecl) {
+ while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
+ TDNDecl = TD->getDecl();
+ if (ObjCBridgeRelatedAttr *ObjCBAttr =
+ getObjCBridgeAttr<ObjCBridgeRelatedAttr>(TD))
+ return ObjCBAttr;
+ T = TDNDecl->getUnderlyingType();
+ }
+ return 0;
+}
+
static void
diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
QualType castType, ARCConversionTypeClass castACTC,
@@ -3059,6 +3182,12 @@
return;
QualType castExprType = castExpr->getType();
+ TypedefNameDecl *TDNDecl = 0;
+ if ((castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&
+ ObjCBridgeRelatedAttrFromType(castType, TDNDecl)) ||
+ (exprACTC == ACTC_coreFoundation && castACTC == ACTC_retainable &&
+ ObjCBridgeRelatedAttrFromType(castExprType, TDNDecl)))
+ return;
unsigned srcKind = 0;
switch (exprACTC) {
@@ -3165,24 +3294,12 @@
<< 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;
-}
-
+template <typename TB>
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 (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
NamedDecl *Target = 0;
// Check for an existing type with this name.
@@ -3196,20 +3313,30 @@
castType->getAsObjCInterfacePointerType()) {
ObjCInterfaceDecl *CastClass
= InterfacePointerType->getObjectType()->getInterface();
- if ((CastClass == ExprClass) || (CastClass && ExprClass->isSuperClassOf(CastClass)))
+ 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 {
+ } else if (castType->isObjCIdType() ||
+ (S.Context.ObjCObjectAdoptsQTypeProtocols(
+ castType, ExprClass)))
+ // ok to cast to 'id'.
+ // casting to id<p-list> is ok if bridge type adopts all of
+ // p-list protocols.
+ return true;
+ else {
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
<< T << Target->getName() << castType;
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ S.Diag(Target->getLocStart(), diag::note_declared_at);
return true;
}
}
}
S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface)
- << castExpr->getType() << Parm->getName();
+ << castExpr->getType() << Parm;
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
if (Target)
S.Diag(Target->getLocStart(), diag::note_declared_at);
@@ -3221,12 +3348,12 @@
return false;
}
-// (CFErrorRef)ns
+template <typename TB>
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 (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
NamedDecl *Target = 0;
// Check for an existing type with this name.
@@ -3240,16 +3367,25 @@
castExpr->getType()->getAsObjCInterfacePointerType()) {
ObjCInterfaceDecl *ExprClass
= InterfacePointerType->getObjectType()->getInterface();
- if ((CastClass == ExprClass) || (ExprClass && CastClass->isSuperClassOf(ExprClass)))
+ 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 {
+ } else if (castExpr->getType()->isObjCIdType() ||
+ (S.Context.QIdProtocolsAdoptObjCObjectProtocols(
+ castExpr->getType(), CastClass)))
+ // ok to cast an 'id' expression to a CFtype.
+ // ok to cast an 'id<plist>' expression to CFtype provided plist
+ // adopts all of CFtype's ObjetiveC's class plist.
+ 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);
+ S.Diag(Target->getLocStart(), diag::note_declared_at);
return true;
}
}
@@ -3267,6 +3403,173 @@
return false;
}
+void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) {
+ // warn in presence of __bridge casting to or from a toll free bridge cast.
+ ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExpr->getType());
+ ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType);
+ if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) {
+ (void)CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr);
+ (void)CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr);
+ }
+ else if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable) {
+ (void)CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr);
+ (void)CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr);
+ }
+}
+
+
+bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
+ QualType DestType, QualType SrcType,
+ ObjCInterfaceDecl *&RelatedClass,
+ ObjCMethodDecl *&ClassMethod,
+ ObjCMethodDecl *&InstanceMethod,
+ TypedefNameDecl *&TDNDecl,
+ bool CfToNs) {
+ QualType T = CfToNs ? SrcType : DestType;
+ ObjCBridgeRelatedAttr *ObjCBAttr = ObjCBridgeRelatedAttrFromType(T, TDNDecl);
+ if (!ObjCBAttr)
+ return false;
+
+ IdentifierInfo *RCId = ObjCBAttr->getRelatedClass();
+ IdentifierInfo *CMId = ObjCBAttr->getClassMethod();
+ IdentifierInfo *IMId = ObjCBAttr->getInstanceMethod();
+ if (!RCId)
+ return false;
+ NamedDecl *Target = 0;
+ // Check for an existing type with this name.
+ LookupResult R(*this, DeclarationName(RCId), SourceLocation(),
+ Sema::LookupOrdinaryName);
+ if (!LookupName(R, TUScope)) {
+ Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId
+ << SrcType << DestType;
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ return false;
+ }
+ Target = R.getFoundDecl();
+ if (Target && isa<ObjCInterfaceDecl>(Target))
+ RelatedClass = cast<ObjCInterfaceDecl>(Target);
+ else {
+ Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId
+ << SrcType << DestType;
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ if (Target)
+ Diag(Target->getLocStart(), diag::note_declared_at);
+ return false;
+ }
+
+ // Check for an existing class method with the given selector name.
+ if (CfToNs && CMId) {
+ Selector Sel = Context.Selectors.getUnarySelector(CMId);
+ ClassMethod = RelatedClass->lookupMethod(Sel, false);
+ if (!ClassMethod) {
+ Diag(Loc, diag::err_objc_bridged_related_known_method)
+ << SrcType << DestType << Sel << false;
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ return false;
+ }
+ }
+
+ // Check for an existing instance method with the given selector name.
+ if (!CfToNs && IMId) {
+ Selector Sel = Context.Selectors.getNullarySelector(IMId);
+ InstanceMethod = RelatedClass->lookupMethod(Sel, true);
+ if (!InstanceMethod) {
+ Diag(Loc, diag::err_objc_bridged_related_known_method)
+ << SrcType << DestType << Sel << true;
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
+ QualType DestType, QualType SrcType,
+ Expr *&SrcExpr) {
+ ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType);
+ ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType);
+ bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable);
+ bool NsToCf = (rhsExprACTC == ACTC_retainable && lhsExprACTC == ACTC_coreFoundation);
+ if (!CfToNs && !NsToCf)
+ return false;
+
+ ObjCInterfaceDecl *RelatedClass;
+ ObjCMethodDecl *ClassMethod = 0;
+ ObjCMethodDecl *InstanceMethod = 0;
+ TypedefNameDecl *TDNDecl = 0;
+ if (!checkObjCBridgeRelatedComponents(Loc, DestType, SrcType, RelatedClass,
+ ClassMethod, InstanceMethod, TDNDecl, CfToNs))
+ return false;
+
+ if (CfToNs) {
+ // Implicit conversion from CF to ObjC object is needed.
+ if (ClassMethod) {
+ std::string ExpressionString = "[";
+ ExpressionString += RelatedClass->getNameAsString();
+ ExpressionString += " ";
+ ExpressionString += ClassMethod->getSelector().getAsString();
+ SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd());
+ // Provide a fixit: [RelatedClass ClassMethod SrcExpr]
+ Diag(Loc, diag::err_objc_bridged_related_known_method)
+ << SrcType << DestType << ClassMethod->getSelector() << false
+ << FixItHint::CreateInsertion(SrcExpr->getLocStart(), ExpressionString)
+ << FixItHint::CreateInsertion(SrcExprEndLoc, "]");
+ Diag(RelatedClass->getLocStart(), diag::note_declared_at);
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+
+ QualType receiverType =
+ Context.getObjCInterfaceType(RelatedClass);
+ // Argument.
+ Expr *args[] = { SrcExpr };
+ ExprResult msg = BuildClassMessageImplicit(receiverType, false,
+ ClassMethod->getLocation(),
+ ClassMethod->getSelector(), ClassMethod,
+ MultiExprArg(args, 1));
+ SrcExpr = msg.take();
+ return true;
+ }
+ }
+ else {
+ // Implicit conversion from ObjC type to CF object is needed.
+ if (InstanceMethod) {
+ std::string ExpressionString;
+ SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd());
+ if (InstanceMethod->isPropertyAccessor())
+ if (const ObjCPropertyDecl *PDecl = InstanceMethod->findPropertyDecl()) {
+ // fixit: ObjectExpr.propertyname when it is aproperty accessor.
+ ExpressionString = ".";
+ ExpressionString += PDecl->getNameAsString();
+ Diag(Loc, diag::err_objc_bridged_related_known_method)
+ << SrcType << DestType << InstanceMethod->getSelector() << true
+ << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString);
+ }
+ if (ExpressionString.empty()) {
+ // Provide a fixit: [ObjectExpr InstanceMethod]
+ ExpressionString = " ";
+ ExpressionString += InstanceMethod->getSelector().getAsString();
+ ExpressionString += "]";
+
+ Diag(Loc, diag::err_objc_bridged_related_known_method)
+ << SrcType << DestType << InstanceMethod->getSelector() << true
+ << FixItHint::CreateInsertion(SrcExpr->getLocStart(), "[")
+ << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString);
+ }
+ Diag(RelatedClass->getLocStart(), diag::note_declared_at);
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+
+ ExprResult msg =
+ BuildInstanceMessageImplicit(SrcExpr, SrcType,
+ InstanceMethod->getLocation(),
+ InstanceMethod->getSelector(),
+ InstanceMethod, None);
+ SrcExpr = msg.take();
+ return true;
+ }
+ }
+ return false;
+}
+
Sema::ARCConversionResult
Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
Expr *&castExpr, CheckedConversionKind CCK,
@@ -3327,12 +3630,14 @@
if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation &&
(CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
- if (CheckObjCBridgeNSCast(*this, castType, castExpr))
+ if (CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr) ||
+ CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr))
return ACR_okay;
if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&
(CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
- if (CheckObjCBridgeCFCast(*this, castType, castExpr))
+ if (CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr) ||
+ CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr))
return ACR_okay;
@@ -3362,6 +3667,13 @@
CCK != CCK_ImplicitConversion)
return ACR_unbridged;
+ // Do not issue bridge cast" diagnostic when implicit casting a cstring
+ // to 'NSString *'. Let caller issue a normal mismatched diagnostic with
+ // suitable fix-it.
+ if (castACTC == ACTC_retainable && exprACTC == ACTC_none &&
+ ConversionToObjCStringLiteralCheck(castType, castExpr))
+ return ACR_okay;
+
// 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
@@ -3599,6 +3911,8 @@
Expr *SubExpr) {
TypeSourceInfo *TSInfo = 0;
QualType T = GetTypeFromParser(Type, &TSInfo);
+ if (Kind == OBC_Bridge)
+ CheckTollFreeBridgeCast(T, SubExpr);
if (!TSInfo)
TSInfo = Context.getTrivialTypeSourceInfo(T, LParenLoc);
return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo,
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 034c1b6..3829016 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -441,26 +441,22 @@
Entity, ILE, RequiresSecondPass);
else if (RDecl->isUnion() && isa<CXXRecordDecl>(RDecl) &&
cast<CXXRecordDecl>(RDecl)->hasInClassInitializer()) {
- for (RecordDecl::field_iterator Field = RDecl->field_begin(),
- FieldEnd = RDecl->field_end();
- Field != FieldEnd; ++Field) {
+ for (auto *Field : RDecl->fields()) {
if (Field->hasInClassInitializer()) {
- FillInValueInitForField(0, *Field, Entity, ILE, RequiresSecondPass);
+ FillInValueInitForField(0, Field, Entity, ILE, RequiresSecondPass);
break;
}
}
} else {
unsigned Init = 0;
- for (RecordDecl::field_iterator Field = RDecl->field_begin(),
- FieldEnd = RDecl->field_end();
- Field != FieldEnd; ++Field) {
+ for (auto *Field : RDecl->fields()) {
if (Field->isUnnamedBitfield())
continue;
if (hadError)
return;
- FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass);
+ FillInValueInitForField(Init, Field, Entity, ILE, RequiresSecondPass);
if (hadError)
return;
@@ -587,13 +583,10 @@
int InitListChecker::numStructUnionElements(QualType DeclType) {
RecordDecl *structDecl = DeclType->getAs<RecordType>()->getDecl();
int InitializableMembers = 0;
- for (RecordDecl::field_iterator
- Field = structDecl->field_begin(),
- FieldEnd = structDecl->field_end();
- Field != FieldEnd; ++Field) {
+ for (const auto *Field : structDecl->fields())
if (!Field->isUnnamedBitfield())
++InitializableMembers;
- }
+
if (structDecl->isUnion())
return std::min(InitializableMembers, 1);
return InitializableMembers - structDecl->hasFlexibleArrayMember();
@@ -1005,9 +998,11 @@
Expr *expr = IList->getInit(Index);
if (InitListExpr *SubIList = dyn_cast<InitListExpr>(expr)) {
+ // FIXME: This is invalid, and accepting it causes overload resolution
+ // to pick the wrong overload in some corner cases.
if (!VerifyOnly)
SemaRef.Diag(SubIList->getLocStart(),
- diag::warn_many_braces_around_scalar_init)
+ diag::ext_many_braces_around_scalar_init)
<< SubIList->getSourceRange();
CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList,
@@ -1538,7 +1533,7 @@
it != end; ++it) {
if (!it->isUnnamedBitfield() && !it->hasInClassInitializer()) {
SemaRef.Diag(IList->getSourceRange().getEnd(),
- diag::warn_missing_field_initializers) << it->getName();
+ diag::warn_missing_field_initializers) << *it;
break;
}
}
@@ -1648,7 +1643,7 @@
explicit FieldInitializerValidatorCCC(RecordDecl *RD)
: Record(RD) {}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>();
return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record);
}
@@ -2291,8 +2286,7 @@
if (RDecl->isUnion())
NumElements = 1;
else
- NumElements = std::distance(RDecl->field_begin(),
- RDecl->field_end());
+ NumElements = std::distance(RDecl->field_begin(), RDecl->field_end());
}
Result->reserveInits(SemaRef.Context, NumElements);
@@ -3520,10 +3514,13 @@
if (ConvTemplate)
S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
ActingDC, Initializer,
- DestType, CandidateSet);
+ DestType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/
+ false);
else
S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
- Initializer, DestType, CandidateSet);
+ Initializer, DestType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/false);
}
}
}
@@ -3545,7 +3542,7 @@
// Compute the returned type of the conversion.
if (isa<CXXConversionDecl>(Function))
- T2 = Function->getResultType();
+ T2 = Function->getReturnType();
else
T2 = cv1T1;
@@ -4143,10 +4140,11 @@
if (ConvTemplate)
S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
ActingDC, Initializer, DestType,
- CandidateSet);
+ CandidateSet, AllowExplicit);
else
S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
- Initializer, DestType, CandidateSet);
+ Initializer, DestType, CandidateSet,
+ AllowExplicit);
}
}
}
@@ -4460,6 +4458,14 @@
Expr *Initializer = 0;
if (Args.size() == 1) {
Initializer = Args[0];
+ if (S.getLangOpts().ObjC1) {
+ if (S.CheckObjCBridgeRelatedConversions(Initializer->getLocStart(),
+ DestType, Initializer->getType(),
+ Initializer) ||
+ S.ConversionToObjCStringLiteralCheck(DestType, Initializer))
+ Args[0] = Initializer;
+
+ }
if (!isa<InitListExpr>(Initializer))
SourceType = Initializer->getType();
}
@@ -5218,10 +5224,13 @@
ConstructKind = CXXConstructExpr::CK_Delegating;
}
- // Only get the parenthesis range if it is a direct construction.
- SourceRange parenRange =
- Kind.getKind() == InitializationKind::IK_Direct ?
- Kind.getParenRange() : SourceRange();
+ // Only get the parenthesis or brace range if it is a list initialization or
+ // direct construction.
+ SourceRange ParenOrBraceRange;
+ if (IsListInitialization)
+ ParenOrBraceRange = SourceRange(LBraceLoc, RBraceLoc);
+ else if (Kind.getKind() == InitializationKind::IK_Direct)
+ ParenOrBraceRange = Kind.getParenRange();
// If the entity allows NRVO, mark the construction as elidable
// unconditionally.
@@ -5233,7 +5242,7 @@
IsListInitialization,
ConstructorInitRequiresZeroInit,
ConstructKind,
- parenRange);
+ ParenOrBraceRange);
else
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
Constructor,
@@ -5242,7 +5251,7 @@
IsListInitialization,
ConstructorInitRequiresZeroInit,
ConstructKind,
- parenRange);
+ ParenOrBraceRange);
}
if (CurInit.isInvalid())
return ExprError();
@@ -5451,9 +5460,7 @@
performReferenceExtension(ILE->getInit(0), ExtendingD);
else {
unsigned Index = 0;
- for (RecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end();
- I != E; ++I) {
+ for (const auto *I : RD->fields()) {
if (Index >= ILE->getNumInits())
break;
if (I->isUnnamedBitfield())
@@ -5874,7 +5881,7 @@
CastKind = CK_UserDefinedConversion;
- CreatedObject = Conversion->getResultType()->isRecordType();
+ CreatedObject = Conversion->getReturnType()->isRecordType();
}
bool RequiresCopy = !IsCopy && !isReferenceBinding(Steps.back());
@@ -6196,7 +6203,7 @@
case SK_OCLSamplerInit: {
assert(Step->Type->isSamplerT() &&
- "Sampler initialization on non sampler type.");
+ "Sampler initialization on non-sampler type.");
QualType SourceType = CurInit.get()->getType();
@@ -6212,7 +6219,7 @@
}
case SK_OCLZeroEvent: {
assert(Step->Type->isEventT() &&
- "Event initialization on non event type.");
+ "Event initialization on non-event type.");
CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type,
CK_ZeroToOCLEvent,
@@ -6246,8 +6253,7 @@
if (!RD || !RD->hasUninitializedReferenceMember())
return false;
- for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
- FE = RD->field_end(); FI != FE; ++FI) {
+ for (const auto *FI : RD->fields()) {
if (FI->isUnnamedBitfield())
continue;
@@ -6257,10 +6263,8 @@
}
}
- for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(),
- BE = RD->bases_end();
- BI != BE; ++BI) {
- if (DiagnoseUninitializedReference(S, BI->getLocStart(), BI->getType())) {
+ for (const auto &BI : RD->bases()) {
+ if (DiagnoseUninitializedReference(S, BI.getLocStart(), BI.getType())) {
S.Diag(Loc, diag::note_value_initialization_here) << RD;
return true;
}
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index a7d5b65..0d287f7 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/DeclSpec.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/TargetInfo.h"
@@ -21,115 +22,204 @@
#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) {
+/// \brief Examines the FunctionScopeInfo stack to determine the nearest
+/// enclosing lambda (to the current lambda) that is 'capture-ready' for
+/// the variable referenced in the current lambda (i.e. \p VarToCapture).
+/// If successful, returns the index into Sema's FunctionScopeInfo stack
+/// of the capture-ready lambda's LambdaScopeInfo.
+///
+/// Climbs down the stack of lambdas (deepest nested lambda - i.e. current
+/// lambda - is on top) to determine the index of the nearest enclosing/outer
+/// lambda that is ready to capture the \p VarToCapture being referenced in
+/// the current lambda.
+/// As we climb down the stack, we want the index of the first such lambda -
+/// that is the lambda with the highest index that is 'capture-ready'.
+///
+/// A lambda 'L' is capture-ready for 'V' (var or this) if:
+/// - its enclosing context is non-dependent
+/// - and if the chain of lambdas between L and the lambda in which
+/// V is potentially used (i.e. the lambda at the top of the scope info
+/// stack), can all capture or have already captured V.
+/// If \p VarToCapture is 'null' then we are trying to capture 'this'.
+///
+/// Note that a lambda that is deemed 'capture-ready' still needs to be checked
+/// for whether it is 'capture-capable' (see
+/// getStackIndexOfNearestEnclosingCaptureCapableLambda), before it can truly
+/// capture.
+///
+/// \param FunctionScopes - Sema's stack of nested FunctionScopeInfo's (which a
+/// LambdaScopeInfo inherits from). The current/deepest/innermost lambda
+/// is at the top of the stack and has the highest index.
+/// \param VarToCapture - the variable to capture. If NULL, capture 'this'.
+///
+/// \returns An Optional<unsigned> Index that if evaluates to 'true' contains
+/// the index (into Sema's FunctionScopeInfo stack) of the innermost lambda
+/// which is capture-ready. If the return value evaluates to 'false' then
+/// no lambda is capture-ready for \p VarToCapture.
+
+static inline Optional<unsigned>
+getStackIndexOfNearestEnclosingCaptureReadyLambda(
+ ArrayRef<const clang::sema::FunctionScopeInfo *> FunctionScopes,
+ VarDecl *VarToCapture) {
+ // Label failure to capture.
+ const Optional<unsigned> NoLambdaIsCaptureReady;
+
+ assert(
+ isa<clang::sema::LambdaScopeInfo>(
+ FunctionScopes[FunctionScopes.size() - 1]) &&
+ "The function on the top of sema's function-info stack must be a lambda");
- DeclContext *EnclosingDC = CurContext;
- // If VD is null, we are attempting to capture 'this'
- const bool IsCapturingThis = !VD;
+ // If VarToCapture is null, we are attempting to capture 'this'.
+ const bool IsCapturingThis = !VarToCapture;
const bool IsCapturingVariable = !IsCapturingThis;
- int RetIndex = -1;
+
+ // Start with the current lambda at the top of the stack (highest index).
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
+ DeclContext *EnclosingDC =
+ cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex])->CallOperator;
+
+ do {
+ const clang::sema::LambdaScopeInfo *LSI =
+ cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]);
+ // IF we have climbed down to an intervening enclosing lambda that contains
+ // the variable declaration - it obviously can/must not capture the
// variable.
- if (IsCapturingVariable && VD->getDeclContext()->Equals(EnclosingDC))
- return -1;
- // All intervening lambda call operators have to be able to capture.
+ // Since its enclosing DC is dependent, all the lambdas between it and the
+ // innermost nested lambda are dependent (otherwise we wouldn't have
+ // arrived here) - so we don't yet have a lambda that can capture the
+ // variable.
+ if (IsCapturingVariable &&
+ VarToCapture->getDeclContext()->Equals(EnclosingDC))
+ return NoLambdaIsCaptureReady;
+
+ // For an enclosing lambda to be capture ready for an entity, all
+ // intervening lambda's have to be able to capture that entity. If even
+ // one of the intervening lambda's is not capable of capturing the entity
+ // then no enclosing lambda can ever capture that entity.
+ // For e.g.
+ // const int x = 10;
+ // [=](auto a) { #1
+ // [](auto b) { #2 <-- an intervening lambda that can never capture 'x'
+ // [=](auto c) { #3
+ // f(x, c); <-- can not lead to x's speculative capture by #1 or #2
+ // }; }; };
// 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
+ // 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 (IsCapturingVariable && !LSI->isCaptured(VarToCapture))
+ return NoLambdaIsCaptureReady;
if (IsCapturingThis && !LSI->isCXXThisCaptured())
- return -1;
+ return NoLambdaIsCaptureReady;
}
EnclosingDC = getLambdaAwareParentOfDeclContext(EnclosingDC);
+
+ assert(CurScopeIndex);
--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) {
+ } while (!EnclosingDC->isTranslationUnit() &&
+ EnclosingDC->isDependentContext() &&
+ isLambdaCallOperator(EnclosingDC));
- 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;
+ assert(CurScopeIndex < (FunctionScopes.size() - 1));
+ // If the enclosingDC is not dependent, then the immediately nested lambda
+ // (one index above) is capture-ready.
+ if (!EnclosingDC->isDependentContext())
+ return CurScopeIndex + 1;
+ return NoLambdaIsCaptureReady;
+}
+
+/// \brief Examines the FunctionScopeInfo stack to determine the nearest
+/// enclosing lambda (to the current lambda) that is 'capture-capable' for
+/// the variable referenced in the current lambda (i.e. \p VarToCapture).
+/// If successful, returns the index into Sema's FunctionScopeInfo stack
+/// of the capture-capable lambda's LambdaScopeInfo.
+///
+/// Given the current stack of lambdas being processed by Sema and
+/// the variable of interest, to identify the nearest enclosing lambda (to the
+/// current lambda at the top of the stack) that can truly capture
+/// a variable, it has to have the following two properties:
+/// a) 'capture-ready' - be the innermost lambda that is 'capture-ready':
+/// - climb down the stack (i.e. starting from the innermost and examining
+/// each outer lambda step by step) checking if each enclosing
+/// lambda can either implicitly or explicitly capture the variable.
+/// Record the first such lambda that is enclosed in a non-dependent
+/// context. If no such lambda currently exists return failure.
+/// b) 'capture-capable' - make sure the 'capture-ready' lambda can truly
+/// capture the variable by checking all its enclosing lambdas:
+/// - check if all outer lambdas enclosing the 'capture-ready' lambda
+/// identified above in 'a' can also capture the variable (this is done
+/// via tryCaptureVariable for variables and CheckCXXThisCapture for
+/// 'this' by passing in the index of the Lambda identified in step 'a')
+///
+/// \param FunctionScopes - Sema's stack of nested FunctionScopeInfo's (which a
+/// LambdaScopeInfo inherits from). The current/deepest/innermost lambda
+/// is at the top of the stack.
+///
+/// \param VarToCapture - the variable to capture. If NULL, capture 'this'.
+///
+///
+/// \returns An Optional<unsigned> Index that if evaluates to 'true' contains
+/// the index (into Sema's FunctionScopeInfo stack) of the innermost lambda
+/// which is capture-capable. If the return value evaluates to 'false' then
+/// no lambda is capture-capable for \p VarToCapture.
+
+Optional<unsigned> clang::getStackIndexOfNearestEnclosingCaptureCapableLambda(
+ ArrayRef<const sema::FunctionScopeInfo *> FunctionScopes,
+ VarDecl *VarToCapture, Sema &S) {
+
+ const Optional<unsigned> NoLambdaIsCaptureCapable;
+
+ const Optional<unsigned> OptionalStackIndex =
+ getStackIndexOfNearestEnclosingCaptureReadyLambda(FunctionScopes,
+ VarToCapture);
+ if (!OptionalStackIndex)
+ return NoLambdaIsCaptureCapable;
+
+ const unsigned IndexOfCaptureReadyLambda = OptionalStackIndex.getValue();
+ assert(((IndexOfCaptureReadyLambda != (FunctionScopes.size() - 1)) ||
+ S.getCurGenericLambda()) &&
+ "The capture ready lambda for a potential capture can only be the "
+ "current lambda if it is a generic lambda");
+
+ const sema::LambdaScopeInfo *const CaptureReadyLambdaLSI =
+ cast<sema::LambdaScopeInfo>(FunctionScopes[IndexOfCaptureReadyLambda]);
+
+ // If VarToCapture is null, we are attempting to capture 'this'
+ const bool IsCapturingThis = !VarToCapture;
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.
+ // Check if the capture-ready lambda can truly capture the variable, by
+ // checking whether all enclosing lambdas of the capture-ready lambda allow
+ // the capture - i.e. make sure it is capture-capable.
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;
+ const bool CanCaptureVariable =
+ !S.tryCaptureVariable(VarToCapture,
+ /*ExprVarIsUsedInLoc*/ SourceLocation(),
+ clang::Sema::TryCapture_Implicit,
+ /*EllipsisLoc*/ SourceLocation(),
+ /*BuildAndDiagnose*/ false, CaptureType,
+ DeclRefType, &IndexOfCaptureReadyLambda);
+ if (!CanCaptureVariable)
+ return NoLambdaIsCaptureCapable;
+ } else {
+ // Check if the capture-ready lambda can truly capture 'this' by checking
+ // whether all enclosing lambdas of the capture-ready lambda can capture
+ // 'this'.
+ const bool CanCaptureThis =
+ !S.CheckCXXThisCapture(
+ CaptureReadyLambdaLSI->PotentialThisCaptureLocation,
+ /*Explicit*/ false, /*BuildAndDiagnose*/ false,
+ &IndexOfCaptureReadyLambda);
+ if (!CanCaptureThis)
+ return NoLambdaIsCaptureCapable;
+ }
+ return IndexOfCaptureReadyLambda;
}
static inline TemplateParameterList *
@@ -142,17 +232,14 @@
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);
+ 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,
@@ -169,7 +256,7 @@
IsGenericLambda,
CaptureDefault);
DC->addDecl(Class);
-
+
return Class;
}
@@ -277,10 +364,10 @@
// dependent type.
if (Class->isDependentContext() || TemplateParams) {
const FunctionProtoType *FPT = MethodType->castAs<FunctionProtoType>();
- QualType Result = FPT->getResultType();
+ QualType Result = FPT->getReturnType();
if (Result->isUndeducedType()) {
Result = SubstAutoType(Result, Context.DependentTy);
- MethodType = Context.getFunctionType(Result, FPT->getArgTypes(),
+ MethodType = Context.getFunctionType(Result, FPT->getParamTypes(),
FPT->getExtProtoInfo());
}
}
@@ -331,10 +418,8 @@
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);
+ for (auto P : Method->params())
+ P->setOwningFunction(Method);
}
Decl *ManglingContextDecl;
@@ -369,8 +454,8 @@
LSI->Mutable = Mutable;
if (ExplicitResultType) {
- LSI->ReturnType = CallOperator->getResultType();
-
+ LSI->ReturnType = CallOperator->getReturnType();
+
if (!LSI->ReturnType->isDependentType() &&
!LSI->ReturnType->isVoidType()) {
if (RequireCompleteType(CallOperator->getLocStart(), LSI->ReturnType,
@@ -651,6 +736,9 @@
return QualType();
} else {
DeduceInit = CXXDirectInit->getExpr(0);
+ if (isa<InitListExpr>(DeduceInit))
+ Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_paren_braces)
+ << DeclarationName(Id) << Loc;
}
}
@@ -811,14 +899,13 @@
ExplicitResultType = FTI.hasTrailingReturnType();
- if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
- cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
+ if (FTI.NumParams == 1 && !FTI.isVariadic && FTI.Params[0].Ident == 0 &&
+ cast<ParmVarDecl>(FTI.Params[0].Param)->getType()->isVoidType()) {
// Empty arg list, don't push any params.
- checkVoidParamDecl(cast<ParmVarDecl>(FTI.ArgInfo[0].Param));
} else {
- Params.reserve(FTI.NumArgs);
- for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
- Params.push_back(cast<ParmVarDecl>(FTI.ArgInfo[i].Param));
+ Params.reserve(FTI.NumParams);
+ for (unsigned i = 0, e = FTI.NumParams; i != e; ++i)
+ Params.push_back(cast<ParmVarDecl>(FTI.Params[i].Param));
}
// Check for unexpanded parameter packs in the method type.
@@ -848,6 +935,23 @@
ExplicitResultType,
!Method->isConst());
+ // C++11 [expr.prim.lambda]p9:
+ // A lambda-expression whose smallest enclosing scope is a block scope is a
+ // local lambda expression; any other lambda expression shall not have a
+ // capture-default or simple-capture in its lambda-introducer.
+ //
+ // For simple-captures, this is covered by the check below that any named
+ // entity is a variable that can be captured.
+ //
+ // For DR1632, we also allow a capture-default in any context where we can
+ // odr-use 'this' (in particular, in a default initializer for a non-static
+ // data member).
+ if (Intro.Default != LCD_None && !Class->getParent()->isFunctionOrMethod() &&
+ (getCurrentThisType().isNull() ||
+ CheckCXXThisCapture(SourceLocation(), /*Explicit*/true,
+ /*BuildAndDiagnose*/false)))
+ Diag(Intro.DefaultLoc, diag::err_capture_default_non_local);
+
// Distinct capture names, for diagnostics.
llvm::SmallSet<IdentifierInfo*, 8> CaptureNames;
@@ -958,6 +1062,8 @@
}
Var = R.getAsSingle<VarDecl>();
+ if (Var && DiagnoseUseOfDecl(Var, C->Loc))
+ continue;
}
// C++11 [expr.prim.lambda]p8:
@@ -1045,12 +1151,9 @@
LambdaScopeInfo *LSI = getCurLambda();
CXXRecordDecl *Class = LSI->Lambda;
Class->setInvalidDecl();
- SmallVector<Decl*, 4> Fields;
- for (RecordDecl::field_iterator i = Class->field_begin(),
- e = Class->field_end(); i != e; ++i)
- Fields.push_back(*i);
- ActOnFields(0, Class->getLocation(), Class, Fields,
- SourceLocation(), SourceLocation(), 0);
+ SmallVector<Decl*, 4> Fields(Class->fields());
+ ActOnFields(0, Class->getLocation(), Class, Fields, SourceLocation(),
+ SourceLocation(), 0);
CheckCompletedCXXClass(Class);
PopFunctionScopeInfo();
@@ -1077,8 +1180,9 @@
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);
+ InvokerFunctionTy =
+ S.Context.getFunctionType(CallOpProto->getReturnType(),
+ CallOpProto->getParamTypes(), InvokerExtInfo);
PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy);
}
@@ -1122,7 +1226,7 @@
ConvTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
// Get the result of the conversion function which is a pointer-to-function.
PointerTypeLoc PtrToFunctionTL =
- ConvTL.getResultLoc().getAs<PointerTypeLoc>();
+ ConvTL.getReturnLoc().getAs<PointerTypeLoc>();
// Do the same for the TypeSourceInfo that is used to name the conversion
// operator.
PointerTypeLoc ConvNamePtrToFunctionTL =
@@ -1157,8 +1261,8 @@
From->getTypeSourceInfo(),
From->getStorageClass(),
/*DefaultArg=*/0));
- CallOpConvTL.setArg(I, From);
- CallOpConvNameTL.setArg(I, From);
+ CallOpConvTL.setParam(I, From);
+ CallOpConvNameTL.setParam(I, From);
}
CXXConversionDecl *Conversion
@@ -1244,7 +1348,7 @@
FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
ExtInfo.TypeQuals = 0;
QualType FunctionTy = S.Context.getFunctionType(
- Proto->getResultType(), Proto->getArgTypes(), ExtInfo);
+ Proto->getReturnType(), Proto->getParamTypes(), ExtInfo);
BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);
}
@@ -1369,7 +1473,7 @@
const FunctionProtoType *Proto
= CallOperator->getType()->getAs<FunctionProtoType>();
QualType FunctionTy = Context.getFunctionType(
- LSI->ReturnType, Proto->getArgTypes(), Proto->getExtProtoInfo());
+ LSI->ReturnType, Proto->getParamTypes(), Proto->getExtProtoInfo());
CallOperator->setType(FunctionTy);
}
// C++ [expr.prim.lambda]p7:
@@ -1407,12 +1511,9 @@
addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator);
// Finalize the lambda class.
- SmallVector<Decl*, 4> Fields;
- for (RecordDecl::field_iterator i = Class->field_begin(),
- e = Class->field_end(); i != e; ++i)
- Fields.push_back(*i);
- ActOnFields(0, Class->getLocation(), Class, Fields,
- SourceLocation(), SourceLocation(), 0);
+ SmallVector<Decl*, 4> Fields(Class->fields());
+ ActOnFields(0, Class->getLocation(), Class, Fields, SourceLocation(),
+ SourceLocation(), 0);
CheckCompletedCXXClass(Class);
}
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 919c6ad..ac6fb25 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -113,10 +113,8 @@
if (Ctx && Ctx->isFileContext()) {
visit(Ctx, Ctx);
} else if (!Ctx || Ctx->isFunctionOrMethod()) {
- Scope::udir_iterator I = S->using_directives_begin(),
- End = S->using_directives_end();
- for (; I != End; ++I)
- visit(*I, InnermostFileDC);
+ for (auto *I : S->using_directives())
+ visit(I, InnermostFileDC);
}
}
}
@@ -153,9 +151,7 @@
void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) {
SmallVector<DeclContext*,4> queue;
while (true) {
- DeclContext::udir_iterator I, End;
- for (llvm::tie(I, End) = DC->getUsingDirectives(); I != End; ++I) {
- UsingDirectiveDecl *UD = *I;
+ for (auto UD : DC->using_directives()) {
DeclContext *NS = UD->getNominatedNamespace();
if (visited.insert(NS)) {
addUsingDirective(UD, EffectiveDC);
@@ -288,36 +284,33 @@
IDNS = getIDNS(LookupKind, SemaRef.getLangOpts().CPlusPlus,
isForRedeclaration());
- if (!isForRedeclaration()) {
- // If we're looking for one of the allocation or deallocation
- // operators, make sure that the implicitly-declared new and delete
- // operators can be found.
- switch (NameInfo.getName().getCXXOverloadedOperator()) {
- case OO_New:
- case OO_Delete:
- case OO_Array_New:
- case OO_Array_Delete:
- SemaRef.DeclareGlobalNewDelete();
- break;
+ // If we're looking for one of the allocation or deallocation
+ // operators, make sure that the implicitly-declared new and delete
+ // operators can be found.
+ switch (NameInfo.getName().getCXXOverloadedOperator()) {
+ case OO_New:
+ case OO_Delete:
+ case OO_Array_New:
+ case OO_Array_Delete:
+ SemaRef.DeclareGlobalNewDelete();
+ break;
- default:
- break;
- }
+ default:
+ break;
+ }
- // Compiler builtins are always visible, regardless of where they end
- // up being declared.
- if (IdentifierInfo *Id = NameInfo.getName().getAsIdentifierInfo()) {
- if (unsigned BuiltinID = Id->getBuiltinID()) {
- if (!SemaRef.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
- AllowHidden = true;
- }
+ // Compiler builtins are always visible, regardless of where they end
+ // up being declared.
+ if (IdentifierInfo *Id = NameInfo.getName().getAsIdentifierInfo()) {
+ if (unsigned BuiltinID = Id->getBuiltinID()) {
+ if (!SemaRef.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+ AllowHidden = true;
}
}
}
-void LookupResult::sanityImpl() const {
- // Note that this function is never called by NDEBUG builds. See
- // LookupResult::sanity().
+bool LookupResult::sanity() const {
+ // This function is never called by NDEBUG builds.
assert(ResultKind != NotFound || Decls.size() == 0);
assert(ResultKind != Found || Decls.size() == 1);
assert(ResultKind != FoundOverloaded || Decls.size() > 1 ||
@@ -330,6 +323,7 @@
assert((Paths != NULL) == (ResultKind == Ambiguous &&
(Ambiguity == AmbiguousBaseSubobjectTypes ||
Ambiguity == AmbiguousBaseSubobjects)));
+ return true;
}
// Necessary because CXXBasePaths is not complete in Sema.h
@@ -544,14 +538,6 @@
R.addDecl(D);
return true;
}
-
- if (R.isForRedeclaration()) {
- // If we're redeclaring this function anyway, forget that
- // this was a builtin at all.
- S.Context.BuiltinInfo.ForgetBuiltin(BuiltinID, S.Context.Idents);
- }
-
- return false;
}
}
}
@@ -777,7 +763,7 @@
// Perform direct name lookup into the namespaces nominated by the
// using directives whose common ancestor is this namespace.
UnqualUsingDirectiveSet::const_iterator UI, UEnd;
- llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS);
+ std::tie(UI, UEnd) = UDirs.getNamespacesFor(NS);
for (; UI != UEnd; ++UI)
if (LookupDirect(S, R, UI->getNominatedNamespace()))
@@ -989,7 +975,7 @@
if (Ctx) {
DeclContext *OuterCtx;
bool SearchAfterTemplateScope;
- llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
+ std::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
if (SearchAfterTemplateScope)
OutsideOfTemplateParamDC = OuterCtx;
@@ -1132,7 +1118,7 @@
if (Ctx) {
DeclContext *OuterCtx;
bool SearchAfterTemplateScope;
- llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
+ std::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
if (SearchAfterTemplateScope)
OutsideOfTemplateParamDC = OuterCtx;
@@ -1278,9 +1264,8 @@
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)) {
+ for (auto RD : D->redecls()) {
+ if (auto ND = dyn_cast<NamedDecl>(RD)) {
if (LookupResult::isVisible(SemaRef, ND))
return ND;
}
@@ -1462,10 +1447,8 @@
DeclContext *StartDC) {
assert(StartDC->isFileContext() && "start context is not a file context");
- DeclContext::udir_iterator I = StartDC->using_directives_begin();
- DeclContext::udir_iterator E = StartDC->using_directives_end();
-
- if (I == E) return false;
+ DeclContext::udir_range UsingDirectives = StartDC->using_directives();
+ if (UsingDirectives.begin() == UsingDirectives.end()) return false;
// We have at least added all these contexts to the queue.
llvm::SmallPtrSet<DeclContext*, 8> Visited;
@@ -1477,8 +1460,8 @@
// We have already looked into the initial namespace; seed the queue
// with its using-children.
- for (; I != E; ++I) {
- NamespaceDecl *ND = (*I)->getNominatedNamespace()->getOriginalNamespace();
+ for (auto *I : UsingDirectives) {
+ NamespaceDecl *ND = I->getNominatedNamespace()->getOriginalNamespace();
if (Visited.insert(ND))
Queue.push_back(ND);
}
@@ -1525,8 +1508,8 @@
continue;
}
- for (llvm::tie(I,E) = ND->getUsingDirectives(); I != E; ++I) {
- NamespaceDecl *Nom = (*I)->getNominatedNamespace();
+ for (auto I : ND->using_directives()) {
+ NamespaceDecl *Nom = I->getNominatedNamespace();
if (Visited.insert(Nom))
Queue.push_back(Nom);
}
@@ -2039,6 +2022,10 @@
// Add the class itself. If we've already seen this class, we don't
// need to visit base classes.
+ //
+ // FIXME: That's not correct, we may have added this class only because it
+ // was the enclosing class of another class, and in that case we won't have
+ // added its base classes yet.
if (!Result.Classes.insert(Class))
return;
@@ -2065,12 +2052,8 @@
}
// Only recurse into base classes for complete types.
- if (!Class->hasDefinition()) {
- QualType type = Result.S.Context.getTypeDeclType(Class);
- if (Result.S.RequireCompleteType(Result.InstantiationLoc, type,
- /*no diagnostic*/ 0))
- return;
- }
+ if (!Class->hasDefinition())
+ return;
// Add direct and indirect base classes along with their associated
// namespaces.
@@ -2081,10 +2064,8 @@
Class = Bases.pop_back_val();
// Visit the base classes.
- for (CXXRecordDecl::base_class_iterator Base = Class->bases_begin(),
- BaseEnd = Class->bases_end();
- Base != BaseEnd; ++Base) {
- const RecordType *BaseType = Base->getType()->getAs<RecordType>();
+ for (const auto &Base : Class->bases()) {
+ const RecordType *BaseType = Base.getType()->getAs<RecordType>();
// In dependent contexts, we do ADL twice, and the first time around,
// the base type might be a dependent TemplateSpecializationType, or a
// TemplateTypeParmType. If that happens, simply ignore it.
@@ -2164,6 +2145,8 @@
// classes. Its associated namespaces are the namespaces in
// which its associated classes are defined.
case Type::Record: {
+ Result.S.RequireCompleteType(Result.InstantiationLoc, QualType(T, 0),
+ /*no diagnostic*/ 0);
CXXRecordDecl *Class
= cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl());
addAssociatedClassesAndNamespaces(Result, Class);
@@ -2192,15 +2175,13 @@
// types and those associated with the return type.
case Type::FunctionProto: {
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
- for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
- ArgEnd = Proto->arg_type_end();
- Arg != ArgEnd; ++Arg)
- Queue.push_back(Arg->getTypePtr());
+ for (const auto &Arg : Proto->param_types())
+ Queue.push_back(Arg.getTypePtr());
// fallthrough
}
case Type::FunctionNoProto: {
const FunctionType *FnType = cast<FunctionType>(T);
- T = FnType->getResultType().getTypePtr();
+ T = FnType->getReturnType().getTypePtr();
continue;
}
@@ -2318,11 +2299,7 @@
for (UnresolvedSetIterator I = ULE->decls_begin(), E = ULE->decls_end();
I != E; ++I) {
// Look through any using declarations to find the underlying function.
- NamedDecl *Fn = (*I)->getUnderlyingDecl();
-
- FunctionDecl *FDecl = dyn_cast<FunctionDecl>(Fn);
- if (!FDecl)
- FDecl = cast<FunctionTemplateDecl>(Fn)->getTemplatedDecl();
+ FunctionDecl *FDecl = (*I)->getUnderlyingDecl()->getAsFunction();
// Add the classes and namespaces associated with the parameter
// types and return type of this function.
@@ -2347,20 +2324,20 @@
return true;
const FunctionProtoType *Proto = Fn->getType()->getAs<FunctionProtoType>();
- if (Proto->getNumArgs() < 1)
+ if (Proto->getNumParams() < 1)
return false;
if (T1->isEnumeralType()) {
- QualType ArgType = Proto->getArgType(0).getNonReferenceType();
+ QualType ArgType = Proto->getParamType(0).getNonReferenceType();
if (Context.hasSameUnqualifiedType(T1, ArgType))
return true;
}
- if (Proto->getNumArgs() < 2)
+ if (Proto->getNumParams() < 2)
return false;
if (!T2.isNull() && T2->isEnumeralType()) {
- QualType ArgType = Proto->getArgType(1).getNonReferenceType();
+ QualType ArgType = Proto->getParamType(1).getNonReferenceType();
if (Context.hasSameUnqualifiedType(T2, ArgType))
return true;
}
@@ -2545,7 +2522,7 @@
// Now we perform lookup on the name we computed earlier and do overload
// resolution. Lookup is only performed directly into the class since there
// will always be a (possibly implicit) declaration to shadow any others.
- OverloadCandidateSet OCS((SourceLocation()));
+ OverloadCandidateSet OCS(RD->getLocation());
DeclContext::lookup_result R = RD->lookup(Name);
assert(!R.empty() &&
"lookup for a constructor or assignment operator was empty");
@@ -2812,14 +2789,8 @@
// operator template, but not both.
if (FoundRaw && FoundTemplate) {
Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName();
- for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
- Decl *D = *I;
- if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
- D = USD->getTargetDecl();
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
- D = FunTmpl->getTemplatedDecl();
- NoteOverloadCandidate(cast<FunctionDecl>(D));
- }
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+ NoteOverloadCandidate((*I)->getUnderlyingDecl()->getAsFunction());
return LOLR_Error;
}
@@ -2851,14 +2822,8 @@
}
// Otherwise, decide which is a more recent redeclaration.
- FunctionDecl *OldFD, *NewFD;
- if (isa<FunctionTemplateDecl>(New)) {
- OldFD = cast<FunctionTemplateDecl>(Old)->getTemplatedDecl();
- NewFD = cast<FunctionTemplateDecl>(New)->getTemplatedDecl();
- } else {
- OldFD = cast<FunctionDecl>(Old);
- NewFD = cast<FunctionDecl>(New);
- }
+ FunctionDecl *OldFD = Old->getAsFunction();
+ FunctionDecl *NewFD = New->getAsFunction();
FunctionDecl *Cursor = NewFD;
while (true) {
@@ -3063,8 +3028,8 @@
// Functions and function templates in the same scope overload
// rather than hide. FIXME: Look for hiding based on function
// signatures!
- if ((*I)->isFunctionOrFunctionTemplate() &&
- ND->isFunctionOrFunctionTemplate() &&
+ if ((*I)->getUnderlyingDecl()->isFunctionOrFunctionTemplate() &&
+ ND->getUnderlyingDecl()->isFunctionOrFunctionTemplate() &&
SM == ShadowMaps.rbegin())
continue;
@@ -3092,13 +3057,9 @@
Result.getSema().ForceDeclarationOfImplicitMembers(Class);
// Enumerate all of the results in this context.
- for (DeclContext::all_lookups_iterator L = Ctx->lookups_begin(),
- LEnd = Ctx->lookups_end();
- L != LEnd; ++L) {
- DeclContext::lookup_result R = *L;
- for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
- ++I) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(*I)) {
+ for (const auto &R : Ctx->lookups()) {
+ for (auto *I : R) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(I)) {
if ((ND = Result.getAcceptableDecl(ND))) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
Visited.add(ND);
@@ -3110,9 +3071,8 @@
// Traverse using directives for qualified name lookup.
if (QualifiedNameLookup) {
ShadowContextRAII Shadow(Visited);
- DeclContext::udir_iterator I, E;
- for (llvm::tie(I, E) = Ctx->getUsingDirectives(); I != E; ++I) {
- LookupVisibleDecls((*I)->getNominatedNamespace(), Result,
+ for (auto I : Ctx->using_directives()) {
+ LookupVisibleDecls(I->getNominatedNamespace(), Result,
QualifiedNameLookup, InBaseClass, Consumer, Visited);
}
}
@@ -3122,10 +3082,8 @@
if (!Record->hasDefinition())
return;
- for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
- BEnd = Record->bases_end();
- B != BEnd; ++B) {
- QualType BaseType = B->getType();
+ for (const auto &B : Record->bases()) {
+ QualType BaseType = B.getType();
// Don't look into dependent bases, because name lookup can't look
// there anyway.
@@ -3165,21 +3123,16 @@
// Traverse the contexts of Objective-C classes.
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Ctx)) {
// Traverse categories.
- for (ObjCInterfaceDecl::visible_categories_iterator
- Cat = IFace->visible_categories_begin(),
- CatEnd = IFace->visible_categories_end();
- Cat != CatEnd; ++Cat) {
+ for (auto *Cat : IFace->visible_categories()) {
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(*Cat, Result, QualifiedNameLookup, false,
+ LookupVisibleDecls(Cat, Result, QualifiedNameLookup, false,
Consumer, Visited);
}
// Traverse protocols.
- for (ObjCInterfaceDecl::all_protocol_iterator
- I = IFace->all_referenced_protocol_begin(),
- E = IFace->all_referenced_protocol_end(); I != E; ++I) {
+ for (auto *I : IFace->all_referenced_protocols()) {
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
+ LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer,
Visited);
}
@@ -3198,17 +3151,15 @@
QualifiedNameLookup, InBaseClass, Consumer, Visited);
}
} else if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Ctx)) {
- for (ObjCProtocolDecl::protocol_iterator I = Protocol->protocol_begin(),
- E = Protocol->protocol_end(); I != E; ++I) {
+ for (auto *I : Protocol->protocols()) {
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
+ LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer,
Visited);
}
} else if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Ctx)) {
- for (ObjCCategoryDecl::protocol_iterator I = Category->protocol_begin(),
- E = Category->protocol_end(); I != E; ++I) {
+ for (auto *I : Category->protocols()) {
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
+ LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer,
Visited);
}
@@ -3234,9 +3185,8 @@
(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) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
+ for (auto *D : S->decls()) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
if ((ND = Result.getAcceptableDecl(ND))) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), 0, false);
Visited.add(ND);
@@ -3297,7 +3247,7 @@
// Lookup visible declarations in any namespaces found by using
// directives.
UnqualUsingDirectiveSet::const_iterator UI, UEnd;
- llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity);
+ std::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity);
for (; UI != UEnd; ++UI)
LookupVisibleDecls(const_cast<DeclContext *>(UI->getNominatedNamespace()),
Result, /*QualifiedNameLookup=*/false,
@@ -3411,10 +3361,10 @@
: Typo(Typo->getName()),
SemaRef(SemaRef) {}
- bool includeHiddenDecls() const { return true; }
+ bool includeHiddenDecls() const override { return true; }
- virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
- bool InBaseClass);
+ void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+ bool InBaseClass) override;
void FoundName(StringRef Name);
void addKeywordResult(StringRef Keyword);
void addName(StringRef Name, NamedDecl *ND, NestedNameSpecifier *NNS = NULL,
@@ -3528,7 +3478,7 @@
CList.push_back(Correction);
while (CorrectionResults.size() > MaxTypoDistanceResultSets)
- erase(llvm::prior(CorrectionResults.end()));
+ erase(std::prev(CorrectionResults.end()));
}
// Fill the supplied vector with the IdentifierInfo pointers for each piece of
@@ -4064,7 +4014,7 @@
// In Microsoft mode, don't perform typo correction in a template member
// function dependent context because it interferes with the "lookup into
// dependent bases of class templates" feature.
- if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() &&
+ if (getLangOpts().MSVCCompat && CurContext->isDependentContext() &&
isa<CXXMethodDecl>(CurContext))
return TypoCorrection();
@@ -4116,10 +4066,8 @@
// Look in qualified interfaces.
if (OPT) {
- for (ObjCObjectPointerType::qual_iterator
- I = OPT->qual_begin(), E = OPT->qual_end();
- I != E; ++I)
- LookupVisibleDecls(*I, LookupKind, Consumer);
+ for (auto *I : OPT->quals())
+ LookupVisibleDecls(I, LookupKind, Consumer);
}
} else if (SS && SS->isSet()) {
QualifiedDC = computeDeclContext(*SS, EnteringContext);
@@ -4191,7 +4139,7 @@
// FIXME: Re-add the ability to skip very unlikely potential corrections.
if (IdentifierInfoLookup *External
= Context.Idents.getExternalIdentifierLookup()) {
- OwningPtr<IdentifierIterator> Iter(External->getIdentifiers());
+ std::unique_ptr<IdentifierIterator> Iter(External->getIdentifiers());
do {
StringRef Name = Iter->Next();
if (Name.empty())
@@ -4228,19 +4176,21 @@
KnownNamespaces[ExternalKnownNamespaces[I]] = true;
}
- for (llvm::MapVector<NamespaceDecl*, bool>::iterator
- KNI = KnownNamespaces.begin(),
- KNIEnd = KnownNamespaces.end();
- KNI != KNIEnd; ++KNI)
- Namespaces.AddNameSpecifier(KNI->first);
+ for (auto KNPair : KnownNamespaces)
+ Namespaces.AddNameSpecifier(KNPair.first);
- for (ASTContext::type_iterator TI = Context.types_begin(),
- TIEnd = Context.types_end();
- TI != TIEnd; ++TI) {
- if (CXXRecordDecl *CD = (*TI)->getAsCXXRecordDecl()) {
+ bool SSIsTemplate = false;
+ if (NestedNameSpecifier *NNS =
+ (SS && SS->isValid()) ? SS->getScopeRep() : 0) {
+ if (const Type *T = NNS->getAsType())
+ SSIsTemplate = T->getTypeClass() == Type::TemplateSpecialization;
+ }
+ for (const auto *TI : Context.types()) {
+ if (CXXRecordDecl *CD = TI->getAsCXXRecordDecl()) {
CD = CD->getCanonicalDecl();
if (!CD->isDependentType() && !CD->isAnonymousStructOrUnion() &&
- !CD->isUnion() &&
+ !CD->isUnion() && CD->getIdentifier() &&
+ (SSIsTemplate || !isa<ClassTemplateSpecializationDecl>(CD)) &&
(CD->isBeingDefined() || CD->isCompleteDefinition()))
Namespaces.AddNameSpecifier(CD);
}
@@ -4258,13 +4208,17 @@
IEnd = DI->second.end();
I != IEnd; /* Increment in loop. */) {
// If we only want nested name specifier corrections, ignore potential
- // corrections that have a different base identifier from the typo.
- if (AllowOnlyNNSChanges &&
- I->second.front().getCorrectionAsIdentifierInfo() != Typo) {
- TypoCorrectionConsumer::result_iterator Prev = I;
- ++I;
- DI->second.erase(Prev);
- continue;
+ // corrections that have a different base identifier from the typo or
+ // which have a normalized edit distance longer than the typo itself.
+ if (AllowOnlyNNSChanges) {
+ TypoCorrection &TC = I->second.front();
+ if (TC.getCorrectionAsIdentifierInfo() != Typo ||
+ TC.getEditDistance(true) > TypoLen) {
+ TypoCorrectionConsumer::result_iterator Prev = I;
+ ++I;
+ DI->second.erase(Prev);
+ continue;
+ }
}
// If the item already has been looked up or is a keyword, keep it.
@@ -4337,10 +4291,8 @@
case LookupResult::FoundOverloaded: {
TypoCorrectionConsumer::result_iterator Prev = I;
// Store all of the Decls for overloaded symbols
- for (LookupResult::iterator TRD = TmpRes.begin(),
- TRDEnd = TmpRes.end();
- TRD != TRDEnd; ++TRD)
- Candidate.addCorrectionDecl(*TRD);
+ for (auto *TRD : TmpRes)
+ Candidate.addCorrectionDecl(TRD);
++I;
if (!isCandidateViable(CCC, Candidate)) {
QualifiedResults.push_back(Candidate);
@@ -4372,15 +4324,10 @@
// Only perform the qualified lookups for C++
if (SearchNamespaces) {
TmpRes.suppressDiagnostics();
- for (SmallVector<TypoCorrection,
- 16>::iterator QRI = QualifiedResults.begin(),
- QRIEnd = QualifiedResults.end();
- QRI != QRIEnd; ++QRI) {
- for (NamespaceSpecifierSet::iterator NI = Namespaces.begin(),
- NIEnd = Namespaces.end();
- NI != NIEnd; ++NI) {
- DeclContext *Ctx = NI->DeclCtx;
- const Type *NSType = NI->NameSpecifier->getAsType();
+ for (auto QR : QualifiedResults) {
+ for (auto NSI : Namespaces) {
+ DeclContext *Ctx = NSI.DeclCtx;
+ const Type *NSType = NSI.NameSpecifier->getAsType();
// If the current NestedNameSpecifier refers to a class and the
// current correction candidate is the name of that class, then skip
@@ -4388,26 +4335,26 @@
// is an appropriate correction.
if (CXXRecordDecl *NSDecl =
NSType ? NSType->getAsCXXRecordDecl() : 0) {
- if (NSDecl->getIdentifier() == QRI->getCorrectionAsIdentifierInfo())
+ if (NSDecl->getIdentifier() == QR.getCorrectionAsIdentifierInfo())
continue;
}
- TypoCorrection TC(*QRI);
+ TypoCorrection TC(QR);
TC.ClearCorrectionDecls();
- TC.setCorrectionSpecifier(NI->NameSpecifier);
- TC.setQualifierDistance(NI->EditDistance);
+ TC.setCorrectionSpecifier(NSI.NameSpecifier);
+ TC.setQualifierDistance(NSI.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 &&
+ if (QR.getCorrectionAsIdentifierInfo() != Typo &&
TmpED && TypoLen / TmpED < 3)
continue;
TmpRes.clear();
- TmpRes.setLookupName(QRI->getCorrectionAsIdentifierInfo());
+ TmpRes.setLookupName(QR.getCorrectionAsIdentifierInfo());
if (!LookupQualifiedName(TmpRes, Ctx)) continue;
// Any corrections added below will be validated in subsequent
@@ -4563,8 +4510,11 @@
}
FunctionCallFilterCCC::FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs,
- bool HasExplicitTemplateArgs)
- : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs) {
+ bool HasExplicitTemplateArgs,
+ bool AllowNonStaticMethods)
+ : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs),
+ AllowNonStaticMethods(AllowNonStaticMethods),
+ CurContext(SemaRef.CurContext) {
WantTypeSpecifiers = SemaRef.getLangOpts().CPlusPlus;
WantRemainingKeywords = false;
}
@@ -4589,13 +4539,32 @@
if (ValType->isAnyPointerType() || ValType->isReferenceType())
ValType = ValType->getPointeeType();
if (const FunctionProtoType *FPT = ValType->getAs<FunctionProtoType>())
- if (FPT->getNumArgs() == NumArgs)
+ if (FPT->getNumParams() == NumArgs)
return true;
}
}
- if (FD && FD->getNumParams() >= NumArgs &&
- FD->getMinRequiredArguments() <= NumArgs)
- return true;
+
+ // Skip the current candidate if it is not a FunctionDecl or does not accept
+ // the current number of arguments.
+ if (!FD || !(FD->getNumParams() >= NumArgs &&
+ FD->getMinRequiredArguments() <= NumArgs))
+ continue;
+
+ // If the current candidate is a non-static C++ method and non-static
+ // methods are being excluded, then skip the candidate unless the current
+ // DeclContext is a method in the same class or a descendent class of the
+ // candidate's parent class.
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (!AllowNonStaticMethods && !MD->isStatic()) {
+ CXXMethodDecl *CurMD = dyn_cast_or_null<CXXMethodDecl>(CurContext);
+ CXXRecordDecl *CurRD =
+ CurMD ? CurMD->getParent()->getCanonicalDecl() : 0;
+ CXXRecordDecl *RD = MD->getParent()->getCanonicalDecl();
+ if (!CurRD || (CurRD != RD && !CurRD->isDerivedFrom(RD)))
+ continue;
+ }
+ }
+ return true;
}
return false;
}
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index d9d9cec..3f37efa 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -132,11 +132,8 @@
}
// Check this property against any protocols we inherit.
- for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
- PEnd = Proto->protocol_end();
- P != PEnd; ++P) {
- CheckPropertyAgainstProtocol(S, Prop, *P, Known);
- }
+ for (auto *P : Proto->protocols())
+ CheckPropertyAgainstProtocol(S, Prop, P, Known);
}
Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
@@ -204,7 +201,8 @@
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
// For a class, compare the property against a property in our superclass.
bool FoundInSuper = false;
- if (ObjCInterfaceDecl *Super = IFace->getSuperClass()) {
+ ObjCInterfaceDecl *CurrentInterfaceDecl = IFace;
+ while (ObjCInterfaceDecl *Super = CurrentInterfaceDecl->getSuperClass()) {
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])) {
@@ -213,37 +211,30 @@
break;
}
}
+ if (FoundInSuper)
+ break;
+ else
+ CurrentInterfaceDecl = Super;
}
if (FoundInSuper) {
// Also compare the property against a property in our protocols.
- for (ObjCInterfaceDecl::protocol_iterator P = IFace->protocol_begin(),
- PEnd = IFace->protocol_end();
- P != PEnd; ++P) {
- CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
+ for (auto *P : CurrentInterfaceDecl->protocols()) {
+ CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
}
} else {
// Slower path: look in all protocols we referenced.
- for (ObjCInterfaceDecl::all_protocol_iterator
- P = IFace->all_referenced_protocol_begin(),
- PEnd = IFace->all_referenced_protocol_end();
- P != PEnd; ++P) {
- CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
+ for (auto *P : IFace->all_referenced_protocols()) {
+ CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
}
}
} else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
- for (ObjCCategoryDecl::protocol_iterator P = Cat->protocol_begin(),
- PEnd = Cat->protocol_end();
- P != PEnd; ++P) {
- CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
- }
+ for (auto *P : Cat->protocols())
+ CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
} else {
ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl);
- for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
- PEnd = Proto->protocol_end();
- P != PEnd; ++P) {
- CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
- }
+ for (auto *P : Proto->protocols())
+ CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
}
ActOnDocumentableDecl(Res);
@@ -321,21 +312,6 @@
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,
@@ -358,12 +334,9 @@
if (CCPrimary) {
// Check for duplicate declaration of this property in current and
// other class extensions.
- for (ObjCInterfaceDecl::known_extensions_iterator
- Ext = CCPrimary->known_extensions_begin(),
- ExtEnd = CCPrimary->known_extensions_end();
- Ext != ExtEnd; ++Ext) {
+ for (const auto *Ext : CCPrimary->known_extensions()) {
if (ObjCPropertyDecl *prevDecl
- = ObjCPropertyDecl::findPropertyDecl(*Ext, PropertyId)) {
+ = ObjCPropertyDecl::findPropertyDecl(Ext, PropertyId)) {
Diag(AtLoc, diag::err_duplicate_property);
Diag(prevDecl->getLocation(), diag::note_property_declare);
return 0;
@@ -478,6 +451,18 @@
DeclContext *DC = cast<DeclContext>(CCPrimary);
if (!ObjCPropertyDecl::findPropertyDecl(DC,
PIDecl->getDeclName().getAsIdentifierInfo())) {
+ // In mrr mode, 'readwrite' property must have an explicit
+ // memory attribute. If none specified, select the default (assign).
+ if (!getLangOpts().ObjCAutoRefCount) {
+ if (!(PIkind & (ObjCDeclSpec::DQ_PR_assign |
+ ObjCDeclSpec::DQ_PR_retain |
+ ObjCDeclSpec::DQ_PR_strong |
+ ObjCDeclSpec::DQ_PR_copy |
+ ObjCDeclSpec::DQ_PR_unsafe_unretained |
+ ObjCDeclSpec::DQ_PR_weak)))
+ PIkind |= ObjCPropertyDecl::OBJC_PR_assign;
+ }
+
// Protocol is not in the primary class. Must build one for it.
ObjCDeclSpec ProtocolPropertyODS;
// FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind
@@ -763,18 +748,14 @@
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())
+ for (const auto *PI : ClassDecl->all_referenced_protocols()) {
+ if (const ObjCProtocolDecl *PDecl = PI->getDefinition())
PDecl->collectInheritedProtocolProperties(Property, PropMap);
}
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())
+ for (const auto *PI : SDecl->all_referenced_protocols()) {
+ if (const ObjCProtocolDecl *PDecl = PI->getDefinition())
PDecl->collectInheritedProtocolProperties(Property, PropMap);
}
SDecl = SDecl->getSuperClass();
@@ -875,9 +856,7 @@
bool ReadWriteProperty = false;
// Search into the class extensions and see if 'readonly property is
// redeclared 'readwrite', then no warning is to be issued.
- for (ObjCInterfaceDecl::known_extensions_iterator
- Ext = IDecl->known_extensions_begin(),
- ExtEnd = IDecl->known_extensions_end(); Ext != ExtEnd; ++Ext) {
+ for (auto *Ext : IDecl->known_extensions()) {
DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
if (!R.empty())
if (ObjCPropertyDecl *ExtProp = dyn_cast<ObjCPropertyDecl>(R[0])) {
@@ -891,7 +870,7 @@
if (!ReadWriteProperty) {
Diag(property->getLocation(), diag::warn_auto_readonly_iboutlet_property)
- << property->getName();
+ << property;
SourceLocation readonlyLoc;
if (LocPropertyAttribute(Context, "readonly",
property->getLParenLoc(), readonlyLoc)) {
@@ -1163,19 +1142,20 @@
ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
DeclRefExpr *SelfExpr =
new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
- VK_RValue, PropertyDiagLoc);
+ VK_LValue, PropertyDiagLoc);
MarkDeclRefReferenced(SelfExpr);
+ Expr *LoadSelfExpr =
+ ImplicitCastExpr::Create(Context, SelfDecl->getType(),
+ CK_LValueToRValue, SelfExpr, 0, VK_RValue);
Expr *IvarRefExpr =
new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
Ivar->getLocation(),
- SelfExpr, true, true);
- ExprResult Res =
- PerformCopyInitialization(InitializedEntity::InitializeResult(
- PropertyDiagLoc,
- getterMethod->getResultType(),
- /*NRVO=*/false),
- PropertyDiagLoc,
- Owned(IvarRefExpr));
+ LoadSelfExpr, true, true);
+ ExprResult Res = PerformCopyInitialization(
+ InitializedEntity::InitializeResult(PropertyDiagLoc,
+ getterMethod->getReturnType(),
+ /*NRVO=*/false),
+ PropertyDiagLoc, Owned(IvarRefExpr));
if (!Res.isInvalid()) {
Expr *ResExpr = Res.takeAs<Expr>();
if (ResExpr)
@@ -1211,12 +1191,15 @@
ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
DeclRefExpr *SelfExpr =
new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
- VK_RValue, PropertyDiagLoc);
+ VK_LValue, PropertyDiagLoc);
MarkDeclRefReferenced(SelfExpr);
+ Expr *LoadSelfExpr =
+ ImplicitCastExpr::Create(Context, SelfDecl->getType(),
+ CK_LValueToRValue, SelfExpr, 0, VK_RValue);
Expr *lhs =
new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
Ivar->getLocation(),
- SelfExpr, true, true);
+ LoadSelfExpr, true, true);
ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
ParmVarDecl *Param = (*P);
QualType T = Param->getType().getNonReferenceType();
@@ -1394,7 +1377,7 @@
SourceLocation Loc) {
if (!GetterMethod)
return false;
- QualType GetterType = GetterMethod->getResultType().getNonReferenceType();
+ QualType GetterType = GetterMethod->getReturnType().getNonReferenceType();
QualType PropertyIvarType = property->getType().getNonReferenceType();
bool compat = Context.hasSameType(PropertyIvarType, GetterType);
if (!compat) {
@@ -1433,37 +1416,32 @@
/// 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,
- ObjCContainerDecl::PropertyMap &PropMap,
- ObjCContainerDecl::PropertyMap &SuperPropMap) {
+static void CollectImmediateProperties(ObjCContainerDecl *CDecl,
+ ObjCContainerDecl::PropertyMap &PropMap,
+ ObjCContainerDecl::PropertyMap &SuperPropMap,
+ bool IncludeProtocols = true) {
+
if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
- for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
- E = IDecl->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *Prop = *P;
+ for (auto *Prop : IDecl->properties())
PropMap[Prop->getIdentifier()] = Prop;
+ if (IncludeProtocols) {
+ // Scan through class's protocols.
+ for (auto *PI : IDecl->all_referenced_protocols())
+ CollectImmediateProperties(PI, PropMap, SuperPropMap);
}
- // scan through class's protocols.
- for (ObjCInterfaceDecl::all_protocol_iterator
- PI = IDecl->all_referenced_protocol_begin(),
- E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
- CollectImmediateProperties((*PI), PropMap, SuperPropMap);
}
if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
if (!CATDecl->IsClassExtension())
- for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
- E = CATDecl->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *Prop = *P;
+ for (auto *Prop : CATDecl->properties())
PropMap[Prop->getIdentifier()] = Prop;
- }
- // scan through class's protocols.
- for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(),
- E = CATDecl->protocol_end(); PI != E; ++PI)
- CollectImmediateProperties((*PI), PropMap, SuperPropMap);
+ if (IncludeProtocols) {
+ // Scan through class's protocols.
+ for (auto *PI : CATDecl->protocols())
+ CollectImmediateProperties(PI, PropMap, SuperPropMap);
+ }
}
else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
- for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
- E = PDecl->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *Prop = *P;
+ for (auto *Prop : PDecl->properties()) {
ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()];
// Exclude property for protocols which conform to class's super-class,
// as super-class has to implement the property.
@@ -1475,9 +1453,8 @@
}
}
// scan through protocol's protocols.
- for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
- E = PDecl->protocol_end(); PI != E; ++PI)
- CollectImmediateProperties((*PI), PropMap, SuperPropMap);
+ for (auto *PI : PDecl->protocols())
+ CollectImmediateProperties(PI, PropMap, SuperPropMap);
}
}
@@ -1510,17 +1487,35 @@
// look up a property declaration whose one of its accessors is implemented
// by this method.
- for (ObjCContainerDecl::prop_iterator P = IFace->prop_begin(),
- E = IFace->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *property = *P;
- if ((property->getGetterName() == IMD->getSelector() ||
- property->getSetterName() == IMD->getSelector()) &&
- (property->getPropertyIvarDecl() == IV))
+ for (const auto *Property : IFace->properties()) {
+ if ((Property->getGetterName() == IMD->getSelector() ||
+ Property->getSetterName() == IMD->getSelector()) &&
+ (Property->getPropertyIvarDecl() == IV))
return true;
}
return false;
}
+static bool SuperClassImplementsProperty(ObjCInterfaceDecl *IDecl,
+ ObjCPropertyDecl *Prop) {
+ bool SuperClassImplementsGetter = false;
+ bool SuperClassImplementsSetter = false;
+ if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
+ SuperClassImplementsSetter = true;
+
+ while (IDecl->getSuperClass()) {
+ ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
+ if (!SuperClassImplementsGetter && SDecl->getInstanceMethod(Prop->getGetterName()))
+ SuperClassImplementsGetter = true;
+
+ if (!SuperClassImplementsSetter && SDecl->getInstanceMethod(Prop->getSetterName()))
+ SuperClassImplementsSetter = true;
+ if (SuperClassImplementsGetter && SuperClassImplementsSetter)
+ return true;
+ IDecl = IDecl->getSuperClass();
+ }
+ return false;
+}
/// \brief Default synthesizes all properties which must be synthesized
/// in class's \@implementation.
@@ -1559,7 +1554,7 @@
!IMPDecl->getInstanceMethod(Prop->getSetterName()) &&
!IDecl->HasUserDeclaredSetterMethod(Prop)) {
Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property)
- << Prop->getIdentifier()->getName();
+ << Prop->getIdentifier();
Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
}
continue;
@@ -1568,17 +1563,23 @@
IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) {
if (PID->getPropertyDecl() != Prop) {
Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property)
- << Prop->getIdentifier()->getName();
+ << Prop->getIdentifier();
if (!PID->getLocation().isInvalid())
Diag(PID->getLocation(), diag::note_property_synthesize);
}
continue;
}
- if (isa<ObjCProtocolDecl>(Prop->getDeclContext())) {
+ if (ObjCProtocolDecl *Proto =
+ dyn_cast<ObjCProtocolDecl>(Prop->getDeclContext())) {
// We won't auto-synthesize properties declared in protocols.
- Diag(IMPDecl->getLocation(),
- diag::warn_auto_synthesizing_protocol_property);
- Diag(Prop->getLocation(), diag::note_property_declare);
+ // Suppress the warning if class's superclass implements property's
+ // getter and implements property's setter (if readwrite property).
+ if (!SuperClassImplementsProperty(IDecl, Prop)) {
+ Diag(IMPDecl->getLocation(),
+ diag::warn_auto_synthesizing_protocol_property)
+ << Prop << Proto;
+ Diag(Prop->getLocation(), diag::note_property_declare);
+ }
continue;
}
@@ -1610,41 +1611,105 @@
DefaultSynthesizeProperties(S, IC, IDecl);
}
+static void DiagnoseUnimplementedAccessor(Sema &S,
+ ObjCInterfaceDecl *PrimaryClass,
+ Selector Method,
+ ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl *CDecl,
+ ObjCCategoryDecl *C,
+ ObjCPropertyDecl *Prop,
+ Sema::SelectorSet &SMap) {
+ // When reporting on missing property setter/getter implementation in
+ // categories, do not report when they are declared in primary class,
+ // class's protocol, or one of it super classes. This is because,
+ // the class is going to implement them.
+ if (!SMap.count(Method) &&
+ (PrimaryClass == 0 ||
+ !PrimaryClass->lookupPropertyAccessor(Method, C))) {
+ S.Diag(IMPDecl->getLocation(),
+ isa<ObjCCategoryDecl>(CDecl) ?
+ diag::warn_setter_getter_impl_required_in_category :
+ diag::warn_setter_getter_impl_required)
+ << Prop->getDeclName() << Method;
+ S.Diag(Prop->getLocation(),
+ diag::note_property_declare);
+ if (S.LangOpts.ObjCDefaultSynthProperties &&
+ S.LangOpts.ObjCRuntime.isNonFragile())
+ if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
+ if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
+ S.Diag(RID->getLocation(), diag::note_suppressed_class_declare);
+ }
+}
+
void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
- ObjCContainerDecl *CDecl) {
- ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
- ObjCInterfaceDecl *IDecl;
- // Gather properties which need not be implemented in this class
- // or category.
- if (!(IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)))
- if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
- // For categories, no need to implement properties declared in
- // its primary class (and its super classes) if property is
- // declared in one of those containers.
- if ((IDecl = C->getClassInterface())) {
- ObjCInterfaceDecl::PropertyDeclOrder PO;
- IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO);
+ ObjCContainerDecl *CDecl,
+ bool SynthesizeProperties) {
+ ObjCContainerDecl::PropertyMap PropMap;
+ ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
+
+ if (!SynthesizeProperties) {
+ ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
+ // Gather properties which need not be implemented in this class
+ // or category.
+ if (!IDecl)
+ if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+ // For categories, no need to implement properties declared in
+ // its primary class (and its super classes) if property is
+ // declared in one of those containers.
+ if ((IDecl = C->getClassInterface())) {
+ ObjCInterfaceDecl::PropertyDeclOrder PO;
+ IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO);
+ }
+ }
+ if (IDecl)
+ CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap);
+
+ CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap);
+ }
+
+ // Scan the @interface to see if any of the protocols it adopts
+ // require an explicit implementation, via attribute
+ // 'objc_protocol_requires_explicit_implementation'.
+ if (IDecl) {
+ std::unique_ptr<ObjCContainerDecl::PropertyMap> LazyMap;
+
+ for (auto *PDecl : IDecl->all_referenced_protocols()) {
+ if (!PDecl->hasAttr<ObjCExplicitProtocolImplAttr>())
+ continue;
+ // Lazily construct a set of all the properties in the @interface
+ // of the class, without looking at the superclass. We cannot
+ // use the call to CollectImmediateProperties() above as that
+ // utilizes information fromt he super class's properties as well
+ // as scans the adopted protocols. This work only triggers for protocols
+ // with the attribute, which is very rare, and only occurs when
+ // analyzing the @implementation.
+ if (!LazyMap) {
+ ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
+ LazyMap.reset(new ObjCContainerDecl::PropertyMap());
+ CollectImmediateProperties(CDecl, *LazyMap, NoNeedToImplPropMap,
+ /* IncludeProtocols */ false);
+ }
+ // Add the properties of 'PDecl' to the list of properties that
+ // need to be implemented.
+ for (auto *PropDecl : PDecl->properties()) {
+ if ((*LazyMap)[PropDecl->getIdentifier()])
+ continue;
+ PropMap[PropDecl->getIdentifier()] = PropDecl;
}
}
- if (IDecl)
- CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap);
-
- ObjCContainerDecl::PropertyMap PropMap;
- CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap);
+ }
+
if (PropMap.empty())
return;
llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
- for (ObjCImplDecl::propimpl_iterator
- I = IMPDecl->propimpl_begin(),
- EI = IMPDecl->propimpl_end(); I != EI; ++I)
+ for (const auto *I : IMPDecl->property_impls())
PropImplMap.insert(I->getPropertyDecl());
SelectorSet InsMap;
// Collect property accessors implemented in current implementation.
- for (ObjCImplementationDecl::instmeth_iterator
- I = IMPDecl->instmeth_begin(), E = IMPDecl->instmeth_end(); I!=E; ++I)
- InsMap.insert((*I)->getSelector());
+ for (const auto *I : IMPDecl->instance_methods())
+ InsMap.insert(I->getSelector());
ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
ObjCInterfaceDecl *PrimaryClass = 0;
@@ -1655,9 +1720,8 @@
// When reporting on missing setter/getters, do not report when
// setter/getter is implemented in category's primary class
// implementation.
- for (ObjCImplementationDecl::instmeth_iterator
- I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I)
- InsMap.insert((*I)->getSelector());
+ for (const auto *I : IMP->instance_methods())
+ InsMap.insert(I->getSelector());
}
for (ObjCContainerDecl::PropertyMap::iterator
@@ -1669,45 +1733,14 @@
PropImplMap.count(Prop) ||
Prop->getAvailability() == AR_Unavailable)
continue;
- // When reporting on missing property getter implementation in
- // categories, do not report when they are declared in primary class,
- // class's protocol, or one of it super classes. This is because,
- // the class is going to implement them.
- if (!InsMap.count(Prop->getGetterName()) &&
- (PrimaryClass == 0 ||
- !PrimaryClass->lookupPropertyAccessor(Prop->getGetterName(), C))) {
- Diag(IMPDecl->getLocation(),
- isa<ObjCCategoryDecl>(CDecl) ?
- diag::warn_setter_getter_impl_required_in_category :
- diag::warn_setter_getter_impl_required)
- << Prop->getDeclName() << Prop->getGetterName();
- Diag(Prop->getLocation(),
- diag::note_property_declare);
- if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCRuntime.isNonFragile())
- if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
- if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
- Diag(RID->getLocation(), diag::note_suppressed_class_declare);
-
- }
- // When reporting on missing property setter implementation in
- // categories, do not report when they are declared in primary class,
- // class's protocol, or one of it super classes. This is because,
- // the class is going to implement them.
- if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName()) &&
- (PrimaryClass == 0 ||
- !PrimaryClass->lookupPropertyAccessor(Prop->getSetterName(), C))) {
- Diag(IMPDecl->getLocation(),
- isa<ObjCCategoryDecl>(CDecl) ?
- diag::warn_setter_getter_impl_required_in_category :
- diag::warn_setter_getter_impl_required)
- << Prop->getDeclName() << Prop->getSetterName();
- Diag(Prop->getLocation(),
- diag::note_property_declare);
- if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCRuntime.isNonFragile())
- if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
- if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
- Diag(RID->getLocation(), diag::note_suppressed_class_declare);
- }
+
+ // Diagnose unimplemented getters and setters.
+ DiagnoseUnimplementedAccessor(*this,
+ PrimaryClass, Prop->getGetterName(), IMPDecl, CDecl, C, Prop, InsMap);
+ if (!Prop->isReadOnly())
+ DiagnoseUnimplementedAccessor(*this,
+ PrimaryClass, Prop->getSetterName(),
+ IMPDecl, CDecl, C, Prop, InsMap);
}
}
@@ -1717,10 +1750,7 @@
// Rules apply in non-GC mode only
if (getLangOpts().getGC() != LangOptions::NonGC)
return;
- for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(),
- E = IDecl->prop_end();
- I != E; ++I) {
- ObjCPropertyDecl *Property = *I;
+ for (const auto *Property : IDecl->properties()) {
ObjCMethodDecl *GetterMethod = 0;
ObjCMethodDecl *SetterMethod = 0;
bool LookedUpGetterSetter = false;
@@ -1758,7 +1788,6 @@
if (!LookedUpGetterSetter) {
GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName());
SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName());
- LookedUpGetterSetter = true;
}
if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) {
SourceLocation MethodLoc =
@@ -1805,12 +1834,7 @@
if (getLangOpts().getGC() == LangOptions::GCOnly)
return;
- for (ObjCImplementationDecl::propimpl_iterator
- i = D->propimpl_begin(), e = D->propimpl_end(); i != e; ++i) {
- ObjCPropertyImplDecl *PID = *i;
- if (PID->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
- continue;
-
+ for (const auto *PID : D->property_impls()) {
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() &&
!D->getInstanceMethod(PD->getGetterName())) {
@@ -1821,27 +1845,51 @@
if (family == OMF_alloc || family == OMF_copy ||
family == OMF_mutableCopy || family == OMF_new) {
if (getLangOpts().ObjCAutoRefCount)
- Diag(PID->getLocation(), diag::err_ownin_getter_rule);
+ Diag(PD->getLocation(), diag::err_cocoa_naming_owned_rule);
else
- Diag(PID->getLocation(), diag::warn_owning_getter_rule);
- Diag(PD->getLocation(), diag::note_property_declare);
+ Diag(PD->getLocation(), diag::warn_cocoa_naming_owned_rule);
}
}
}
}
+void Sema::DiagnoseMissingDesignatedInitOverrides(
+ const ObjCImplementationDecl *ImplD,
+ const ObjCInterfaceDecl *IFD) {
+ assert(IFD->hasDesignatedInitializers());
+ const ObjCInterfaceDecl *SuperD = IFD->getSuperClass();
+ if (!SuperD)
+ return;
+
+ SelectorSet InitSelSet;
+ for (const auto *I : ImplD->instance_methods())
+ if (I->getMethodFamily() == OMF_init)
+ InitSelSet.insert(I->getSelector());
+
+ SmallVector<const ObjCMethodDecl *, 8> DesignatedInits;
+ SuperD->getDesignatedInitializers(DesignatedInits);
+ for (SmallVector<const ObjCMethodDecl *, 8>::iterator
+ I = DesignatedInits.begin(), E = DesignatedInits.end(); I != E; ++I) {
+ const ObjCMethodDecl *MD = *I;
+ if (!InitSelSet.count(MD->getSelector())) {
+ Diag(ImplD->getLocation(),
+ diag::warn_objc_implementation_missing_designated_init_override)
+ << MD->getSelector();
+ Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here);
+ }
+ }
+}
+
/// AddPropertyAttrs - Propagates attributes from a property to the
/// implicitly-declared getter or setter for that property.
static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
ObjCPropertyDecl *Property) {
// Should we just clone all attributes over?
- for (Decl::attr_iterator A = Property->attr_begin(),
- AEnd = Property->attr_end();
- A != AEnd; ++A) {
- if (isa<DeprecatedAttr>(*A) ||
- isa<UnavailableAttr>(*A) ||
- isa<AvailabilityAttr>(*A))
- PropertyMethod->addAttr((*A)->clone(S.Context));
+ for (const auto *A : Property->attrs()) {
+ if (isa<DeprecatedAttr>(A) ||
+ isa<UnavailableAttr>(A) ||
+ isa<AvailabilityAttr>(A))
+ PropertyMethod->addAttr(A->clone(S.Context));
}
}
@@ -1866,8 +1914,8 @@
ObjCPropertyDecl::PropertyAttributeKind CAttr =
property->getPropertyAttributes();
if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) &&
- Context.getCanonicalType(SetterMethod->getResultType()) !=
- Context.VoidTy)
+ Context.getCanonicalType(SetterMethod->getReturnType()) !=
+ Context.VoidTy)
Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
if (SetterMethod->param_size() != 1 ||
!Context.hasSameUnqualifiedType(
@@ -1913,12 +1961,16 @@
if (lexicalDC)
GetterMethod->setLexicalDeclContext(lexicalDC);
if (property->hasAttr<NSReturnsNotRetainedAttr>())
- GetterMethod->addAttr(
- ::new (Context) NSReturnsNotRetainedAttr(Loc, Context));
+ GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context,
+ Loc));
if (property->hasAttr<ObjCReturnsInnerPointerAttr>())
GetterMethod->addAttr(
- ::new (Context) ObjCReturnsInnerPointerAttr(Loc, Context));
+ ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc));
+
+ if (const SectionAttr *SA = property->getAttr<SectionAttr>())
+ GetterMethod->addAttr(SectionAttr::CreateImplicit(Context, SA->getName(),
+ Loc));
if (getLangOpts().ObjCAutoRefCount)
CheckARCMethodDecl(GetterMethod);
@@ -1969,7 +2021,9 @@
// and the real context should be the same.
if (lexicalDC)
SetterMethod->setLexicalDeclContext(lexicalDC);
-
+ if (const SectionAttr *SA = property->getAttr<SectionAttr>())
+ SetterMethod->addAttr(SectionAttr::CreateImplicit(Context,
+ SA->getName(), Loc));
// It's possible for the user to have set a very odd custom
// setter selector that causes it to have a method family.
if (getLangOpts().ObjCAutoRefCount)
@@ -2027,27 +2081,19 @@
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;
- }
- else if (PropertyOwnership) {
- if (!getSourceManager().isInSystemHeader(Loc))
- Diag(Loc, diag::warn_objc_property_attr_mutually_exclusive)
- << "readonly" << NameOfOwnershipAttribute(Attributes);
- return;
- }
- }
+ // 'readonly' property with no obvious lifetime.
+ // its life time will be determined by its backing ivar.
+ if (getLangOpts().ObjCAutoRefCount &&
+ Attributes & ObjCDeclSpec::DQ_PR_readonly &&
+ PropertyTy->isObjCRetainableType() &&
+ !PropertyOwnership)
+ return;
// Check for copy or retain on non-object types.
if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy |
ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong)) &&
!PropertyTy->isObjCRetainableType() &&
- !PropertyDecl->getAttr<ObjCNSObjectAttr>()) {
+ !PropertyDecl->hasAttr<ObjCNSObjectAttr>()) {
Diag(Loc, diag::err_objc_property_requires_object)
<< (Attributes & ObjCDeclSpec::DQ_PR_weak ? "weak" :
Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain (or strong)");
@@ -2079,7 +2125,7 @@
<< "assign" << "weak";
Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
}
- if (PropertyDecl->getAttr<IBOutletCollectionAttr>())
+ if (PropertyDecl->hasAttr<IBOutletCollectionAttr>())
Diag(Loc, diag::warn_iboutletcollection_property_assign);
} else if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) {
if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index c63caf4..78f73c0 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -21,10 +21,10 @@
#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"
+#include "clang/Sema/SemaInternal.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -82,6 +82,9 @@
typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator;
DSAVarData getDSA(StackTy::reverse_iterator Iter, VarDecl *D);
+
+ /// \brief Checks if the variable is a local for OpenMP region.
+ bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter);
public:
explicit DSAStackTy(Sema &S) : Stack(1), Actions(S) { }
@@ -98,9 +101,6 @@
/// \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);
@@ -111,7 +111,6 @@
DSAVarData hasDSA(VarDecl *D, OpenMPClauseKind CKind,
OpenMPDirectiveKind DKind = OMPD_unknown);
-
/// \brief Returns currently analyzed directive.
OpenMPDirectiveKind getCurrentDirective() const {
return Stack.back().Directive;
@@ -126,6 +125,13 @@
return Stack.back().DefaultAttr;
}
+ /// \brief Checks if the spewcified variable is threadprivate.
+ bool isThreadPrivate(VarDecl *D) {
+ DSAVarData DVar = getTopDSA(D);
+ return (DVar.CKind == OMPC_threadprivate || DVar.CKind == OMPC_copyin);
+ }
+
+ Scope *getCurScope() const { return Stack.back().CurScope; }
Scope *getCurScope() { return Stack.back().CurScope; }
};
} // end anonymous namespace.
@@ -152,7 +158,21 @@
return DVar;
}
+
DVar.DKind = Iter->Directive;
+ // 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 (DVar.DKind != OMPD_parallel) {
+ if (isOpenMPLocal(D, Iter) && D->isLocalVarDecl() &&
+ (D->getStorageClass() == SC_Auto ||
+ D->getStorageClass() == SC_None)) {
+ DVar.CKind = OMPC_private;
+ return DVar;
+ }
+ }
+
// Explicitly specified attributes and local variables with predetermined
// attributes.
if (Iter->SharingMap.count(D)) {
@@ -189,8 +209,8 @@
// TODO
if (DVar.DKind == OMPD_task) {
DSAVarData DVarTemp;
- for (StackTy::reverse_iterator I = Iter + 1,
- EE = Stack.rend() - 1;
+ for (StackTy::reverse_iterator I = std::next(Iter),
+ EE = std::prev(Stack.rend());
I != EE; ++I) {
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct, implicitly determined, p.6]
@@ -217,7 +237,7 @@
// 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);
+ return getDSA(std::next(Iter), D);
}
void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
@@ -231,23 +251,24 @@
}
}
-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())
+bool
+DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
+ if (Stack.size() > 2) {
+ reverse_iterator I = Iter, E = Stack.rend() - 1;
+ Scope *TopScope = 0;
+ while (I != E &&
+ I->Directive != OMPD_parallel) {
+ ++I;
+ }
+ if (I == E) return false;
+ TopScope = I->CurScope ? I->CurScope->getParent() : 0;
+ Scope *CurScope = getCurScope();
+ while (CurScope != TopScope && !CurScope->isDeclScope(D)) {
CurScope = CurScope->getParent();
- isOpenMPLocal =
- CurScope &&
- isa<CapturedDecl>(D->getDeclContext()) &&
- CurScope->getFnParent()->getEntity()->Encloses(D->getDeclContext());
+ }
+ return CurScope != TopScope;
}
- return isOpenMPLocal;
+ return false;
}
DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
@@ -270,11 +291,13 @@
// 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;
+ OpenMPDirectiveKind Kind = getCurrentDirective();
+ if (Kind != OMPD_parallel) {
+ if (isOpenMPLocal(D, std::next(Stack.rbegin())) && 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
@@ -319,7 +342,7 @@
// 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()) {
+ if (D->isStaticLocal()) {
DVar.CKind = OMPC_shared;
return DVar;
}
@@ -335,13 +358,13 @@
}
DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D) {
- return getDSA(Stack.rbegin() + 1, D);
+ return getDSA(std::next(Stack.rbegin()), D);
}
DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, OpenMPClauseKind CKind,
OpenMPDirectiveKind DKind) {
- for (StackTy::reverse_iterator I = Stack.rbegin() + 1,
- E = Stack.rend() - 1;
+ for (StackTy::reverse_iterator I = std::next(Stack.rbegin()),
+ E = std::prev(Stack.rend());
I != E; ++I) {
if (DKind != OMPD_unknown && DKind != I->Directive) continue;
DSAVarData DVar = getDSA(I, D);
@@ -381,7 +404,7 @@
Sema &Actions;
public:
VarDeclFilterCCC(Sema &S) : Actions(S) { }
- virtual bool ValidateCandidate(const TypoCorrection &Candidate) {
+ bool ValidateCandidate(const TypoCorrection &Candidate) override {
NamedDecl *ND = Candidate.getCorrectionDecl();
if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) {
return VD->hasGlobalStorage() &&
@@ -509,8 +532,7 @@
}
QualType ExprType = VD->getType().getNonReferenceType();
- ExprResult DE = BuildDeclRefExpr(VD, ExprType, VK_RValue, Id.getLoc());
- DSAStack->addDSA(VD, cast<DeclRefExpr>(DE.get()), OMPC_threadprivate);
+ ExprResult DE = BuildDeclRefExpr(VD, ExprType, VK_LValue, Id.getLoc());
return DE;
}
@@ -566,11 +588,15 @@
}
Vars.push_back(*I);
+ DSAStack->addDSA(VD, DE, OMPC_threadprivate);
}
- return Vars.empty() ?
- 0 : OMPThreadPrivateDecl::Create(Context,
- getCurLexicalContext(),
- Loc, Vars);
+ OMPThreadPrivateDecl *D = 0;
+ if (!Vars.empty()) {
+ D = OMPThreadPrivateDecl::Create(Context, getCurLexicalContext(), Loc,
+ Vars);
+ D->setAccess(AS_public);
+ }
+ return D;
}
namespace {
@@ -592,7 +618,7 @@
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)
+ !Stack->isThreadPrivate(VD) && !DVar.RefExpr)
ImplicitFirstprivate.push_back(DVar.RefExpr);
return;
}
@@ -680,6 +706,10 @@
Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt,
StartLoc, EndLoc);
break;
+ case OMPD_simd:
+ Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt,
+ StartLoc, EndLoc);
+ break;
case OMPD_threadprivate:
case OMPD_task:
llvm_unreachable("OpenMP Directive is not allowed");
@@ -702,6 +732,185 @@
Clauses, AStmt));
}
+StmtResult Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ Stmt *CStmt = AStmt;
+ while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(CStmt))
+ CStmt = CS->getCapturedStmt();
+ while (AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(CStmt))
+ CStmt = AS->getSubStmt();
+ ForStmt *For = dyn_cast<ForStmt>(CStmt);
+ if (!For) {
+ Diag(CStmt->getLocStart(), diag::err_omp_not_for)
+ << getOpenMPDirectiveName(OMPD_simd);
+ return StmtError();
+ }
+
+ // FIXME: Checking loop canonical form, collapsing etc.
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return Owned(OMPSimdDirective::Create(Context, StartLoc, EndLoc,
+ Clauses, AStmt));
+}
+
+OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
+ Expr *Expr,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ OMPClause *Res = 0;
+ switch (Kind) {
+ case OMPC_if:
+ Res = ActOnOpenMPIfClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_num_threads:
+ Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_safelen:
+ Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_default:
+ case OMPC_private:
+ case OMPC_firstprivate:
+ case OMPC_shared:
+ case OMPC_copyin:
+ case OMPC_threadprivate:
+ case OMPC_unknown:
+ case NUM_OPENMP_CLAUSES:
+ llvm_unreachable("Clause is not allowed.");
+ }
+ return Res;
+}
+
+OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = Condition;
+ if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
+ !Condition->isInstantiationDependent() &&
+ !Condition->containsUnexpandedParameterPack()) {
+ ExprResult Val = ActOnBooleanCondition(DSAStack->getCurScope(),
+ Condition->getExprLoc(),
+ Condition);
+ if (Val.isInvalid())
+ return 0;
+
+ ValExpr = Val.take();
+ }
+
+ return new (Context) OMPIfClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+ExprResult Sema::PerformImplicitIntegerConversion(SourceLocation Loc,
+ Expr *Op) {
+ if (!Op)
+ return ExprError();
+
+ class IntConvertDiagnoser : public ICEConvertDiagnoser {
+ public:
+ IntConvertDiagnoser()
+ : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false,
+ false, true) {}
+ SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) override {
+ return S.Diag(Loc, diag::err_omp_not_integral) << T;
+ }
+ SemaDiagnosticBuilder diagnoseIncomplete(
+ Sema &S, SourceLocation Loc, QualType T) override {
+ return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
+ }
+ SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
+ return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
+ }
+ SemaDiagnosticBuilder noteExplicitConv(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
+ return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
+ << ConvTy->isEnumeralType() << ConvTy;
+ }
+ SemaDiagnosticBuilder diagnoseAmbiguous(
+ Sema &S, SourceLocation Loc, QualType T) override {
+ return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
+ }
+ SemaDiagnosticBuilder noteAmbiguous(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
+ return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
+ << ConvTy->isEnumeralType() << ConvTy;
+ }
+ SemaDiagnosticBuilder diagnoseConversion(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
+ llvm_unreachable("conversion functions are permitted");
+ }
+ } ConvertDiagnoser;
+ return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
+}
+
+OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = NumThreads;
+ if (!NumThreads->isValueDependent() && !NumThreads->isTypeDependent() &&
+ !NumThreads->isInstantiationDependent() &&
+ !NumThreads->containsUnexpandedParameterPack()) {
+ SourceLocation NumThreadsLoc = NumThreads->getLocStart();
+ ExprResult Val =
+ PerformImplicitIntegerConversion(NumThreadsLoc, NumThreads);
+ if (Val.isInvalid())
+ return 0;
+
+ ValExpr = Val.take();
+
+ // OpenMP [2.5, Restrictions]
+ // The num_threads expression must evaluate to a positive integer value.
+ llvm::APSInt Result;
+ if (ValExpr->isIntegerConstantExpr(Result, Context) &&
+ Result.isSigned() && !Result.isStrictlyPositive()) {
+ Diag(NumThreadsLoc, diag::err_omp_negative_expression_in_clause)
+ << "num_threads" << NumThreads->getSourceRange();
+ return 0;
+ }
+ }
+
+ return new (Context) OMPNumThreadsClause(ValExpr, StartLoc, LParenLoc,
+ EndLoc);
+}
+
+ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
+ OpenMPClauseKind CKind) {
+ if (!E)
+ return ExprError();
+ if (E->isValueDependent() || E->isTypeDependent() ||
+ E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
+ return Owned(E);
+ llvm::APSInt Result;
+ ExprResult ICE = VerifyIntegerConstantExpression(E, &Result);
+ if (ICE.isInvalid())
+ return ExprError();
+ if (!Result.isStrictlyPositive()) {
+ Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
+ << getOpenMPClauseName(CKind) << E->getSourceRange();
+ return ExprError();
+ }
+ return ICE;
+}
+
+OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ // OpenMP [2.8.1, simd construct, Description]
+ // The parameter of the safelen clause must be a constant
+ // positive integer expression.
+ ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
+ if (Safelen.isInvalid())
+ return 0;
+ return new (Context)
+ OMPSafelenClause(Safelen.take(), StartLoc, LParenLoc, EndLoc);
+}
+
OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
unsigned Argument,
SourceLocation ArgumentLoc,
@@ -715,9 +924,13 @@
ActOnOpenMPDefaultClause(static_cast<OpenMPDefaultClauseKind>(Argument),
ArgumentLoc, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_if:
+ case OMPC_num_threads:
+ case OMPC_safelen:
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
+ case OMPC_copyin:
case OMPC_threadprivate:
case OMPC_unknown:
case NUM_OPENMP_CLAUSES:
@@ -733,7 +946,9 @@
SourceLocation EndLoc) {
if (Kind == OMPC_DEFAULT_unknown) {
std::string Values;
- std::string Sep(NUM_OPENMP_DEFAULT_KINDS > 1 ? ", " : "");
+ static_assert(NUM_OPENMP_DEFAULT_KINDS > 1,
+ "NUM_OPENMP_DEFAULT_KINDS not greater than 1");
+ std::string Sep(", ");
for (unsigned i = OMPC_DEFAULT_unknown + 1;
i < NUM_OPENMP_DEFAULT_KINDS; ++i) {
Values += "'";
@@ -761,7 +976,9 @@
case OMPC_DEFAULT_shared:
DSAStack->setDefaultDSAShared();
break;
- default:
+ case OMPC_DEFAULT_unknown:
+ case NUM_OPENMP_DEFAULT_KINDS:
+ llvm_unreachable("Clause kind is not allowed.");
break;
}
return new (Context) OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc,
@@ -784,6 +1001,12 @@
case OMPC_shared:
Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_copyin:
+ Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_if:
+ case OMPC_num_threads:
+ case OMPC_safelen:
case OMPC_default:
case OMPC_threadprivate:
case OMPC_unknown:
@@ -1114,9 +1337,10 @@
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.
+ // OpenMP [2.14.3.2, Restrictions, p.1]
+ // A variable that is part of another variable (as an array or structure
+ // element) cannot appear in a shared unless it is a static data member
+ // of a C++ class.
DeclRefExpr *DE = dyn_cast<DeclRefExpr>(*I);
if (!DE || !isa<VarDecl>(DE->getDecl())) {
Diag(ELoc, diag::err_omp_expected_var_name)
@@ -1159,4 +1383,84 @@
return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
}
+OMPClause *Sema::ActOnOpenMPCopyinClause(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 copyin 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.14.4.1, Restrictions, p.1]
+ // A list item that appears in a copyin clause must be threadprivate.
+ 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.14.4.1, Restrictions, C/C++, p.1]
+ // A list item that appears in a copyin clause must be threadprivate.
+ if (!DSAStack->isThreadPrivate(VD)) {
+ Diag(ELoc, diag::err_omp_required_access)
+ << getOpenMPClauseName(OMPC_copyin)
+ << getOpenMPDirectiveName(OMPD_threadprivate);
+ continue;
+ }
+
+ // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
+ // A variable of class type (or array thereof) that appears in a
+ // copyin clause requires an accesible, unambiguous copy assignment
+ // operator for the class type.
+ Type = Context.getBaseElementType(Type);
+ CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
+ Type->getAsCXXRecordDecl() : 0;
+ if (RD) {
+ CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
+ DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
+ if (!MD ||
+ CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
+ MD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_copyin) << 2;
+ 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, MD);
+ DiagnoseUseOfDecl(MD, ELoc);
+ }
+
+ DSAStack->addDSA(VD, DE, OMPC_copyin);
+ Vars.push_back(DE);
+ }
+
+ if (Vars.empty()) return 0;
+
+ return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
+}
+
#undef DSAStack
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 802f2b7..ee1feb5 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -930,24 +930,15 @@
(OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord() &&
!New->getFriendObjectKind();
- if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) {
- if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) {
- if (UseMemberUsingDeclRules && OldIsUsingDecl) {
- HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
- continue;
- }
-
- Match = *I;
- return Ovl_Match;
- }
- } else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(OldD)) {
+ if (FunctionDecl *OldF = OldD->getAsFunction()) {
if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) {
if (UseMemberUsingDeclRules && OldIsUsingDecl) {
HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
continue;
}
- if (!shouldLinkPossiblyHiddenDecl(*I, New))
+ if (!isa<FunctionTemplateDecl>(OldD) &&
+ !shouldLinkPossiblyHiddenDecl(*I, New))
continue;
Match = *I;
@@ -1008,16 +999,16 @@
isa<FunctionNoProtoType>(NewQType.getTypePtr()))
return false;
- const FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
- const FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
+ const FunctionProtoType *OldType = cast<FunctionProtoType>(OldQType);
+ const FunctionProtoType *NewType = cast<FunctionProtoType>(NewQType);
// The signature of a function includes the types of its
// parameters (C++ 1.3.10), which includes the presence or absence
// of the ellipsis; see C++ DR 357).
if (OldQType != NewQType &&
- (OldType->getNumArgs() != NewType->getNumArgs() ||
+ (OldType->getNumParams() != NewType->getNumParams() ||
OldType->isVariadic() != NewType->isVariadic() ||
- !FunctionArgTypesAreEqual(OldType, NewType)))
+ !FunctionParamTypesAreEqual(OldType, NewType)))
return true;
// C++ [temp.over.link]p4:
@@ -1036,7 +1027,7 @@
(!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
false, TPL_TemplateMatch) ||
- OldType->getResultType() != NewType->getResultType()))
+ OldType->getReturnType() != NewType->getReturnType()))
return true;
// If the function is a class member, its signature includes the
@@ -1085,6 +1076,22 @@
return true;
}
+ // enable_if attributes are an order-sensitive part of the signature.
+ for (specific_attr_iterator<EnableIfAttr>
+ NewI = New->specific_attr_begin<EnableIfAttr>(),
+ NewE = New->specific_attr_end<EnableIfAttr>(),
+ OldI = Old->specific_attr_begin<EnableIfAttr>(),
+ OldE = Old->specific_attr_end<EnableIfAttr>();
+ NewI != NewE || OldI != OldE; ++NewI, ++OldI) {
+ if (NewI == NewE || OldI == OldE)
+ return true;
+ llvm::FoldingSetNodeID NewID, OldID;
+ NewI->getCond()->Profile(NewID, Context, true);
+ OldI->getCond()->Profile(OldID, Context, true);
+ if (NewID != OldID)
+ return true;
+ }
+
// The signatures match; this is not an overload.
return false;
}
@@ -1127,6 +1134,7 @@
if (UserDefResult == OR_Success) {
ICS.setUserDefined();
+ ICS.UserDefined.Before.setAsIdentityConversion();
// C++ [over.ics.user]p4:
// A conversion of an expression of class type to the same class
// type is given Exact Match rank, and a conversion of an
@@ -1298,7 +1306,9 @@
bool AllowObjCWritebackConversion
= getLangOpts().ObjCAutoRefCount &&
(Action == AA_Passing || Action == AA_Sending);
-
+ if (getLangOpts().ObjC1)
+ CheckObjCBridgeRelatedConversions(From->getLocStart(),
+ ToType, From->getType(), From);
ICS = clang::TryImplicitConversion(*this, From, ToType,
/*SuppressUserConversions=*/false,
AllowExplicit,
@@ -1362,7 +1372,7 @@
///
/// \param ICK Will be set to the vector conversion kind, if this is a vector
/// conversion.
-static bool IsVectorConversion(ASTContext &Context, QualType FromType,
+static bool IsVectorConversion(Sema &S, QualType FromType,
QualType ToType, ImplicitConversionKind &ICK) {
// We need at least one of these types to be a vector type to have a vector
// conversion.
@@ -1370,7 +1380,7 @@
return false;
// Identical types require no conversions.
- if (Context.hasSameUnqualifiedType(FromType, ToType))
+ if (S.Context.hasSameUnqualifiedType(FromType, ToType))
return false;
// There are no conversions between extended vector types, only identity.
@@ -1392,9 +1402,8 @@
// 2)lax vector conversions are permitted and the vector types are of the
// same size
if (ToType->isVectorType() && FromType->isVectorType()) {
- if (Context.areCompatibleVectorTypes(FromType, ToType) ||
- (Context.getLangOpts().LaxVectorConversions &&
- (Context.getTypeSize(FromType) == Context.getTypeSize(ToType)))) {
+ if (S.Context.areCompatibleVectorTypes(FromType, ToType) ||
+ S.isLaxVectorConversion(FromType, ToType)) {
ICK = ICK_Vector_Conversion;
return true;
}
@@ -1425,7 +1434,6 @@
// Standard conversions (C++ [conv])
SCS.setAsIdentityConversion();
- SCS.DeprecatedStringLiteralToCharPtr = false;
SCS.IncompatibleObjC = false;
SCS.setFromType(FromType);
SCS.CopyConstructor = 0;
@@ -1524,7 +1532,7 @@
FromType = S.Context.getArrayDecayedType(FromType);
if (S.IsStringLiteralToNonConstPointerConversion(From, ToType)) {
- // This conversion is deprecated. (C++ D.4).
+ // This conversion is deprecated in C++03 (D.4)
SCS.DeprecatedStringLiteralToCharPtr = true;
// For the purpose of ranking in overload resolution
@@ -1624,7 +1632,7 @@
InOverloadResolution, FromType)) {
// Pointer to member conversions (4.11).
SCS.Second = ICK_Pointer_Member;
- } else if (IsVectorConversion(S.Context, FromType, ToType, SecondICK)) {
+ } else if (IsVectorConversion(S, FromType, ToType, SecondICK)) {
SCS.Second = SecondICK;
FromType = ToType.getUnqualifiedType();
} else if (!S.getLangOpts().CPlusPlus &&
@@ -1707,9 +1715,7 @@
// The field to initialize within the transparent union.
RecordDecl *UD = UT->getDecl();
// It's compatible if the expression matches any of the fields.
- for (RecordDecl::field_iterator it = UD->field_begin(),
- itend = UD->field_end();
- it != itend; ++it) {
+ for (const auto *it : UD->fields()) {
if (IsStandardConversion(S, From, it->getType(), InOverloadResolution, SCS,
CStyle, /*ObjCWritebackConversion=*/false)) {
ToType = it->getType();
@@ -2288,17 +2294,17 @@
// Perform the quick checks that will tell us whether these
// function types are obviously different.
- if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() ||
+ if (FromFunctionType->getNumParams() != ToFunctionType->getNumParams() ||
FromFunctionType->isVariadic() != ToFunctionType->isVariadic() ||
FromFunctionType->getTypeQuals() != ToFunctionType->getTypeQuals())
return false;
bool HasObjCConversion = false;
- if (Context.getCanonicalType(FromFunctionType->getResultType())
- == Context.getCanonicalType(ToFunctionType->getResultType())) {
+ if (Context.getCanonicalType(FromFunctionType->getReturnType()) ==
+ Context.getCanonicalType(ToFunctionType->getReturnType())) {
// Okay, the types match exactly. Nothing to do.
- } else if (isObjCPointerConversion(FromFunctionType->getResultType(),
- ToFunctionType->getResultType(),
+ } else if (isObjCPointerConversion(FromFunctionType->getReturnType(),
+ ToFunctionType->getReturnType(),
ConvertedType, IncompatibleObjC)) {
// Okay, we have an Objective-C pointer conversion.
HasObjCConversion = true;
@@ -2308,10 +2314,10 @@
}
// Check argument types.
- for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
+ for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumParams();
ArgIdx != NumArgs; ++ArgIdx) {
- QualType FromArgType = FromFunctionType->getArgType(ArgIdx);
- QualType ToArgType = ToFunctionType->getArgType(ArgIdx);
+ QualType FromArgType = FromFunctionType->getParamType(ArgIdx);
+ QualType ToArgType = ToFunctionType->getParamType(ArgIdx);
if (Context.getCanonicalType(FromArgType)
== Context.getCanonicalType(ToArgType)) {
// Okay, the types match exactly. Nothing to do.
@@ -2436,7 +2442,7 @@
// Perform the quick checks that will tell us whether these
// function types are obviously different.
- if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() ||
+ if (FromFunctionType->getNumParams() != ToFunctionType->getNumParams() ||
FromFunctionType->isVariadic() != ToFunctionType->isVariadic())
return false;
@@ -2446,12 +2452,12 @@
return false;
bool IncompatibleObjC = false;
- if (Context.hasSameType(FromFunctionType->getResultType(),
- ToFunctionType->getResultType())) {
+ if (Context.hasSameType(FromFunctionType->getReturnType(),
+ ToFunctionType->getReturnType())) {
// Okay, the types match exactly. Nothing to do.
} else {
- QualType RHS = FromFunctionType->getResultType();
- QualType LHS = ToFunctionType->getResultType();
+ QualType RHS = FromFunctionType->getReturnType();
+ QualType LHS = ToFunctionType->getReturnType();
if ((!getLangOpts().CPlusPlus || !RHS->isRecordType()) &&
!RHS.hasQualifiers() && LHS.hasQualifiers())
LHS = LHS.getUnqualifiedType();
@@ -2469,11 +2475,11 @@
}
// Check argument types.
- for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
+ for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumParams();
ArgIdx != NumArgs; ++ArgIdx) {
IncompatibleObjC = false;
- QualType FromArgType = FromFunctionType->getArgType(ArgIdx);
- QualType ToArgType = ToFunctionType->getArgType(ArgIdx);
+ QualType FromArgType = FromFunctionType->getParamType(ArgIdx);
+ QualType ToArgType = ToFunctionType->getParamType(ArgIdx);
if (Context.hasSameType(FromArgType, ToArgType)) {
// Okay, the types match exactly. Nothing to do.
} else if (isObjCPointerConversion(ToArgType, FromArgType,
@@ -2558,26 +2564,26 @@
return;
}
- if (FromFunction->getNumArgs() != ToFunction->getNumArgs()) {
- PDiag << ft_parameter_arity << ToFunction->getNumArgs()
- << FromFunction->getNumArgs();
+ if (FromFunction->getNumParams() != ToFunction->getNumParams()) {
+ PDiag << ft_parameter_arity << ToFunction->getNumParams()
+ << FromFunction->getNumParams();
return;
}
// Handle different parameter types.
unsigned ArgPos;
- if (!FunctionArgTypesAreEqual(FromFunction, ToFunction, &ArgPos)) {
+ if (!FunctionParamTypesAreEqual(FromFunction, ToFunction, &ArgPos)) {
PDiag << ft_parameter_mismatch << ArgPos + 1
- << ToFunction->getArgType(ArgPos)
- << FromFunction->getArgType(ArgPos);
+ << ToFunction->getParamType(ArgPos)
+ << FromFunction->getParamType(ArgPos);
return;
}
// Handle different return type.
- if (!Context.hasSameType(FromFunction->getResultType(),
- ToFunction->getResultType())) {
- PDiag << ft_return_type << ToFunction->getResultType()
- << FromFunction->getResultType();
+ if (!Context.hasSameType(FromFunction->getReturnType(),
+ ToFunction->getReturnType())) {
+ PDiag << ft_return_type << ToFunction->getReturnType()
+ << FromFunction->getReturnType();
return;
}
@@ -2592,19 +2598,21 @@
PDiag << ft_default;
}
-/// FunctionArgTypesAreEqual - This routine checks two function proto types
+/// FunctionParamTypesAreEqual - This routine checks two function proto types
/// for equality of their argument types. Caller has already checked that
/// 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) {
- 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) {
+bool Sema::FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
+ const FunctionProtoType *NewType,
+ unsigned *ArgPos) {
+ for (FunctionProtoType::param_type_iterator O = OldType->param_type_begin(),
+ N = NewType->param_type_begin(),
+ E = OldType->param_type_end();
+ O && (O != E); ++O, ++N) {
if (!Context.hasSameType(O->getUnqualifiedType(),
N->getUnqualifiedType())) {
- if (ArgPos) *ArgPos = O - OldType->arg_type_begin();
+ if (ArgPos)
+ *ArgPos = O - OldType->param_type_begin();
return false;
}
}
@@ -2919,8 +2927,8 @@
QualType Type) {
const FunctionProtoType *CtorType =
Constructor->getType()->getAs<FunctionProtoType>();
- if (CtorType->getNumArgs() > 0) {
- QualType FirstArg = CtorType->getArgType(0);
+ if (CtorType->getNumParams() > 0) {
+ QualType FirstArg = CtorType->getParamType(0);
if (Context.hasSameUnqualifiedType(Type, FirstArg.getNonReferenceType()))
return true;
}
@@ -3241,18 +3249,15 @@
IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined,
CandidateSet, false, false);
if (OvResult == OR_Ambiguous)
- Diag(From->getLocStart(),
- diag::err_typecheck_ambiguous_condition)
- << From->getType() << ToType << From->getSourceRange();
+ Diag(From->getLocStart(), diag::err_typecheck_ambiguous_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,
+ diag::err_typecheck_nonviable_condition_incomplete,
From->getType(), From->getSourceRange()))
- Diag(From->getLocStart(),
- diag::err_typecheck_nonviable_condition)
- << From->getType() << From->getSourceRange() << ToType;
- }
- else
+ Diag(From->getLocStart(), diag::err_typecheck_nonviable_condition)
+ << From->getType() << From->getSourceRange() << ToType;
+ } else
return false;
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From);
return true;
@@ -3262,37 +3267,43 @@
/// of two user-defined conversion sequences to determine whether any ordering
/// is possible.
static ImplicitConversionSequence::CompareKind
-compareConversionFunctions(Sema &S,
- FunctionDecl *Function1,
+compareConversionFunctions(Sema &S, FunctionDecl *Function1,
FunctionDecl *Function2) {
if (!S.getLangOpts().ObjC1 || !S.getLangOpts().CPlusPlus11)
return ImplicitConversionSequence::Indistinguishable;
-
+
// Objective-C++:
// If both conversion functions are implicitly-declared conversions from
- // a lambda closure type to a function pointer and a block pointer,
+ // a lambda closure type to a function pointer and a block pointer,
// respectively, always prefer the conversion to a function pointer,
// because the function pointer is more lightweight and is more likely
// to keep code working.
- CXXConversionDecl *Conv1 = dyn_cast<CXXConversionDecl>(Function1);
+ CXXConversionDecl *Conv1 = dyn_cast_or_null<CXXConversionDecl>(Function1);
if (!Conv1)
return ImplicitConversionSequence::Indistinguishable;
-
+
CXXConversionDecl *Conv2 = dyn_cast<CXXConversionDecl>(Function2);
if (!Conv2)
return ImplicitConversionSequence::Indistinguishable;
-
+
if (Conv1->getParent()->isLambda() && Conv2->getParent()->isLambda()) {
bool Block1 = Conv1->getConversionType()->isBlockPointerType();
bool Block2 = Conv2->getConversionType()->isBlockPointerType();
if (Block1 != Block2)
- return Block1? ImplicitConversionSequence::Worse
- : ImplicitConversionSequence::Better;
+ return Block1 ? ImplicitConversionSequence::Worse
+ : ImplicitConversionSequence::Better;
}
return ImplicitConversionSequence::Indistinguishable;
}
-
+
+static bool hasDeprecatedStringLiteralToCharPtrConversion(
+ const ImplicitConversionSequence &ICS) {
+ return (ICS.isStandard() && ICS.Standard.DeprecatedStringLiteralToCharPtr) ||
+ (ICS.isUserDefined() &&
+ ICS.UserDefined.Before.DeprecatedStringLiteralToCharPtr);
+}
+
/// CompareImplicitConversionSequences - Compare two implicit
/// conversion sequences to determine whether one is better than the
/// other or if they are indistinguishable (C++ 13.3.3.2).
@@ -3315,6 +3326,32 @@
// described in 13.3.3.2, the ambiguous conversion sequence is
// treated as a user-defined sequence that is indistinguishable
// from any other user-defined conversion sequence.
+
+ // String literal to 'char *' conversion has been deprecated in C++03. It has
+ // been removed from C++11. We still accept this conversion, if it happens at
+ // the best viable function. Otherwise, this conversion is considered worse
+ // than ellipsis conversion. Consider this as an extension; this is not in the
+ // standard. For example:
+ //
+ // int &f(...); // #1
+ // void f(char*); // #2
+ // void g() { int &r = f("foo"); }
+ //
+ // In C++03, we pick #2 as the best viable function.
+ // In C++11, we pick #1 as the best viable function, because ellipsis
+ // conversion is better than string-literal to char* conversion (since there
+ // is no such conversion in C++11). If there was no #1 at all or #1 couldn't
+ // convert arguments, #2 would be the best viable function in C++11.
+ // If the best viable function has this conversion, a warning will be issued
+ // in C++03, or an ExtWarn (+SFINAE failure) will be issued in C++11.
+
+ if (S.getLangOpts().CPlusPlus11 && !S.getLangOpts().WritableStrings &&
+ hasDeprecatedStringLiteralToCharPtrConversion(ICS1) !=
+ hasDeprecatedStringLiteralToCharPtrConversion(ICS2))
+ return hasDeprecatedStringLiteralToCharPtrConversion(ICS1)
+ ? ImplicitConversionSequence::Worse
+ : ImplicitConversionSequence::Better;
+
if (ICS1.getKindRank() < ICS2.getKindRank())
return ImplicitConversionSequence::Better;
if (ICS2.getKindRank() < ICS1.getKindRank())
@@ -3613,11 +3650,10 @@
// }
// Here, MSVC will call f(int) instead of generating a compile error
// as clang will do in standard mode.
- if (S.getLangOpts().MicrosoftMode &&
- SCS1.Second == ICK_Integral_Conversion &&
- SCS2.Second == ICK_Floating_Integral &&
+ if (S.getLangOpts().MSVCCompat && SCS1.Second == ICK_Integral_Conversion &&
+ SCS2.Second == ICK_Floating_Integral &&
S.Context.getTypeSize(SCS1.getFromType()) ==
- S.Context.getTypeSize(SCS1.getToType(2)))
+ S.Context.getTypeSize(SCS1.getToType(2)))
return ImplicitConversionSequence::Better;
return ImplicitConversionSequence::Indistinguishable;
@@ -4227,6 +4263,7 @@
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
ICS.Standard.CopyConstructor = 0;
+ ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
// Nothing more to do: the inaccessibility/ambiguity check for
// derived-to-base conversions is suppressed when we're
@@ -4301,6 +4338,7 @@
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
ICS.Standard.CopyConstructor = 0;
+ ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
return ICS;
}
@@ -4398,9 +4436,9 @@
} else if (ICS.isUserDefined()) {
// Don't allow rvalue references to bind to lvalues.
if (DeclType->isRValueReferenceType()) {
- if (const ReferenceType *RefType
- = ICS.UserDefined.ConversionFunction->getResultType()
- ->getAs<LValueReferenceType>()) {
+ if (const ReferenceType *RefType =
+ ICS.UserDefined.ConversionFunction->getReturnType()
+ ->getAs<LValueReferenceType>()) {
if (!RefType->getPointeeType()->isFunctionType()) {
ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init,
DeclType);
@@ -4408,7 +4446,7 @@
}
}
}
-
+ ICS.UserDefined.Before.setAsIdentityConversion();
ICS.UserDefined.After.ReferenceBinding = true;
ICS.UserDefined.After.IsLvalueReference = !isRValRef;
ICS.UserDefined.After.BindsToFunctionLvalue = T2->isFunctionType();
@@ -5291,7 +5329,7 @@
TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter, Expr *From)
: TypeDiagnoser(Converter.Suppress), Converter(Converter), From(From) {}
- virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
Converter.diagnoseIncomplete(S, Loc, T) << From->getSourceRange();
}
} IncompleteDiagnoser(Converter, From);
@@ -5450,11 +5488,11 @@
Sema::AddOverloadCandidate(FunctionDecl *Function,
DeclAccessPair FoundDecl,
ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
+ OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions,
bool PartialOverloading,
bool AllowExplicit) {
- const FunctionProtoType* Proto
+ const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
assert(Proto && "Functions without a prototype cannot be overloaded");
assert(!Function->getDescribedFunctionTemplate() &&
@@ -5513,12 +5551,12 @@
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
- unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumParams = Proto->getNumParams();
// (C++ 13.3.2p2): A candidate function having fewer than m
// parameters is viable only if it has an ellipsis in its parameter
// list (8.3.5).
- if ((Args.size() + (PartialOverloading && Args.size())) > NumArgsInProto &&
+ if ((Args.size() + (PartialOverloading && Args.size())) > NumParams &&
!Proto->isVariadic()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_many_arguments;
@@ -5550,12 +5588,12 @@
// Determine the implicit conversion sequences for each of the
// arguments.
for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
- if (ArgIdx < NumArgsInProto) {
+ if (ArgIdx < NumParams) {
// (C++ 13.3.2p3): for F to be a viable function, there shall
// exist for each argument an implicit conversion sequence
// (13.3.3.1) that converts that argument to the corresponding
// parameter of F.
- QualType ParamType = Proto->getArgType(ArgIdx);
+ QualType ParamType = Proto->getParamType(ArgIdx);
Candidate.Conversions[ArgIdx]
= TryCopyInitialization(*this, Args[ArgIdx], ParamType,
SuppressUserConversions,
@@ -5566,7 +5604,7 @@
if (Candidate.Conversions[ArgIdx].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
- break;
+ return;
}
} else {
// (C++ 13.3.2p2): For the purposes of overload resolution, any
@@ -5575,6 +5613,78 @@
Candidate.Conversions[ArgIdx].setEllipsis();
}
}
+
+ if (EnableIfAttr *FailedAttr = CheckEnableIf(Function, Args)) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_enable_if;
+ Candidate.DeductionFailure.Data = FailedAttr;
+ return;
+ }
+}
+
+static bool IsNotEnableIfAttr(Attr *A) { return !isa<EnableIfAttr>(A); }
+
+EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
+ bool MissingImplicitThis) {
+ // FIXME: specific_attr_iterator<EnableIfAttr> iterates in reverse order, but
+ // we need to find the first failing one.
+ if (!Function->hasAttrs())
+ return 0;
+ AttrVec Attrs = Function->getAttrs();
+ AttrVec::iterator E = std::remove_if(Attrs.begin(), Attrs.end(),
+ IsNotEnableIfAttr);
+ if (Attrs.begin() == E)
+ return 0;
+ std::reverse(Attrs.begin(), E);
+
+ SFINAETrap Trap(*this);
+
+ // Convert the arguments.
+ SmallVector<Expr *, 16> ConvertedArgs;
+ bool InitializationFailed = false;
+ for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+ if (i == 0 && !MissingImplicitThis && isa<CXXMethodDecl>(Function) &&
+ !cast<CXXMethodDecl>(Function)->isStatic() &&
+ !isa<CXXConstructorDecl>(Function)) {
+ CXXMethodDecl *Method = cast<CXXMethodDecl>(Function);
+ ExprResult R =
+ PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+ Method, Method);
+ if (R.isInvalid()) {
+ InitializationFailed = true;
+ break;
+ }
+ ConvertedArgs.push_back(R.take());
+ } else {
+ ExprResult R =
+ PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context,
+ Function->getParamDecl(i)),
+ SourceLocation(),
+ Args[i]);
+ if (R.isInvalid()) {
+ InitializationFailed = true;
+ break;
+ }
+ ConvertedArgs.push_back(R.take());
+ }
+ }
+
+ if (InitializationFailed || Trap.hasErrorOccurred())
+ return cast<EnableIfAttr>(Attrs[0]);
+
+ for (AttrVec::iterator I = Attrs.begin(); I != E; ++I) {
+ APValue Result;
+ EnableIfAttr *EIA = cast<EnableIfAttr>(*I);
+ if (!EIA->getCond()->EvaluateWithSubstitution(
+ Result, Context, Function,
+ llvm::ArrayRef<const Expr*>(ConvertedArgs.data(),
+ ConvertedArgs.size())) ||
+ !Result.isInt() || !Result.getInt().getBoolValue()) {
+ return EIA;
+ }
+ }
+ return 0;
}
/// \brief Add all of the function declarations in the given function set to
@@ -5656,9 +5766,9 @@
CXXRecordDecl *ActingContext, QualType ObjectType,
Expr::Classification ObjectClassification,
ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
+ OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions) {
- const FunctionProtoType* Proto
+ const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
assert(Proto && "Methods without a prototype cannot be overloaded");
assert(!isa<CXXConstructorDecl>(Method) &&
@@ -5685,12 +5795,12 @@
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
- unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumParams = Proto->getNumParams();
// (C++ 13.3.2p2): A candidate function having fewer than m
// parameters is viable only if it has an ellipsis in its parameter
// list (8.3.5).
- if (Args.size() > NumArgsInProto && !Proto->isVariadic()) {
+ if (Args.size() > NumParams && !Proto->isVariadic()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_many_arguments;
return;
@@ -5730,12 +5840,12 @@
// Determine the implicit conversion sequences for each of the
// arguments.
for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
- if (ArgIdx < NumArgsInProto) {
+ if (ArgIdx < NumParams) {
// (C++ 13.3.2p3): for F to be a viable function, there shall
// exist for each argument an implicit conversion sequence
// (13.3.3.1) that converts that argument to the corresponding
// parameter of F.
- QualType ParamType = Proto->getArgType(ArgIdx);
+ QualType ParamType = Proto->getParamType(ArgIdx);
Candidate.Conversions[ArgIdx + 1]
= TryCopyInitialization(*this, Args[ArgIdx], ParamType,
SuppressUserConversions,
@@ -5745,15 +5855,22 @@
if (Candidate.Conversions[ArgIdx + 1].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
- break;
+ return;
}
} else {
// (C++ 13.3.2p2): For the purposes of overload resolution, any
// argument for which there is no corresponding parameter is
- // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
+ // considered to "match the ellipsis" (C+ 13.3.3.1.3).
Candidate.Conversions[ArgIdx + 1].setEllipsis();
}
}
+
+ if (EnableIfAttr *FailedAttr = CheckEnableIf(Method, Args, true)) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_enable_if;
+ Candidate.DeductionFailure.Data = FailedAttr;
+ return;
+ }
}
/// \brief Add a C++ member function template as a candidate to the candidate
@@ -5969,7 +6086,7 @@
return;
}
- // We won't go through a user-define type conversion function to convert a
+ // We won't go through a user-defined type conversion function to convert a
// derived to base as such conversions are given Conversion Rank. They only
// go through a copy constructor. 13.3.3.1.2-p4 [over.ics.user]
QualType FromCanon
@@ -6029,6 +6146,7 @@
GetConversionRank(ICS.Standard.Second) != ICR_Exact_Match) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_final_conversion_not_exact;
+ return;
}
// C++0x [dcl.init.ref]p5:
@@ -6040,18 +6158,26 @@
ICS.Standard.First == ICK_Lvalue_To_Rvalue) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_final_conversion;
+ return;
}
break;
case ImplicitConversionSequence::BadConversion:
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_final_conversion;
- break;
+ return;
default:
llvm_unreachable(
"Can only end up with a standard conversion sequence or failure");
}
+
+ if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, ArrayRef<Expr*>())) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_enable_if;
+ Candidate.DeductionFailure.Data = FailedAttr;
+ return;
+ }
}
/// \brief Adds a conversion function template specialization
@@ -6151,12 +6277,12 @@
Candidate.Conversions[0].UserDefined.After.setAsIdentityConversion();
// Find the
- unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumParams = Proto->getNumParams();
// (C++ 13.3.2p2): A candidate function having fewer than m
// parameters is viable only if it has an ellipsis in its parameter
// list (8.3.5).
- if (Args.size() > NumArgsInProto && !Proto->isVariadic()) {
+ if (Args.size() > NumParams && !Proto->isVariadic()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_many_arguments;
return;
@@ -6164,7 +6290,7 @@
// Function types don't have any default arguments, so just check if
// we have enough arguments.
- if (Args.size() < NumArgsInProto) {
+ if (Args.size() < NumParams) {
// Not enough arguments.
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_few_arguments;
@@ -6174,12 +6300,12 @@
// Determine the implicit conversion sequences for each of the
// arguments.
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
- if (ArgIdx < NumArgsInProto) {
+ if (ArgIdx < NumParams) {
// (C++ 13.3.2p3): for F to be a viable function, there shall
// exist for each argument an implicit conversion sequence
// (13.3.3.1) that converts that argument to the corresponding
// parameter of F.
- QualType ParamType = Proto->getArgType(ArgIdx);
+ QualType ParamType = Proto->getParamType(ArgIdx);
Candidate.Conversions[ArgIdx + 1]
= TryCopyInitialization(*this, Args[ArgIdx], ParamType,
/*SuppressUserConversions=*/false,
@@ -6189,7 +6315,7 @@
if (Candidate.Conversions[ArgIdx + 1].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
- break;
+ return;
}
} else {
// (C++ 13.3.2p2): For the purposes of overload resolution, any
@@ -6198,6 +6324,13 @@
Candidate.Conversions[ArgIdx + 1].setEllipsis();
}
}
+
+ if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, ArrayRef<Expr*>())) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_enable_if;
+ Candidate.DeductionFailure.Data = FailedAttr;
+ return;
+ }
}
/// \brief Add overload candidates for overloaded operators that are
@@ -8109,6 +8242,47 @@
}
}
+ // Check for enable_if value-based overload resolution.
+ if (Cand1.Function && Cand2.Function &&
+ (Cand1.Function->hasAttr<EnableIfAttr>() ||
+ Cand2.Function->hasAttr<EnableIfAttr>())) {
+ // FIXME: The next several lines are just
+ // specific_attr_iterator<EnableIfAttr> but going in declaration order,
+ // instead of reverse order which is how they're stored in the AST.
+ AttrVec Cand1Attrs;
+ AttrVec::iterator Cand1E = Cand1Attrs.end();
+ if (Cand1.Function->hasAttrs()) {
+ Cand1Attrs = Cand1.Function->getAttrs();
+ Cand1E = std::remove_if(Cand1Attrs.begin(), Cand1Attrs.end(),
+ IsNotEnableIfAttr);
+ std::reverse(Cand1Attrs.begin(), Cand1E);
+ }
+
+ AttrVec Cand2Attrs;
+ AttrVec::iterator Cand2E = Cand2Attrs.end();
+ if (Cand2.Function->hasAttrs()) {
+ Cand2Attrs = Cand2.Function->getAttrs();
+ Cand2E = std::remove_if(Cand2Attrs.begin(), Cand2Attrs.end(),
+ IsNotEnableIfAttr);
+ std::reverse(Cand2Attrs.begin(), Cand2E);
+ }
+ for (AttrVec::iterator
+ Cand1I = Cand1Attrs.begin(), Cand2I = Cand2Attrs.begin();
+ Cand1I != Cand1E || Cand2I != Cand2E; ++Cand1I, ++Cand2I) {
+ if (Cand1I == Cand1E)
+ return false;
+ if (Cand2I == Cand2E)
+ return true;
+ llvm::FoldingSetNodeID Cand1ID, Cand2ID;
+ cast<EnableIfAttr>(*Cand1I)->getCond()->Profile(Cand1ID,
+ S.getASTContext(), true);
+ cast<EnableIfAttr>(*Cand2I)->getCond()->Profile(Cand2ID,
+ S.getASTContext(), true);
+ if (Cand1ID != Cand2ID)
+ return false;
+ }
+ }
+
return false;
}
@@ -8557,18 +8731,18 @@
// at least / at most / exactly
unsigned mode, modeCount;
if (NumFormalArgs < MinParams) {
- if (MinParams != FnTy->getNumArgs() ||
- FnTy->isVariadic() || FnTy->isTemplateVariadic())
+ if (MinParams != FnTy->getNumParams() || FnTy->isVariadic() ||
+ FnTy->isTemplateVariadic())
mode = 0; // "at least"
else
mode = 2; // "exactly"
modeCount = MinParams;
} else {
- if (MinParams != FnTy->getNumArgs())
+ if (MinParams != FnTy->getNumParams())
mode = 1; // "at most"
else
mode = 2; // "exactly"
- modeCount = FnTy->getNumArgs();
+ modeCount = FnTy->getNumParams();
}
std::string Description;
@@ -8817,6 +8991,15 @@
<< (unsigned) FnKind << CalleeTarget << CallerTarget;
}
+void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) {
+ FunctionDecl *Callee = Cand->Function;
+ EnableIfAttr *Attr = static_cast<EnableIfAttr*>(Cand->DeductionFailure.Data);
+
+ S.Diag(Callee->getLocation(),
+ diag::note_ovl_candidate_disabled_by_enable_if_attr)
+ << Attr->getCond()->getSourceRange() << Attr->getMessage();
+}
+
/// Generates a 'note' diagnostic for an overload candidate. We've
/// already generated a primary error at the call site.
///
@@ -8880,6 +9063,9 @@
case ovl_fail_bad_target:
return DiagnoseBadTarget(S, Cand);
+
+ case ovl_fail_enable_if:
+ return DiagnoseFailedEnableIfAttr(S, Cand);
}
}
@@ -9160,15 +9346,14 @@
}
// Fill in the rest of the conversions.
- unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumParams = Proto->getNumParams();
for (; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) {
- if (ArgIdx < NumArgsInProto) {
- Cand->Conversions[ConvIdx]
- = TryCopyInitialization(S, Args[ArgIdx], Proto->getArgType(ArgIdx),
- SuppressUserConversions,
- /*InOverloadResolution=*/true,
- /*AllowObjCWritebackConversion=*/
- S.getLangOpts().ObjCAutoRefCount);
+ if (ArgIdx < NumParams) {
+ Cand->Conversions[ConvIdx] = TryCopyInitialization(
+ S, Args[ArgIdx], Proto->getParamType(ArgIdx), SuppressUserConversions,
+ /*InOverloadResolution=*/true,
+ /*AllowObjCWritebackConversion=*/
+ S.getLangOpts().ObjCAutoRefCount);
// Store the FixIt in the candidate if it exists.
if (!Unfixable && Cand->Conversions[ConvIdx].isBad())
Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S);
@@ -9320,7 +9505,7 @@
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,
+ // Otherwise, this is a non-matching builtin candidate. We do not,
// in general, want to list every possible builtin candidate.
}
@@ -9531,7 +9716,7 @@
// If any candidate has a placeholder return type, trigger its deduction
// now.
if (S.getLangOpts().CPlusPlus1y &&
- FunDecl->getResultType()->isUndeducedType() &&
+ FunDecl->getReturnType()->isUndeducedType() &&
S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain))
return false;
@@ -9836,7 +10021,7 @@
}
if (Matched && getLangOpts().CPlusPlus1y &&
- Matched->getResultType()->isUndeducedType() &&
+ Matched->getReturnType()->isUndeducedType() &&
DeduceReturnType(Matched, ovl->getExprLoc(), Complain))
return 0;
@@ -10198,7 +10383,7 @@
LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
Sema::LookupOrdinaryName);
FunctionCallFilterCCC Validator(SemaRef, Args.size(),
- ExplicitTemplateArgs != 0);
+ ExplicitTemplateArgs != 0, false);
NoTypoCorrectionCCC RejectAll;
CorrectionCandidateCallback *CCC = AllowTypoCorrection ?
(CorrectionCandidateCallback*)&Validator :
@@ -10280,7 +10465,7 @@
// create a type dependent CallExpr. The goal is to postpone name lookup
// to instantiation time to be able to search into type dependent base
// classes.
- if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() &&
+ if (getLangOpts().MSVCCompat && CurContext->isDependentContext() &&
(isa<FunctionDecl>(CurContext) || isa<CXXRecordDecl>(CurContext))) {
CallExpr *CE = new (Context) CallExpr(Context, Fn, Args,
Context.DependentTy, VK_RValue,
@@ -10530,7 +10715,7 @@
return ExprError();
// Determine the result type.
- QualType ResultTy = FnDecl->getResultType();
+ QualType ResultTy = FnDecl->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
@@ -10539,8 +10724,7 @@
new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), ArgsArray,
ResultTy, VK, OpLoc, false);
- if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
- FnDecl))
+ if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl))
return ExprError();
return MaybeBindToTemporary(TheCall);
@@ -10765,7 +10949,7 @@
return ExprError();
// Determine the result type.
- QualType ResultTy = FnDecl->getResultType();
+ QualType ResultTy = FnDecl->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
@@ -10774,7 +10958,7 @@
Args, ResultTy, VK, OpLoc,
FPFeatures.fp_contract);
- if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
+ if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall,
FnDecl))
return ExprError();
@@ -10981,7 +11165,7 @@
return ExprError();
// Determine the result type
- QualType ResultTy = FnDecl->getResultType();
+ QualType ResultTy = FnDecl->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
@@ -10991,8 +11175,7 @@
ResultTy, VK, RLoc,
false);
- if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall,
- FnDecl))
+ if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
return ExprError();
return MaybeBindToTemporary(TheCall);
@@ -11084,7 +11267,7 @@
const FunctionProtoType *proto = fnType->castAs<FunctionProtoType>();
QualType resultType = proto->getCallResultType(Context);
- ExprValueKind valueKind = Expr::getValueKindForType(proto->getResultType());
+ ExprValueKind valueKind = Expr::getValueKindForType(proto->getReturnType());
// Check that the object type isn't more qualified than the
// member function we're calling.
@@ -11105,13 +11288,12 @@
<< qualsString
<< (qualsString.find(' ') == std::string::npos ? 1 : 2);
}
-
+
CXXMemberCallExpr *call
= new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
resultType, valueKind, RParenLoc);
- if (CheckCallReturnType(proto->getResultType(),
- op->getRHS()->getLocStart(),
+ if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getLocStart(),
call, 0))
return ExprError();
@@ -11250,7 +11432,7 @@
MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens());
}
- QualType ResultType = Method->getResultType();
+ QualType ResultType = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultType);
ResultType = ResultType.getNonLValueExprType(Context);
@@ -11260,7 +11442,7 @@
ResultType, VK, RParenLoc);
// Check for a valid return type.
- if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(),
+ if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(),
TheCall, Method))
return ExprError();
@@ -11489,7 +11671,7 @@
const FunctionProtoType *Proto =
Method->getType()->getAs<FunctionProtoType>();
- unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumParams = Proto->getNumParams();
DeclarationNameInfo OpLocInfo(
Context.DeclarationNames.getCXXOperatorName(OO_Call), LParenLoc);
@@ -11503,13 +11685,13 @@
// 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]);
+ std::unique_ptr<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();
+ QualType ResultTy = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
@@ -11519,14 +11701,13 @@
ResultTy, VK, RParenLoc, false);
MethodArgs.reset();
- if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall,
- Method))
+ if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
return true;
// We may have default arguments. If so, we need to allocate more
// slots in the call for them.
- if (Args.size() < NumArgsInProto)
- TheCall->setNumArgs(Context, NumArgsInProto + 1);
+ if (Args.size() < NumParams)
+ TheCall->setNumArgs(Context, NumParams + 1);
bool IsError = false;
@@ -11541,7 +11722,7 @@
TheCall->setArg(0, Object.take());
// Check the argument types.
- for (unsigned i = 0; i != NumArgsInProto; i++) {
+ for (unsigned i = 0; i != NumParams; i++) {
Expr *Arg;
if (i < Args.size()) {
Arg = Args[i];
@@ -11573,7 +11754,7 @@
// 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, e = Args.size(); i < e; i++) {
+ for (unsigned i = NumParams, e = Args.size(); i < e; i++) {
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0);
IsError |= Arg.isInvalid();
TheCall->setArg(i + 1, Arg.take());
@@ -11692,15 +11873,14 @@
if (FnExpr.isInvalid())
return ExprError();
- QualType ResultTy = Method->getResultType();
+ QualType ResultTy = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(),
Base, ResultTy, VK, OpLoc, false);
- if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall,
- Method))
+ if (CheckCallReturnType(Method->getReturnType(), OpLoc, TheCall, Method))
return ExprError();
return MaybeBindToTemporary(TheCall);
@@ -11761,7 +11941,7 @@
ConvArgs[ArgIdx] = InputInit.take();
}
- QualType ResultTy = FD->getResultType();
+ QualType ResultTy = FD->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
@@ -11770,7 +11950,7 @@
llvm::makeArrayRef(ConvArgs, Args.size()),
ResultTy, VK, LitEndLoc, UDSuffixLoc);
- if (CheckCallReturnType(FD->getResultType(), UDSuffixLoc, UDL, FD))
+ if (CheckCallReturnType(FD->getReturnType(), UDSuffixLoc, UDL, FD))
return ExprError();
if (CheckFunctionCall(FD, UDL, NULL))
@@ -11893,7 +12073,7 @@
// Do nothing: static member functions aren't any different
// from non-member functions.
} else {
- // Fix the sub expression, which really has to be an
+ // Fix the subexpression, which really has to be an
// UnresolvedLookupExpr holding an overloaded member function
// or template.
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index af74f0d..de02fa9 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -235,7 +235,10 @@
}
/// Return true if assignments have a non-void result.
- bool CanCaptureValueOfType(QualType ty) {
+ bool CanCaptureValue(Expr *exp) {
+ if (exp->isGLValue())
+ return true;
+ QualType ty = exp->getType();
assert(!ty->isIncompleteType());
assert(!ty->isDependentType());
@@ -280,10 +283,10 @@
bool findSetter(bool warn=true);
bool findGetter();
- Expr *rebuildAndCaptureObject(Expr *syntacticBase);
- ExprResult buildGet();
- ExprResult buildSet(Expr *op, SourceLocation, bool);
- ExprResult complete(Expr *SyntacticForm);
+ Expr *rebuildAndCaptureObject(Expr *syntacticBase) override;
+ ExprResult buildGet() override;
+ ExprResult buildSet(Expr *op, SourceLocation, bool) override;
+ ExprResult complete(Expr *SyntacticForm) override;
bool isWeakProperty() const;
};
@@ -311,13 +314,13 @@
SourceLocation opLoc,
BinaryOperatorKind opcode,
Expr *LHS, Expr *RHS);
- Expr *rebuildAndCaptureObject(Expr *syntacticBase);
-
+ Expr *rebuildAndCaptureObject(Expr *syntacticBase) override;
+
bool findAtIndexGetter();
bool findAtIndexSetter();
-
- ExprResult buildGet();
- ExprResult buildSet(Expr *op, SourceLocation, bool);
+
+ ExprResult buildGet() override;
+ ExprResult buildSet(Expr *op, SourceLocation, bool) override;
};
class MSPropertyOpBuilder : public PseudoOpBuilder {
@@ -328,9 +331,9 @@
PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
RefExpr(refExpr) {}
- Expr *rebuildAndCaptureObject(Expr *);
- ExprResult buildGet();
- ExprResult buildSet(Expr *op, SourceLocation, bool);
+ Expr *rebuildAndCaptureObject(Expr *) override;
+ ExprResult buildGet() override;
+ ExprResult buildSet(Expr *op, SourceLocation, bool) override;
};
}
@@ -461,7 +464,7 @@
// That's the postfix result.
if (UnaryOperator::isPostfix(opcode) &&
- (result.get()->isTypeDependent() || CanCaptureValueOfType(resultType))) {
+ (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) {
result = capture(result.take());
setResultToLastSemantic();
}
@@ -540,7 +543,7 @@
T = Prop->getType();
} else if (Getter) {
- T = Getter->getResultType();
+ T = Getter->getReturnType();
} else {
return false;
}
@@ -621,7 +624,7 @@
if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(AltMember))
if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {
S.Diag(RefExpr->getExprLoc(), diag::error_property_setter_ambiguous_use)
- << prop->getName() << prop1->getName() << setter->getSelector();
+ << prop << prop1 << setter->getSelector();
S.Diag(prop->getLocation(), diag::note_property_declare);
S.Diag(prop1->getLocation(), diag::note_property_declare);
}
@@ -762,7 +765,7 @@
ObjCMessageExpr *msgExpr =
cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
Expr *arg = msgExpr->getArg(0);
- if (CanCaptureValueOfType(arg->getType()))
+ if (CanCaptureValue(arg))
msgExpr->setArg(0, captureValueAsResult(arg));
}
@@ -813,7 +816,7 @@
assert(Getter && "property has no setter and no getter!");
// Only do this if the getter returns an l-value reference type.
- QualType resultType = Getter->getResultType();
+ QualType resultType = Getter->getReturnType();
if (!resultType->isLValueReferenceType()) return false;
result = buildRValueOperation(op);
@@ -1011,8 +1014,6 @@
// Look for a conversion to an integral, enumeration type, or
// objective-C pointer type.
- UnresolvedSet<4> ViableConversions;
- UnresolvedSet<4> ExplicitConversions;
std::pair<CXXRecordDecl::conversion_iterator,
CXXRecordDecl::conversion_iterator> Conversions
= cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
@@ -1172,7 +1173,7 @@
diag::note_parameter_type) << T;
return false;
}
- QualType R = AtIndexGetter->getResultType();
+ QualType R = AtIndexGetter->getReturnType();
if (!R->isObjCObjectPointerType()) {
S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
diag::err_objc_indexing_method_result_type) << R << arrayRef;
@@ -1239,18 +1240,15 @@
BaseT->isObjCQualifiedIdType());
if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
- TypeSourceInfo *ResultTInfo = 0;
+ TypeSourceInfo *ReturnTInfo = 0;
QualType ReturnType = S.Context.VoidTy;
- AtIndexSetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
- SourceLocation(), AtIndexSetterSelector,
- ReturnType,
- ResultTInfo,
- S.Context.getTranslationUnitDecl(),
- true /*Instance*/, false/*isVariadic*/,
- /*isPropertyAccessor=*/false,
- /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
- ObjCMethodDecl::Required,
- false);
+ AtIndexSetter = ObjCMethodDecl::Create(
+ S.Context, SourceLocation(), SourceLocation(), AtIndexSetterSelector,
+ ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(),
+ true /*Instance*/, false /*isVariadic*/,
+ /*isPropertyAccessor=*/false,
+ /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+ ObjCMethodDecl::Required, false);
SmallVector<ParmVarDecl *, 2> Params;
ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,
SourceLocation(), SourceLocation(),
@@ -1373,7 +1371,7 @@
ObjCMessageExpr *msgExpr =
cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
Expr *arg = msgExpr->getArg(0);
- if (CanCaptureValueOfType(arg->getType()))
+ if (CanCaptureValue(arg))
msgExpr->setArg(0, captureValueAsResult(arg));
}
@@ -1395,8 +1393,8 @@
ExprResult MSPropertyOpBuilder::buildGet() {
if (!RefExpr->getPropertyDecl()->hasGetter()) {
- S.Diag(RefExpr->getMemberLoc(), diag::err_no_getter_for_property)
- << RefExpr->getPropertyDecl()->getName();
+ S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)
+ << 0 /* getter */ << RefExpr->getPropertyDecl();
return ExprError();
}
@@ -1410,8 +1408,9 @@
RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
GetterName, 0, true);
if (GetterExpr.isInvalid()) {
- S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_getter)
- << RefExpr->getPropertyDecl()->getName();
+ S.Diag(RefExpr->getMemberLoc(),
+ diag::error_cannot_find_suitable_accessor) << 0 /* getter */
+ << RefExpr->getPropertyDecl();
return ExprError();
}
@@ -1424,8 +1423,8 @@
ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
bool captureSetValueAsResult) {
if (!RefExpr->getPropertyDecl()->hasSetter()) {
- S.Diag(RefExpr->getMemberLoc(), diag::err_no_setter_for_property)
- << RefExpr->getPropertyDecl()->getName();
+ S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)
+ << 1 /* setter */ << RefExpr->getPropertyDecl();
return ExprError();
}
@@ -1439,8 +1438,9 @@
RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
SetterName, 0, true);
if (SetterExpr.isInvalid()) {
- S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_setter)
- << RefExpr->getPropertyDecl()->getName();
+ S.Diag(RefExpr->getMemberLoc(),
+ diag::error_cannot_find_suitable_accessor) << 1 /* setter */
+ << RefExpr->getPropertyDecl();
return ExprError();
}
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 9bd8678..2be5d5c 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -114,25 +114,38 @@
}
}
-/// \brief Diagnose unused '==' and '!=' as likely typos for '=' or '|='.
+/// \brief Diagnose unused comparisons, both builtin and overloaded operators.
+/// For '==' and '!=', suggest fixits for '=' or '|='.
///
/// Adding a cast to void (or other expression wrappers) will prevent the
/// warning from firing.
static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
SourceLocation Loc;
- bool IsNotEqual, CanAssign;
+ bool IsNotEqual, CanAssign, IsRelational;
if (const BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
- if (Op->getOpcode() != BO_EQ && Op->getOpcode() != BO_NE)
+ if (!Op->isComparisonOp())
return false;
+ IsRelational = Op->isRelationalOp();
Loc = Op->getOperatorLoc();
IsNotEqual = Op->getOpcode() == BO_NE;
CanAssign = Op->getLHS()->IgnoreParenImpCasts()->isLValue();
} else if (const CXXOperatorCallExpr *Op = dyn_cast<CXXOperatorCallExpr>(E)) {
- if (Op->getOperator() != OO_EqualEqual &&
- Op->getOperator() != OO_ExclaimEqual)
+ switch (Op->getOperator()) {
+ default:
return false;
+ case OO_EqualEqual:
+ case OO_ExclaimEqual:
+ IsRelational = false;
+ break;
+ case OO_Less:
+ case OO_Greater:
+ case OO_GreaterEqual:
+ case OO_LessEqual:
+ IsRelational = true;
+ break;
+ }
Loc = Op->getOperatorLoc();
IsNotEqual = Op->getOperator() == OO_ExclaimEqual;
@@ -148,11 +161,11 @@
return false;
S.Diag(Loc, diag::warn_unused_comparison)
- << (unsigned)IsNotEqual << E->getSourceRange();
+ << (unsigned)IsRelational << (unsigned)IsNotEqual << E->getSourceRange();
// If the LHS is a plausible entity to assign to, provide a fixit hint to
// correct common typos.
- if (CanAssign) {
+ if (!IsRelational && CanAssign) {
if (IsNotEqual)
S.Diag(Loc, diag::note_inequality_comparison_to_or_assign)
<< FixItHint::CreateReplacement(Loc, "|=");
@@ -216,17 +229,17 @@
// is written in a macro body, only warn if it has the warn_unused_result
// attribute.
if (const Decl *FD = CE->getCalleeDecl()) {
- if (FD->getAttr<WarnUnusedResultAttr>()) {
+ if (FD->hasAttr<WarnUnusedResultAttr>()) {
Diag(Loc, diag::warn_unused_result) << R1 << R2;
return;
}
if (ShouldSuppress)
return;
- if (FD->getAttr<PureAttr>()) {
+ if (FD->hasAttr<PureAttr>()) {
Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure";
return;
}
- if (FD->getAttr<ConstAttr>()) {
+ if (FD->hasAttr<ConstAttr>()) {
Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const";
return;
}
@@ -240,7 +253,7 @@
return;
}
const ObjCMethodDecl *MD = ME->getMethodDecl();
- if (MD && MD->getAttr<WarnUnusedResultAttr>()) {
+ if (MD && MD->hasAttr<WarnUnusedResultAttr>()) {
Diag(Loc, diag::warn_unused_result) << R1 << R2;
return;
}
@@ -499,7 +512,6 @@
// We don't diagnose this overflow, because it is implementation-defined
// behavior.
// FIXME: Introduce a second, default-ignored warning for this case?
- llvm::APSInt OldVal(Val);
Val.setIsSigned(NewSign);
}
}
@@ -589,41 +601,41 @@
: ICEConvertDiagnoser(/*AllowScopedEnumerations*/true, false, true),
Cond(Cond) {}
- virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
- QualType T) {
+ SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) override {
return S.Diag(Loc, diag::err_typecheck_statement_requires_integer) << T;
}
- virtual SemaDiagnosticBuilder diagnoseIncomplete(
- Sema &S, SourceLocation Loc, QualType T) {
+ SemaDiagnosticBuilder diagnoseIncomplete(
+ Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_switch_incomplete_class_type)
<< T << Cond->getSourceRange();
}
- virtual SemaDiagnosticBuilder diagnoseExplicitConv(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
return S.Diag(Loc, diag::err_switch_explicit_conversion) << T << ConvTy;
}
- virtual SemaDiagnosticBuilder noteExplicitConv(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ SemaDiagnosticBuilder noteExplicitConv(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_switch_conversion)
<< ConvTy->isEnumeralType() << ConvTy;
}
- virtual SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
- QualType T) {
+ SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
+ QualType T) override {
return S.Diag(Loc, diag::err_switch_multiple_conversions) << T;
}
- virtual SemaDiagnosticBuilder noteAmbiguous(
- Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
+ SemaDiagnosticBuilder noteAmbiguous(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_switch_conversion)
<< ConvTy->isEnumeralType() << ConvTy;
}
- virtual SemaDiagnosticBuilder diagnoseConversion(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
+ SemaDiagnosticBuilder diagnoseConversion(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
llvm_unreachable("conversion functions are permitted");
}
} SwitchDiagnoser(Cond);
@@ -660,6 +672,29 @@
Val.setIsSigned(IsSigned);
}
+/// Returns true if we should emit a diagnostic about this case expression not
+/// being a part of the enum used in the switch controlling expression.
+static bool ShouldDiagnoseSwitchCaseNotInEnum(const ASTContext &Ctx,
+ const EnumDecl *ED,
+ const Expr *CaseExpr) {
+ // Don't warn if the 'case' expression refers to a static const variable of
+ // the enum type.
+ CaseExpr = CaseExpr->IgnoreParenImpCasts();
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseExpr)) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+ if (!VD->hasGlobalStorage())
+ return true;
+ QualType VarType = VD->getType();
+ if (!VarType.isConstQualified())
+ return true;
+ QualType EnumType = Ctx.getTypeDeclType(ED);
+ if (Ctx.hasSameUnqualifiedType(EnumType, VarType))
+ return false;
+ }
+ }
+ return true;
+}
+
StmtResult
Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
Stmt *BodyStmt) {
@@ -993,11 +1028,10 @@
// Gather all enum values, set their type and sort them,
// allowing easier comparison with CaseVals.
- for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin();
- EDI != ED->enumerator_end(); ++EDI) {
+ for (auto *EDI : ED->enumerators()) {
llvm::APSInt Val = EDI->getInitVal();
AdjustAPSInt(Val, CondWidth, CondIsSigned);
- EnumVals.push_back(std::make_pair(Val, *EDI));
+ EnumVals.push_back(std::make_pair(Val, EDI));
}
std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals);
EnumValsTy::iterator EIend =
@@ -1009,9 +1043,12 @@
CI != CaseVals.end(); CI++) {
while (EI != EIend && EI->first < CI->first)
EI++;
- if (EI == EIend || EI->first > CI->first)
- Diag(CI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum)
- << CondTypeBeforePromotion;
+ if (EI == EIend || EI->first > CI->first) {
+ Expr *CaseExpr = CI->second->getLHS();
+ if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr))
+ Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
+ << CondTypeBeforePromotion;
+ }
}
// See which of case ranges aren't in enum
EI = EnumVals.begin();
@@ -1021,8 +1058,10 @@
EI++;
if (EI == EIend || EI->first != RI->first) {
- Diag(RI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum)
- << CondTypeBeforePromotion;
+ Expr *CaseExpr = RI->second->getLHS();
+ if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr))
+ Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
+ << CondTypeBeforePromotion;
}
llvm::APSInt Hi =
@@ -1030,9 +1069,12 @@
AdjustAPSInt(Hi, CondWidth, CondIsSigned);
while (EI != EIend && EI->first < Hi)
EI++;
- if (EI == EIend || EI->first != Hi)
- Diag(RI->second->getRHS()->getExprLoc(), diag::warn_not_in_enum)
- << CondTypeBeforePromotion;
+ if (EI == EIend || EI->first != Hi) {
+ Expr *CaseExpr = RI->second->getRHS();
+ if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr))
+ Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
+ << CondTypeBeforePromotion;
+ }
}
// Check which enum vals aren't in switch
@@ -1044,7 +1086,6 @@
for (EI = EnumVals.begin(); EI != EIend; EI++){
// Drop unneeded case values
- llvm::APSInt CIVal;
while (CI != CaseVals.end() && CI->first < EI->first)
CI++;
@@ -1120,7 +1161,7 @@
return;
if (const EnumType *ET = DstType->getAs<EnumType>())
- if (!Context.hasSameType(SrcType, DstType) &&
+ if (!Context.hasSameUnqualifiedType(SrcType, DstType) &&
SrcType->isIntegerType()) {
if (!SrcExpr->isTypeDependent() && !SrcExpr->isValueDependent() &&
SrcExpr->isIntegerConstantExpr(Context)) {
@@ -1137,11 +1178,10 @@
// Gather all enum values, set their type and sort them,
// allowing easier comparison with rhs constant.
- for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin();
- EDI != ED->enumerator_end(); ++EDI) {
+ for (auto *EDI : ED->enumerators()) {
llvm::APSInt Val = EDI->getInitVal();
AdjustAPSInt(Val, DstWidth, DstIsSigned);
- EnumVals.push_back(std::make_pair(Val, *EDI));
+ EnumVals.push_back(std::make_pair(Val, EDI));
}
if (EnumVals.empty())
return;
@@ -1155,7 +1195,7 @@
EI++;
if (EI == EIend || EI->first != RhsVal) {
Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)
- << DstType;
+ << DstType.getUnqualifiedType();
}
}
}
@@ -1176,6 +1216,7 @@
Expr *ConditionExpr = CondResult.take();
if (!ConditionExpr)
return StmtError();
+ CheckBreakContinueBinding(ConditionExpr);
DiagnoseUnusedExprResult(Body);
@@ -1192,6 +1233,7 @@
Expr *Cond, SourceLocation CondRParen) {
assert(Cond && "ActOnDoStmt(): missing expression");
+ CheckBreakContinueBinding(Cond);
ExprResult CondResult = CheckBooleanCondition(Cond, DoLoc);
if (CondResult.isInvalid())
return StmtError();
@@ -1454,25 +1496,33 @@
return false;
}
- // A visitor to determine if a continue statement is a subexpression.
- class ContinueFinder : public EvaluatedExprVisitor<ContinueFinder> {
- bool Found;
+ // A visitor to determine if a continue or break statement is a
+ // subexpression.
+ class BreakContinueFinder : public EvaluatedExprVisitor<BreakContinueFinder> {
+ SourceLocation BreakLoc;
+ SourceLocation ContinueLoc;
public:
- ContinueFinder(Sema &S, Stmt* Body) :
- Inherited(S.Context),
- Found(false) {
+ BreakContinueFinder(Sema &S, Stmt* Body) :
+ Inherited(S.Context) {
Visit(Body);
}
- typedef EvaluatedExprVisitor<ContinueFinder> Inherited;
+ typedef EvaluatedExprVisitor<BreakContinueFinder> Inherited;
void VisitContinueStmt(ContinueStmt* E) {
- Found = true;
+ ContinueLoc = E->getContinueLoc();
}
- bool ContinueFound() { return Found; }
+ void VisitBreakStmt(BreakStmt* E) {
+ BreakLoc = E->getBreakLoc();
+ }
- }; // end class ContinueFinder
+ bool ContinueFound() { return ContinueLoc.isValid(); }
+ bool BreakFound() { return BreakLoc.isValid(); }
+ SourceLocation GetContinueLoc() { return ContinueLoc; }
+ SourceLocation GetBreakLoc() { return BreakLoc; }
+
+ }; // end class BreakContinueFinder
// Emit a warning when a loop increment/decrement appears twice per loop
// iteration. The conditions which trigger this warning are:
@@ -1501,11 +1551,11 @@
if (!ProcessIterationStmt(S, LastStmt, LastIncrement, LastDRE)) return;
// Check that the two statements are both increments or both decrements
- // on the same varaible.
+ // on the same variable.
if (LoopIncrement != LastIncrement ||
LoopDRE->getDecl() != LastDRE->getDecl()) return;
- if (ContinueFinder(S, Body).ContinueFound()) return;
+ if (BreakContinueFinder(S, Body).ContinueFound()) return;
S.Diag(LastDRE->getLocation(), diag::warn_redundant_loop_iteration)
<< LastDRE->getDecl() << LastIncrement;
@@ -1515,6 +1565,25 @@
} // end namespace
+
+void Sema::CheckBreakContinueBinding(Expr *E) {
+ if (!E || getLangOpts().CPlusPlus)
+ return;
+ BreakContinueFinder BCFinder(*this, E);
+ Scope *BreakParent = CurScope->getBreakParent();
+ if (BCFinder.BreakFound() && BreakParent) {
+ if (BreakParent->getFlags() & Scope::SwitchScope) {
+ Diag(BCFinder.GetBreakLoc(), diag::warn_break_binds_to_switch);
+ } else {
+ Diag(BCFinder.GetBreakLoc(), diag::warn_loop_ctrl_binds_to_inner)
+ << "break";
+ }
+ } else if (BCFinder.ContinueFound() && CurScope->getContinueParent()) {
+ Diag(BCFinder.GetContinueLoc(), diag::warn_loop_ctrl_binds_to_inner)
+ << "continue";
+ }
+}
+
StmtResult
Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
Stmt *First, FullExprArg second, Decl *secondVar,
@@ -1525,19 +1594,21 @@
// C99 6.8.5p3: The declaration part of a 'for' statement shall only
// declare identifiers for objects having storage class 'auto' or
// 'register'.
- for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
- DI!=DE; ++DI) {
- VarDecl *VD = dyn_cast<VarDecl>(*DI);
+ for (auto *DI : DS->decls()) {
+ VarDecl *VD = dyn_cast<VarDecl>(DI);
if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage())
VD = 0;
if (VD == 0) {
- Diag((*DI)->getLocation(), diag::err_non_local_variable_decl_in_for);
- (*DI)->setInvalidDecl();
+ Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for);
+ DI->setInvalidDecl();
}
}
}
}
+ CheckBreakContinueBinding(second.get());
+ CheckBreakContinueBinding(third.get());
+
CheckForLoopConditionalStatement(*this, second.get(), third.get(), Body);
CheckForRedundantIteration(*this, third.get(), Body);
@@ -2499,7 +2570,7 @@
static bool hasDeducedReturnType(FunctionDecl *FD) {
const FunctionProtoType *FPT =
FD->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>();
- return FPT->getResultType()->isUndeducedType();
+ return FPT->getReturnType()->isUndeducedType();
}
/// ActOnCapScopeReturnStmt - Utility routine to type-check return statements
@@ -2518,7 +2589,7 @@
// FIXME: Blocks might have a return type of 'auto' explicitly specified.
FunctionDecl *FD = CurLambda->CallOperator;
if (CurCap->ReturnType.isNull())
- CurCap->ReturnType = FD->getResultType();
+ CurCap->ReturnType = FD->getReturnType();
AutoType *AT = CurCap->ReturnType->getContainedAutoType();
assert(AT && "lost auto type from lambda return type");
@@ -2526,7 +2597,7 @@
FD->setInvalidDecl();
return StmtError();
}
- CurCap->ReturnType = FnRetType = FD->getResultType();
+ CurCap->ReturnType = FnRetType = FD->getReturnType();
} 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
@@ -2621,7 +2692,7 @@
return StmtError();
}
RetValExp = Res.take();
- CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+ CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc);
}
if (RetValExp) {
@@ -2651,7 +2722,7 @@
Expr *&RetExpr,
AutoType *AT) {
TypeLoc OrigResultType = FD->getTypeSourceInfo()->getTypeLoc().
- IgnoreParens().castAs<FunctionProtoTypeLoc>().getResultLoc();
+ IgnoreParens().castAs<FunctionProtoTypeLoc>().getReturnLoc();
QualType Deduced;
if (RetExpr && isa<InitListExpr>(RetExpr)) {
@@ -2745,13 +2816,21 @@
QualType FnRetType;
QualType RelatedRetType;
+ const AttrVec *Attrs = 0;
+ bool isObjCMethod = false;
+
if (const FunctionDecl *FD = getCurFunctionDecl()) {
- FnRetType = FD->getResultType();
+ FnRetType = FD->getReturnType();
+ if (FD->hasAttrs())
+ Attrs = &FD->getAttrs();
if (FD->isNoReturn())
Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
<< FD->getDeclName();
} else if (ObjCMethodDecl *MD = getCurMethodDecl()) {
- FnRetType = MD->getResultType();
+ FnRetType = MD->getReturnType();
+ isObjCMethod = true;
+ if (MD->hasAttrs())
+ Attrs = &MD->getAttrs();
if (MD->hasRelatedResultType() && MD->getClassInterface()) {
// In the implementation of a method with a related return type, the
// type used to type-check the validity of return statements within the
@@ -2771,7 +2850,7 @@
FD->setInvalidDecl();
return StmtError();
} else {
- FnRetType = FD->getResultType();
+ FnRetType = FD->getReturnType();
}
}
}
@@ -2803,8 +2882,14 @@
} else if (!RetValExp->isTypeDependent()) {
// C99 6.8.6.4p1 (ext_ since GCC warns)
unsigned D = diag::ext_return_has_expr;
- if (RetValExp->getType()->isVoidType())
- D = diag::ext_return_has_void_expr;
+ if (RetValExp->getType()->isVoidType()) {
+ NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
+ if (isa<CXXConstructorDecl>(CurDecl) ||
+ isa<CXXDestructorDecl>(CurDecl))
+ D = diag::err_ctor_dtor_returns_void;
+ else
+ D = diag::ext_return_has_void_expr;
+ }
else {
ExprResult Result = Owned(RetValExp);
Result = IgnoredValueConversions(Result.take());
@@ -2814,9 +2899,15 @@
RetValExp = ImpCastExprToType(RetValExp,
Context.VoidTy, CK_ToVoid).take();
}
-
+ // return of void in constructor/destructor is illegal in C++.
+ if (D == diag::err_ctor_dtor_returns_void) {
+ NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
+ Diag(ReturnLoc, D)
+ << CurDecl->getDeclName() << isa<CXXDestructorDecl>(CurDecl)
+ << RetValExp->getSourceRange();
+ }
// return (some void expression); is legal in C++.
- if (D != diag::ext_return_has_void_expr ||
+ else if (D != diag::ext_return_has_void_expr ||
!getLangOpts().CPlusPlus) {
NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
@@ -2894,7 +2985,8 @@
RetValExp = Res.takeAs<Expr>();
}
- CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+ CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc, isObjCMethod, Attrs,
+ getCurFunctionDecl());
}
if (RetValExp) {
@@ -3269,10 +3361,7 @@
RecordDecl *Record = RSI->TheRecordDecl;
Record->setInvalidDecl();
- SmallVector<Decl*, 4> Fields;
- for (RecordDecl::field_iterator I = Record->field_begin(),
- E = Record->field_end(); I != E; ++I)
- Fields.push_back(*I);
+ SmallVector<Decl*, 4> Fields(Record->fields());
ActOnFields(/*Scope=*/0, Record->getLocation(), Record, Fields,
SourceLocation(), SourceLocation(), /*AttributeList=*/0);
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index eb0188a..9bb191d 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "TargetAttributesSema.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
@@ -41,7 +40,8 @@
S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_outside_switch);
return 0;
}
- return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context);
+ return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context,
+ A.getAttributeSpellingListIndex());
}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 28603da..9be7189 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -10,8 +10,8 @@
//===----------------------------------------------------------------------===/
#include "TreeTransform.h"
-#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
@@ -20,6 +20,7 @@
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
@@ -193,8 +194,7 @@
TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl());
if (SS.isSet() && !SS.isInvalid()) {
- NestedNameSpecifier *Qualifier
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ NestedNameSpecifier *Qualifier = SS.getScopeRep();
Template = Context.getQualifiedTemplateName(Qualifier,
hasTemplateKeyword, TD);
} else {
@@ -968,7 +968,8 @@
PrevDecl = (*Previous.begin())->getUnderlyingDecl();
}
}
- } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
+ } else if (PrevDecl &&
+ !isDeclInScope(PrevDecl, SemanticContext, S, SS.isValid()))
PrevDecl = PrevClassTemplate = 0;
if (PrevClassTemplate) {
@@ -1487,6 +1488,9 @@
unsigned Depth;
bool Match;
+ SourceLocation MatchLoc;
+
+ DependencyChecker(unsigned Depth) : Depth(Depth), Match(false) {}
DependencyChecker(TemplateParameterList *Params) : Match(false) {
NamedDecl *ND = Params->getParam(0);
@@ -1500,14 +1504,19 @@
}
}
- bool Matches(unsigned ParmDepth) {
+ bool Matches(unsigned ParmDepth, SourceLocation Loc = SourceLocation()) {
if (ParmDepth >= Depth) {
Match = true;
+ MatchLoc = Loc;
return true;
}
return false;
}
+ bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+ return !Matches(TL.getTypePtr()->getDepth(), TL.getNameLoc());
+ }
+
bool VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
return !Matches(T->getDepth());
}
@@ -1515,21 +1524,28 @@
bool TraverseTemplateName(TemplateName N) {
if (TemplateTemplateParmDecl *PD =
dyn_cast_or_null<TemplateTemplateParmDecl>(N.getAsTemplateDecl()))
- if (Matches(PD->getDepth())) return false;
+ if (Matches(PD->getDepth()))
+ return false;
return super::TraverseTemplateName(N);
}
bool VisitDeclRefExpr(DeclRefExpr *E) {
if (NonTypeTemplateParmDecl *PD =
- dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) {
- if (PD->getDepth() == Depth) {
- Match = true;
+ dyn_cast<NonTypeTemplateParmDecl>(E->getDecl()))
+ if (Matches(PD->getDepth(), E->getExprLoc()))
return false;
- }
- }
return super::VisitDeclRefExpr(E);
}
-
+
+ bool VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
+ return TraverseType(T->getReplacementType());
+ }
+
+ bool
+ VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
+ return TraverseTemplateArgument(T->getArgumentPack());
+ }
+
bool TraverseInjectedClassNameType(const InjectedClassNameType *T) {
return TraverseType(T->getInjectedSpecializationType());
}
@@ -1959,7 +1975,8 @@
TemplateArgs);
TemplateDecl *Template = Name.getAsTemplateDecl();
- if (!Template || isa<FunctionTemplateDecl>(Template)) {
+ if (!Template || isa<FunctionTemplateDecl>(Template) ||
+ isa<VarTemplateDecl>(Template)) {
// We might have a substituted template template parameter pack. If so,
// build a template specialization type for it.
if (Name.getAsSubstTemplateTemplateParmPack())
@@ -1974,17 +1991,15 @@
// Check that the template argument list is well-formed for this
// template.
SmallVector<TemplateArgument, 4> Converted;
- bool ExpansionIntoFixedList = false;
if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs,
- false, Converted, &ExpansionIntoFixedList))
+ false, Converted))
return QualType();
QualType CanonType;
bool InstantiationDependent = false;
- TypeAliasTemplateDecl *AliasTemplate = 0;
- if (!ExpansionIntoFixedList &&
- (AliasTemplate = dyn_cast<TypeAliasTemplateDecl>(Template))) {
+ if (TypeAliasTemplateDecl *AliasTemplate =
+ dyn_cast<TypeAliasTemplateDecl>(Template)) {
// Find the canonical type for this type alias template specialization.
TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl();
if (Pattern->isInvalidDecl())
@@ -2267,8 +2282,8 @@
}
static bool CheckTemplatePartialSpecializationArgs(
- Sema &S, TemplateParameterList *TemplateParams,
- SmallVectorImpl<TemplateArgument> &TemplateArgs);
+ Sema &S, SourceLocation NameLoc, TemplateParameterList *TemplateParams,
+ unsigned ExplicitArgs, SmallVectorImpl<TemplateArgument> &TemplateArgs);
static bool CheckTemplateSpecializationScope(Sema &S, NamedDecl *Specialized,
NamedDecl *PrevDecl,
@@ -2341,11 +2356,9 @@
}
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?");
-
+ Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation TemplateKWLoc,
+ TemplateParameterList *TemplateParams, VarDecl::StorageClass SC,
+ bool IsPartialSpecialization) {
// D must be variable template id.
assert(D.getName().getKind() == UnqualifiedId::IK_TemplateId &&
"Variable template specialization is declared with a template it.");
@@ -2358,7 +2371,14 @@
TemplateId->NumArgs);
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
- TemplateName Name(VarTemplate);
+ TemplateName Name = TemplateId->Template.get();
+
+ // The template-id must name a variable template.
+ VarTemplateDecl *VarTemplate =
+ dyn_cast<VarTemplateDecl>(Name.getAsTemplateDecl());
+ if (!VarTemplate)
+ return Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template)
+ << IsPartialSpecialization;
// Check for unexpanded parameter packs in any of the template arguments.
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
@@ -2396,7 +2416,8 @@
// corresponds to these arguments.
if (IsPartialSpecialization) {
if (CheckTemplatePartialSpecializationArgs(
- *this, VarTemplate->getTemplateParameters(), Converted))
+ *this, TemplateNameLoc, VarTemplate->getTemplateParameters(),
+ TemplateArgs.size(), Converted))
return true;
bool InstantiationDependent;
@@ -2494,7 +2515,7 @@
<< Param->getDeclName();
else
Diag(Param->getLocation(), diag::note_partial_spec_unused_parameter)
- << "<anonymous>";
+ << "(anonymous)";
}
}
}
@@ -2589,11 +2610,10 @@
// 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))
+ Converted))
return true;
// Find the variable template specialization declaration that
@@ -2652,11 +2672,6 @@
}
}
- // 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) {
@@ -2779,10 +2794,13 @@
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));
+ bool InstantiationDependent;
+ if (R.getAsSingle<VarTemplateDecl>() &&
+ !TemplateSpecializationType::anyDependentTemplateArguments(
+ *TemplateArgs, InstantiationDependent)) {
+ return CheckVarTemplateId(SS, R.getLookupNameInfo(),
+ R.getAsSingle<VarTemplateDecl>(),
+ TemplateKWLoc, TemplateArgs);
}
// We don't want lookup warnings at this point.
@@ -2829,7 +2847,7 @@
if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) {
Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_class_template)
- << (NestedNameSpecifier*) SS.getScopeRep()
+ << SS.getScopeRep()
<< NameInfo.getName() << SS.getRange();
Diag(Temp->getLocation(), diag::note_referenced_class_template);
return ExprError();
@@ -2903,8 +2921,7 @@
}
}
- NestedNameSpecifier *Qualifier
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ NestedNameSpecifier *Qualifier = SS.getScopeRep();
switch (Name.getKind()) {
case UnqualifiedId::IK_Identifier:
@@ -2915,11 +2932,10 @@
case UnqualifiedId::IK_OperatorFunctionId:
Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
Name.OperatorFunctionId.Operator));
- return TNK_Dependent_template_name;
+ return TNK_Function_template;
case UnqualifiedId::IK_LiteralOperatorId:
- llvm_unreachable(
- "We don't support these; Parse shouldn't have allowed propagation");
+ llvm_unreachable("literal operator id cannot have a dependent scope");
default:
break;
@@ -3555,11 +3571,7 @@
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs,
bool PartialTemplateArgs,
- SmallVectorImpl<TemplateArgument> &Converted,
- bool *ExpansionIntoFixedList) {
- if (ExpansionIntoFixedList)
- *ExpansionIntoFixedList = false;
-
+ SmallVectorImpl<TemplateArgument> &Converted) {
TemplateParameterList *Params = Template->getTemplateParameters();
SourceLocation RAngleLoc = TemplateArgs.getRAngleLoc();
@@ -3612,6 +3624,20 @@
ArgumentPack.size(), Converted))
return true;
+ if (TemplateArgs[ArgIdx].getArgument().isPackExpansion() &&
+ isa<TypeAliasTemplateDecl>(Template) &&
+ !(Param + 1 == ParamEnd && (*Param)->isTemplateParameterPack() &&
+ !getExpandedPackSize(*Param))) {
+ // Core issue 1430: we have a pack expansion as an argument to an
+ // alias template, and it's not part of a final parameter pack. This
+ // can't be canonicalized, so reject it now.
+ Diag(TemplateArgs[ArgIdx].getLocation(),
+ diag::err_alias_template_expansion_into_fixed_list)
+ << TemplateArgs[ArgIdx].getSourceRange();
+ Diag((*Param)->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
// We're now done with this argument.
++ArgIdx;
@@ -3658,9 +3684,6 @@
ArgumentPack.data(),
ArgumentPack.size()));
ArgumentPack.clear();
- } else if (ExpansionIntoFixedList) {
- // We have expanded a pack into a fixed list.
- *ExpansionIntoFixedList = true;
}
return false;
@@ -3889,19 +3912,17 @@
bool UnnamedLocalNoLinkageFinder::VisitFunctionProtoType(
const FunctionProtoType* T) {
- for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(),
- AEnd = T->arg_type_end();
- A != AEnd; ++A) {
- if (Visit(*A))
+ for (const auto &A : T->param_types()) {
+ if (Visit(A))
return true;
}
- return Visit(T->getResultType());
+ return Visit(T->getReturnType());
}
bool UnnamedLocalNoLinkageFinder::VisitFunctionNoProtoType(
const FunctionNoProtoType* T) {
- return Visit(T->getResultType());
+ return Visit(T->getReturnType());
}
bool UnnamedLocalNoLinkageFinder::VisitUnresolvedUsingType(
@@ -4523,6 +4544,8 @@
case NPV_NullPointer:
S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
Converted = TemplateArgument(ParamType, /*isNullPtr*/true);
+ if (S.Context.getTargetInfo().getCXXABI().isMicrosoft())
+ S.RequireCompleteType(Arg->getExprLoc(), ParamType, 0);
return false;
case NPV_NotNullPointer:
break;
@@ -4756,9 +4779,9 @@
public:
TmplArgICEDiagnoser(QualType T) : T(T) { }
-
- virtual void diagnoseNotICE(Sema &S, SourceLocation Loc,
- SourceRange SR) {
+
+ void diagnoseNotICE(Sema &S, SourceLocation Loc,
+ SourceRange SR) override {
S.Diag(Loc, diag::err_template_arg_not_ice) << T << SR;
}
} Diagnoser(ArgType);
@@ -5450,18 +5473,19 @@
(S->getFlags() & Scope::TemplateParamScope) != 0)
S = S->getParent();
- // C++ [temp]p2:
- // A template-declaration can appear only as a namespace scope or
- // class scope declaration.
+ // C++ [temp]p4:
+ // A template [...] shall not have C linkage.
DeclContext *Ctx = S->getEntity();
- if (Ctx && isa<LinkageSpecDecl>(Ctx) &&
- cast<LinkageSpecDecl>(Ctx)->getLanguage() != LinkageSpecDecl::lang_cxx)
+ if (Ctx && Ctx->isExternCContext())
return Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage)
<< TemplateParams->getSourceRange();
while (Ctx && isa<LinkageSpecDecl>(Ctx))
Ctx = Ctx->getParent();
+ // C++ [temp]p2:
+ // A template-declaration can appear only as a namespace scope or
+ // class scope declaration.
if (Ctx) {
if (Ctx->isFileContext())
return false;
@@ -5598,13 +5622,37 @@
// A class template partial specialization may be declared or redeclared
// in any namespace scope in which its definition may be defined (14.5.1
// and 14.5.2).
- bool ComplainedAboutScope = false;
- DeclContext *SpecializedContext
+ DeclContext *SpecializedContext
= Specialized->getDeclContext()->getEnclosingNamespaceContext();
DeclContext *DC = S.CurContext->getEnclosingNamespaceContext();
- if ((!PrevDecl ||
- getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared ||
- getTemplateSpecializationKind(PrevDecl) == TSK_ImplicitInstantiation)){
+
+ // Make sure that this redeclaration (or definition) occurs in an enclosing
+ // namespace.
+ // Note that HandleDeclarator() performs this check for explicit
+ // specializations of function templates, static data members, and member
+ // functions, so we skip the check here for those kinds of entities.
+ // FIXME: HandleDeclarator's diagnostics aren't quite as good, though.
+ // Should we refactor that check, so that it occurs later?
+ if (!DC->Encloses(SpecializedContext) &&
+ !(isa<FunctionTemplateDecl>(Specialized) ||
+ isa<FunctionDecl>(Specialized) ||
+ isa<VarTemplateDecl>(Specialized) ||
+ isa<VarDecl>(Specialized))) {
+ if (isa<TranslationUnitDecl>(SpecializedContext))
+ S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
+ << EntityKind << Specialized;
+ else if (isa<NamespaceDecl>(SpecializedContext))
+ S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope)
+ << EntityKind << Specialized
+ << cast<NamedDecl>(SpecializedContext);
+ else
+ llvm_unreachable("unexpected namespace context for specialization");
+
+ S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
+ } else if ((!PrevDecl ||
+ getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared ||
+ getTemplateSpecializationKind(PrevDecl) ==
+ TSK_ImplicitInstantiation)) {
// C++ [temp.exp.spec]p2:
// An explicit specialization shall be declared in the namespace of which
// the template is a member, or, for member templates, in the namespace
@@ -5613,9 +5661,12 @@
// static data member of a class template shall be declared in the
// namespace of which the class template is a member.
//
- // C++0x [temp.expl.spec]p2:
+ // C++11 [temp.expl.spec]p2:
// An explicit specialization shall be declared in a namespace enclosing
// the specialized template.
+ // C++11 [temp.explicit]p3:
+ // An explicit instantiation shall appear in an enclosing namespace of its
+ // template.
if (!DC->InEnclosingNamespaceSetOf(SpecializedContext)) {
bool IsCPlusPlus11Extension = DC->Encloses(SpecializedContext);
if (isa<TranslationUnitDecl>(SpecializedContext)) {
@@ -5636,46 +5687,42 @@
}
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
- ComplainedAboutScope =
- !(IsCPlusPlus11Extension && S.getLangOpts().CPlusPlus11);
}
}
- // Make sure that this redeclaration (or definition) occurs in an enclosing
- // namespace.
- // Note that HandleDeclarator() performs this check for explicit
- // specializations of function templates, static data members, and member
- // functions, so we skip the check here for those kinds of entities.
- // FIXME: HandleDeclarator's diagnostics aren't quite as good, though.
- // Should we refactor that check, so that it occurs later?
- if (!ComplainedAboutScope && !DC->Encloses(SpecializedContext) &&
- !(isa<FunctionTemplateDecl>(Specialized) || isa<VarDecl>(Specialized) ||
- isa<FunctionDecl>(Specialized))) {
- if (isa<TranslationUnitDecl>(SpecializedContext))
- S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
- << EntityKind << Specialized;
- else if (isa<NamespaceDecl>(SpecializedContext))
- S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope)
- << EntityKind << Specialized
- << cast<NamedDecl>(SpecializedContext);
-
- S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
- }
-
- // FIXME: check for specialization-after-instantiation errors and such.
-
return false;
}
+static SourceRange findTemplateParameter(unsigned Depth, Expr *E) {
+ if (!E->isInstantiationDependent())
+ return SourceLocation();
+ DependencyChecker Checker(Depth);
+ Checker.TraverseStmt(E);
+ if (Checker.Match && Checker.MatchLoc.isInvalid())
+ return E->getSourceRange();
+ return Checker.MatchLoc;
+}
+
+static SourceRange findTemplateParameter(unsigned Depth, TypeLoc TL) {
+ if (!TL.getType()->isDependentType())
+ return SourceLocation();
+ DependencyChecker Checker(Depth);
+ Checker.TraverseTypeLoc(TL);
+ if (Checker.Match && Checker.MatchLoc.isInvalid())
+ return TL.getSourceRange();
+ return Checker.MatchLoc;
+}
+
/// \brief Subroutine of Sema::CheckTemplatePartialSpecializationArgs
/// that checks non-type template partial specialization arguments.
static bool CheckNonTypeTemplatePartialSpecializationArgs(
- Sema &S, NonTypeTemplateParmDecl *Param, const TemplateArgument *Args,
- unsigned NumArgs) {
+ Sema &S, SourceLocation TemplateNameLoc, NonTypeTemplateParmDecl *Param,
+ const TemplateArgument *Args, unsigned NumArgs, bool IsDefaultArgument) {
for (unsigned I = 0; I != NumArgs; ++I) {
if (Args[I].getKind() == TemplateArgument::Pack) {
if (CheckNonTypeTemplatePartialSpecializationArgs(
- S, Param, Args[I].pack_begin(), Args[I].pack_size()))
+ S, TemplateNameLoc, Param, Args[I].pack_begin(),
+ Args[I].pack_size(), IsDefaultArgument))
return true;
continue;
@@ -5713,22 +5760,43 @@
// shall not involve a template parameter of the partial
// specialization except when the argument expression is a
// simple identifier.
- if (ArgExpr->isTypeDependent() || ArgExpr->isValueDependent()) {
- S.Diag(ArgExpr->getLocStart(),
- diag::err_dependent_non_type_arg_in_partial_spec)
- << ArgExpr->getSourceRange();
+ SourceRange ParamUseRange =
+ findTemplateParameter(Param->getDepth(), ArgExpr);
+ if (ParamUseRange.isValid()) {
+ if (IsDefaultArgument) {
+ S.Diag(TemplateNameLoc,
+ diag::err_dependent_non_type_arg_in_partial_spec);
+ S.Diag(ParamUseRange.getBegin(),
+ diag::note_dependent_non_type_default_arg_in_partial_spec)
+ << ParamUseRange;
+ } else {
+ S.Diag(ParamUseRange.getBegin(),
+ diag::err_dependent_non_type_arg_in_partial_spec)
+ << ParamUseRange;
+ }
return true;
}
// -- The type of a template parameter corresponding to a
// specialized non-type argument shall not be dependent on a
// parameter of the specialization.
- if (Param->getType()->isDependentType()) {
- S.Diag(ArgExpr->getLocStart(),
- diag::err_dependent_typed_non_type_arg_in_partial_spec)
- << Param->getType()
- << ArgExpr->getSourceRange();
- S.Diag(Param->getLocation(), diag::note_template_param_here);
+ //
+ // FIXME: We need to delay this check until instantiation in some cases:
+ //
+ // template<template<typename> class X> struct A {
+ // template<typename T, X<T> N> struct B;
+ // template<typename T> struct B<T, 0>;
+ // };
+ // template<typename> using X = int;
+ // A<X>::B<int, 0> b;
+ ParamUseRange = findTemplateParameter(
+ Param->getDepth(), Param->getTypeSourceInfo()->getTypeLoc());
+ if (ParamUseRange.isValid()) {
+ S.Diag(IsDefaultArgument ? TemplateNameLoc : ArgExpr->getLocStart(),
+ diag::err_dependent_typed_non_type_arg_in_partial_spec)
+ << Param->getType() << ParamUseRange;
+ S.Diag(Param->getLocation(), diag::note_template_param_here)
+ << (IsDefaultArgument ? ParamUseRange : SourceRange());
return true;
}
}
@@ -5739,15 +5807,17 @@
/// \brief Check the non-type template arguments of a class template
/// partial specialization according to C++ [temp.class.spec]p9.
///
+/// \param TemplateNameLoc the location of the template name.
/// \param TemplateParams the template parameters of the primary class
-/// template.
-///
+/// template.
+/// \param NumExplicit the number of explicitly-specified template arguments.
/// \param TemplateArgs the template arguments of the class template
-/// partial specialization.
+/// partial specialization.
///
-/// \returns true if there was an error, false otherwise.
+/// \returns \c true if there was an error, \c false otherwise.
static bool CheckTemplatePartialSpecializationArgs(
- Sema &S, TemplateParameterList *TemplateParams,
+ Sema &S, SourceLocation TemplateNameLoc,
+ TemplateParameterList *TemplateParams, unsigned NumExplicit,
SmallVectorImpl<TemplateArgument> &TemplateArgs) {
const TemplateArgument *ArgList = TemplateArgs.data();
@@ -5757,7 +5827,8 @@
if (!Param)
continue;
- if (CheckNonTypeTemplatePartialSpecializationArgs(S, Param, &ArgList[I], 1))
+ if (CheckNonTypeTemplatePartialSpecializationArgs(
+ S, TemplateNameLoc, Param, &ArgList[I], 1, I >= NumExplicit))
return true;
}
@@ -5904,7 +5975,8 @@
// corresponds to these arguments.
if (isPartialSpecialization) {
if (CheckTemplatePartialSpecializationArgs(
- *this, ClassTemplate->getTemplateParameters(), Converted))
+ *this, TemplateNameLoc, ClassTemplate->getTemplateParameters(),
+ TemplateArgs.size(), Converted))
return true;
bool InstantiationDependent;
@@ -6043,7 +6115,7 @@
else
Diag(Param->getLocation(),
diag::note_partial_spec_unused_parameter)
- << "<anonymous>";
+ << "(anonymous)";
}
}
}
@@ -6210,10 +6282,8 @@
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
FD->setInlineSpecified(false);
- for (FunctionDecl::param_iterator I = FD->param_begin(),
- E = FD->param_end();
- I != E; ++I)
- (*I)->dropAttrs();
+ for (auto I : FD->params())
+ I->dropAttrs();
}
}
@@ -6509,8 +6579,8 @@
const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals |= Qualifiers::Const;
- FT = Context.getFunctionType(FPT->getResultType(), FPT->getArgTypes(),
- EPI);
+ FT = Context.getFunctionType(FPT->getReturnType(),
+ FPT->getParamTypes(), EPI);
}
}
@@ -6656,7 +6726,10 @@
I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
- if (Context.hasSameType(Function->getType(), Method->getType())) {
+ QualType Adjusted = Function->getType();
+ if (!hasExplicitCallingConv(Adjusted))
+ Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
+ if (Context.hasSameType(Adjusted, Method->getType())) {
Instantiation = Method;
InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
MSInfo = Method->getMemberSpecializationInfo();
@@ -6877,8 +6950,8 @@
// name shall be a simple-template-id.
//
// C++98 has the same restriction, just worded differently.
- for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
- NNS; NNS = NNS->getPrefix())
+ for (NestedNameSpecifier *NNS = SS.getScopeRep(); NNS;
+ NNS = NNS->getPrefix())
if (const Type *T = NNS->getAsType())
if (isa<TemplateSpecializationType>(T))
return true;
@@ -7102,7 +7175,8 @@
KWLoc, SS, Name, NameLoc, Attr, AS_none,
/*ModulePrivateLoc=*/SourceLocation(),
MultiTemplateParamsArg(), Owned, IsDependent,
- SourceLocation(), false, TypeResult());
+ SourceLocation(), false, TypeResult(),
+ /*IsTypeSpecifier*/false);
assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
if (!TagD)
@@ -7554,8 +7628,7 @@
// This has to hold, because SS is expected to be defined.
assert(Name && "Expected a name in a dependent tag");
- NestedNameSpecifier *NNS
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ NestedNameSpecifier *NNS = SS.getScopeRep();
if (!NNS)
return true;
@@ -7641,8 +7714,7 @@
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
// Construct a dependent template specialization type.
assert(DTN && "dependent template has non-dependent name?");
- assert(DTN->getQualifier()
- == static_cast<NestedNameSpecifier*>(SS.getScopeRep()));
+ assert(DTN->getQualifier() == SS.getScopeRep());
QualType T = Context.getDependentTemplateSpecializationType(ETK_Typename,
DTN->getQualifier(),
DTN->getIdentifier(),
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 8d66ff6..8a0589a 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -783,7 +783,7 @@
S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
unsigned Depth, Index;
- llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
+ std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
if (Depth == 0 && !SawIndices[Index]) {
SawIndices[Index] = true;
PackIndices.push_back(Index);
@@ -981,6 +981,17 @@
Comparison.Qualifiers = ParamMoreQualified;
else if (ArgQuals.isStrictSupersetOf(ParamQuals))
Comparison.Qualifiers = ArgMoreQualified;
+ else if (ArgQuals.getObjCLifetime() != ParamQuals.getObjCLifetime() &&
+ ArgQuals.withoutObjCLifetime()
+ == ParamQuals.withoutObjCLifetime()) {
+ // Prefer binding to non-__unsafe_autoretained parameters.
+ if (ArgQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone &&
+ ParamQuals.getObjCLifetime())
+ Comparison.Qualifiers = ParamMoreQualified;
+ else if (ParamQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone &&
+ ArgQuals.getObjCLifetime())
+ Comparison.Qualifiers = ArgMoreQualified;
+ }
RefParamComparisons->push_back(Comparison);
}
@@ -1364,19 +1375,17 @@
return Sema::TDK_NonDeducedMismatch;
// Check return types.
- if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
- FunctionProtoParam->getResultType(),
- FunctionProtoArg->getResultType(),
- Info, Deduced, 0))
+ if (Sema::TemplateDeductionResult Result =
+ DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, FunctionProtoParam->getReturnType(),
+ FunctionProtoArg->getReturnType(), Info, Deduced, 0))
return Result;
- return DeduceTemplateArguments(S, TemplateParams,
- FunctionProtoParam->arg_type_begin(),
- FunctionProtoParam->getNumArgs(),
- FunctionProtoArg->arg_type_begin(),
- FunctionProtoArg->getNumArgs(),
- Info, Deduced, SubTDF);
+ return DeduceTemplateArguments(
+ S, TemplateParams, FunctionProtoParam->param_type_begin(),
+ FunctionProtoParam->getNumParams(),
+ FunctionProtoArg->param_type_begin(),
+ FunctionProtoArg->getNumParams(), Info, Deduced, SubTDF);
}
case Type::InjectedClassName: {
@@ -1463,12 +1472,10 @@
// Visit base classes
CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl());
- for (CXXRecordDecl::base_class_iterator Base = Next->bases_begin(),
- BaseEnd = Next->bases_end();
- Base != BaseEnd; ++Base) {
- assert(Base->getType()->isRecordType() &&
+ for (const auto &Base : Next->bases()) {
+ assert(Base.getType()->isRecordType() &&
"Base class that isn't a record?");
- ToVisit.push_back(Base->getType()->getAs<RecordType>());
+ ToVisit.push_back(Base.getType()->getAs<RecordType>());
}
}
@@ -1854,7 +1861,7 @@
S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
unsigned Depth, Index;
- llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
+ std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
if (Depth == 0 && !SawIndices[Index]) {
SawIndices[Index] = true;
PackIndices.push_back(Index);
@@ -2274,8 +2281,8 @@
return Result;
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
- InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
- DeducedArgs, Info);
+ InstantiatingTemplate Inst(*this, Info.getLocation(), Partial, DeducedArgs,
+ Info);
if (Inst.isInvalid())
return TDK_InstantiationDepth;
@@ -2438,8 +2445,8 @@
return Result;
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
- InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
- DeducedArgs, Info);
+ InstantiatingTemplate Inst(*this, Info.getLocation(), Partial, DeducedArgs,
+ Info);
if (Inst.isInvalid())
return TDK_InstantiationDepth;
@@ -2498,11 +2505,8 @@
if (ExplicitTemplateArgs.size() == 0) {
// No arguments to substitute; just copy over the parameter types and
// fill in the function type.
- for (FunctionDecl::param_iterator P = Function->param_begin(),
- PEnd = Function->param_end();
- P != PEnd;
- ++P)
- ParamTypes.push_back((*P)->getType());
+ for (auto P : Function->params())
+ ParamTypes.push_back(P->getType());
if (FunctionType)
*FunctionType = Function->getType();
@@ -2524,8 +2528,8 @@
// explicitly-specified template arguments against this function template,
// and then substitute them into the function parameter types.
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
- InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
- FunctionTemplate, DeducedArgs,
+ InstantiatingTemplate Inst(*this, Info.getLocation(), FunctionTemplate,
+ DeducedArgs,
ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution,
Info);
if (Inst.isInvalid())
@@ -2604,11 +2608,11 @@
CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals,
getLangOpts().CPlusPlus11);
-
- ResultType = SubstType(Proto->getResultType(),
- MultiLevelTemplateArgumentList(*ExplicitArgumentList),
- Function->getTypeSpecStartLoc(),
- Function->getDeclName());
+
+ ResultType =
+ SubstType(Proto->getReturnType(),
+ MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+ Function->getTypeSpecStartLoc(), Function->getDeclName());
if (ResultType.isNull() || Trap.hasErrorOccurred())
return TDK_SubstitutionFailure;
}
@@ -2778,8 +2782,8 @@
// Enter a new template instantiation context while we instantiate the
// actual function declaration.
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
- InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
- FunctionTemplate, DeducedArgs,
+ InstantiatingTemplate Inst(*this, Info.getLocation(), FunctionTemplate,
+ DeducedArgs,
ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
Info);
if (Inst.isInvalid())
@@ -2976,8 +2980,8 @@
static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R,
FunctionDecl *Fn) {
// We may need to deduce the return type of the function now.
- if (S.getLangOpts().CPlusPlus1y && Fn->getResultType()->isUndeducedType() &&
- S.DeduceReturnType(Fn, R.Expression->getExprLoc(), /*Diagnose*/false))
+ if (S.getLangOpts().CPlusPlus1y && Fn->getReturnType()->isUndeducedType() &&
+ S.DeduceReturnType(Fn, R.Expression->getExprLoc(), /*Diagnose*/ false))
return QualType();
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn))
@@ -3406,7 +3410,7 @@
collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
unsigned Depth, Index;
- llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
+ std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
if (Depth == 0 && !SawIndices[Index]) {
SawIndices[Index] = true;
PackIndices.push_back(Index);
@@ -3589,7 +3593,7 @@
// type so that we treat it as a non-deduced context in what follows.
bool HasDeducedReturnType = false;
if (getLangOpts().CPlusPlus1y && InOverloadResolution &&
- Function->getResultType()->getContainedAutoType()) {
+ Function->getReturnType()->getContainedAutoType()) {
FunctionType = SubstAutoType(FunctionType, Context.DependentTy);
HasDeducedReturnType = true;
}
@@ -3614,7 +3618,7 @@
// 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 (HasDeducedReturnType &&
- Specialization->getResultType()->isUndeducedType() &&
+ Specialization->getReturnType()->isUndeducedType() &&
DeduceReturnType(Specialization, Info.getLocation(), false))
return TDK_MiscellaneousDeductionFailure;
@@ -3643,7 +3647,7 @@
SubstAutoWithinFunctionReturnType(FunctionDecl *F,
QualType TypeToReplaceAutoWith, Sema &S) {
assert(!TypeToReplaceAutoWith->getContainedAutoType());
- QualType AutoResultType = F->getResultType();
+ QualType AutoResultType = F->getReturnType();
assert(AutoResultType->getContainedAutoType());
QualType DeducedResultType = S.SubstAutoType(AutoResultType,
TypeToReplaceAutoWith);
@@ -3668,7 +3672,7 @@
assert(LambdaClass && LambdaClass->isGenericLambda());
CXXMethodDecl *CallOpGeneric = LambdaClass->getLambdaCallOperator();
- QualType CallOpResultType = CallOpGeneric->getResultType();
+ QualType CallOpResultType = CallOpGeneric->getReturnType();
const bool GenericLambdaCallOperatorHasDeducedReturnType =
CallOpResultType->getContainedAutoType();
@@ -3685,15 +3689,15 @@
return Result;
// If we need to deduce the return type, do so (instantiates the callop).
- if (GenericLambdaCallOperatorHasDeducedReturnType &&
- CallOpSpecialized->getResultType()->isUndeducedType())
+ if (GenericLambdaCallOperatorHasDeducedReturnType &&
+ CallOpSpecialized->getReturnType()->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(),
+ if (!S.Context.hasSameType(CallOpSpecialized->getReturnType(),
ReturnTypeOfDestFunctionPtr))
return Sema::TDK_NonDeducedMismatch;
// Since we have succeeded in matching the source and destination
@@ -3712,8 +3716,8 @@
"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()) {
+ if (GenericLambdaCallOperatorHasDeducedReturnType &&
+ InvokerSpecialized->getReturnType()->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
@@ -3722,9 +3726,9 @@
// 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();
+ QualType TypeToReplaceAutoWith = CallOpSpecialized->getReturnType()
+ ->getContainedAutoType()
+ ->getDeducedType();
SubstAutoWithinFunctionReturnType(InvokerSpecialized,
TypeToReplaceAutoWith, S);
SubstAutoWithinFunctionReturnType(ConversionSpecialized,
@@ -3740,7 +3744,7 @@
FunctionProtoType::ExtProtoInfo EPI = InvokerFPT->getExtProtoInfo();
EPI.TypeQuals = 0;
InvokerSpecialized->setType(S.Context.getFunctionType(
- InvokerFPT->getResultType(), InvokerFPT->getArgTypes(),EPI));
+ InvokerFPT->getReturnType(), InvokerFPT->getParamTypes(), EPI));
return Sema::TDK_Success;
}
/// \brief Deduce template arguments for a templated conversion
@@ -3863,8 +3867,8 @@
"Can only convert from lambda to ptr-to-function");
const FunctionType *ToFunType =
A->getPointeeType().getTypePtr()->getAs<FunctionType>();
- const QualType DestFunctionPtrReturnType = ToFunType->getResultType();
-
+ const QualType DestFunctionPtrReturnType = ToFunType->getReturnType();
+
// 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
@@ -4109,12 +4113,12 @@
bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
bool Diagnose) {
- assert(FD->getResultType()->isUndeducedType());
+ assert(FD->getReturnType()->isUndeducedType());
if (FD->getTemplateInstantiationPattern())
InstantiateFunctionDefinition(Loc, FD);
- bool StillUndeduced = FD->getResultType()->isUndeducedType();
+ bool StillUndeduced = FD->getReturnType()->isUndeducedType();
if (StillUndeduced && Diagnose && !FD->isInvalidDecl()) {
Diag(Loc, diag::err_auto_fn_used_before_defined) << FD;
Diag(FD->getLocation(), diag::note_callee_decl) << FD;
@@ -4220,10 +4224,10 @@
++Skip1;
}
- Args1.insert(Args1.end(),
- Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end());
- Args2.insert(Args2.end(),
- Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end());
+ Args1.insert(Args1.end(), Proto1->param_type_begin() + Skip1,
+ Proto1->param_type_end());
+ Args2.insert(Args2.end(), Proto2->param_type_begin() + Skip2,
+ Proto2->param_type_end());
// C++ [temp.func.order]p5:
// The presence of unused ellipsis and default arguments has no effect on
@@ -4244,12 +4248,10 @@
case TPOC_Conversion:
// - In the context of a call to a conversion operator, the return types
// of the conversion function templates are used.
- if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
- Proto2->getResultType(),
- Proto1->getResultType(),
- Info, Deduced, TDF_None,
- /*PartialOrdering=*/true,
- RefParamComparisons))
+ if (DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, Proto2->getReturnType(), Proto1->getReturnType(),
+ Info, Deduced, TDF_None,
+ /*PartialOrdering=*/true, RefParamComparisons))
return false;
break;
@@ -4293,9 +4295,8 @@
break;
case TPOC_Conversion:
- ::MarkUsedTemplateParameters(S.Context, Proto2->getResultType(), false,
- TemplateParams->getDepth(),
- UsedParameters);
+ ::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false,
+ TemplateParams->getDepth(), UsedParameters);
break;
case TPOC_Other:
@@ -4613,8 +4614,7 @@
/*RefParamComparisons=*/0);
if (Better1) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
- InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2, DeducedArgs,
- Info);
+ InstantiatingTemplate Inst(*this, Loc, PS2, DeducedArgs, Info);
Better1 = !::FinishTemplateArgumentDeduction(
*this, PS2, PS1->getTemplateArgs(), Deduced, Info);
}
@@ -4629,8 +4629,7 @@
if (Better2) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
Deduced.end());
- InstantiatingTemplate Inst(*this, PS1->getLocation(), PS1, DeducedArgs,
- Info);
+ InstantiatingTemplate Inst(*this, Loc, PS1, DeducedArgs, Info);
Better2 = !::FinishTemplateArgumentDeduction(
*this, PS1, PS2->getTemplateArgs(), Deduced, Info);
}
@@ -4653,7 +4652,7 @@
SmallVector<DeducedTemplateArgument, 4> Deduced;
TemplateDeductionInfo Info(Loc);
- assert(PS1->getSpecializedTemplate() == PS1->getSpecializedTemplate() &&
+ assert(PS1->getSpecializedTemplate() == PS2->getSpecializedTemplate() &&
"the partial specializations being compared should specialize"
" the same template.");
TemplateName Name(PS1->getSpecializedTemplate());
@@ -4674,8 +4673,7 @@
if (Better1) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
Deduced.end());
- InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2,
- DeducedArgs, Info);
+ InstantiatingTemplate Inst(*this, Loc, PS2, DeducedArgs, Info);
Better1 = !::FinishTemplateArgumentDeduction(*this, PS2,
PS1->getTemplateArgs(),
Deduced, Info);
@@ -4691,8 +4689,7 @@
/*RefParamComparisons=*/0);
if (Better2) {
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
- InstantiatingTemplate Inst(*this, PS1->getLocation(), PS1,
- DeducedArgs, Info);
+ InstantiatingTemplate Inst(*this, Loc, PS1, DeducedArgs, Info);
Better2 = !::FinishTemplateArgumentDeduction(*this, PS1,
PS2->getTemplateArgs(),
Deduced, Info);
@@ -4874,10 +4871,10 @@
case Type::FunctionProto: {
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
- MarkUsedTemplateParameters(Ctx, Proto->getResultType(), OnlyDeduced,
- Depth, Used);
- for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I)
- MarkUsedTemplateParameters(Ctx, Proto->getArgType(I), OnlyDeduced,
+ MarkUsedTemplateParameters(Ctx, Proto->getReturnType(), OnlyDeduced, Depth,
+ Used);
+ for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I)
+ MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced,
Depth, Used);
break;
}
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 8904f37..1ee3e4b 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -76,8 +76,18 @@
// 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;
+ llvm::PointerUnion<VarTemplateDecl*,
+ VarTemplatePartialSpecializationDecl*> Specialized
+ = Spec->getSpecializedTemplateOrPartial();
+ if (VarTemplatePartialSpecializationDecl *Partial =
+ Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
+ if (Partial->isMemberSpecialization())
+ return Result;
+ } else {
+ VarTemplateDecl *Tmpl = Specialized.get<VarTemplateDecl *>();
+ if (Tmpl->isMemberSpecialization())
+ return Result;
+ }
}
// If we have a template template parameter with translation unit context,
@@ -190,50 +200,49 @@
llvm_unreachable("Invalid InstantiationKind!");
}
+void Sema::InstantiatingTemplate::Initialize(
+ ActiveTemplateInstantiation::InstantiationKind Kind,
+ SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
+ Decl *Entity, NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
+ sema::TemplateDeductionInfo *DeductionInfo) {
+ SavedInNonInstantiationSFINAEContext =
+ SemaRef.InNonInstantiationSFINAEContext;
+ Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
+ if (!Invalid) {
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = Kind;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = Entity;
+ Inst.Template = Template;
+ Inst.TemplateArgs = TemplateArgs.data();
+ Inst.NumTemplateArgs = TemplateArgs.size();
+ Inst.DeductionInfo = DeductionInfo;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.InNonInstantiationSFINAEContext = false;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+ if (!Inst.isInstantiationRecord())
+ ++SemaRef.NonInstantiationEntries;
+ }
+}
+
Sema::InstantiatingTemplate::
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
Decl *Entity,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation,
- InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = Entity;
- Inst.TemplateArgs = 0;
- Inst.NumTemplateArgs = 0;
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- }
+ Initialize(ActiveTemplateInstantiation::TemplateInstantiation,
+ PointOfInstantiation, InstantiationRange, Entity);
}
Sema::InstantiatingTemplate::
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
FunctionDecl *Entity, ExceptionSpecification,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation,
- InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind = ActiveTemplateInstantiation::ExceptionSpecInstantiation;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = Entity;
- Inst.TemplateArgs = 0;
- Inst.NumTemplateArgs = 0;
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- }
+ Initialize(ActiveTemplateInstantiation::ExceptionSpecInstantiation,
+ PointOfInstantiation, InstantiationRange, Entity);
}
Sema::InstantiatingTemplate::
@@ -241,24 +250,11 @@
TemplateDecl *Template,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation,
- InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind
- = ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = Template;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- }
+ Initialize(ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation,
+ PointOfInstantiation, InstantiationRange,
+ Template, nullptr, TemplateArgs);
}
Sema::InstantiatingTemplate::
@@ -268,26 +264,10 @@
ActiveTemplateInstantiation::InstantiationKind Kind,
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind = Kind;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = FunctionTemplate;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.DeductionInfo = &DeductionInfo;
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
-
- if (!Inst.isInstantiationRecord())
- ++SemaRef.NonInstantiationEntries;
- }
+ Initialize(Kind, PointOfInstantiation, InstantiationRange,
+ FunctionTemplate, nullptr, TemplateArgs, &DeductionInfo);
}
Sema::InstantiatingTemplate::
@@ -296,23 +276,11 @@
ArrayRef<TemplateArgument> TemplateArgs,
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- 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);
- }
+ Initialize(ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
+ PointOfInstantiation, InstantiationRange,
+ PartialSpec, nullptr, TemplateArgs, &DeductionInfo);
}
Sema::InstantiatingTemplate::InstantiatingTemplate(
@@ -320,22 +288,11 @@
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);
- }
+ : SemaRef(SemaRef)
+{
+ Initialize(ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
+ PointOfInstantiation, InstantiationRange,
+ PartialSpec, nullptr, TemplateArgs, &DeductionInfo);
}
Sema::InstantiatingTemplate::
@@ -343,47 +300,24 @@
ParmVarDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind
- = ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = Param;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- }
+ Initialize(ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation,
+ PointOfInstantiation, InstantiationRange,
+ Param, nullptr, TemplateArgs);
}
+
Sema::InstantiatingTemplate::
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
NamedDecl *Template, NonTypeTemplateParmDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Template = Template;
- Inst.Entity = Param;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- }
+ Initialize(ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution,
+ PointOfInstantiation, InstantiationRange,
+ Param, Template, TemplateArgs);
}
Sema::InstantiatingTemplate::
@@ -391,23 +325,11 @@
NamedDecl *Template, TemplateTemplateParmDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Template = Template;
- Inst.Entity = Param;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- }
+ Initialize(ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution,
+ PointOfInstantiation, InstantiationRange,
+ Param, Template, TemplateArgs);
}
Sema::InstantiatingTemplate::
@@ -415,25 +337,11 @@
TemplateDecl *Template, NamedDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
- : SemaRef(SemaRef),
- SavedInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext)
+ : SemaRef(SemaRef)
{
- Invalid = false;
-
- ActiveTemplateInstantiation Inst;
- Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentChecking;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Template = Template;
- Inst.Entity = Param;
- Inst.TemplateArgs = TemplateArgs.data();
- Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.InNonInstantiationSFINAEContext = false;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
-
- assert(!Inst.isInstantiationRecord());
- ++SemaRef.NonInstantiationEntries;
+ Initialize(ActiveTemplateInstantiation::DefaultTemplateArgumentChecking,
+ PointOfInstantiation, InstantiationRange,
+ Param, Template, TemplateArgs);
}
void Sema::InstantiatingTemplate::Clear() {
@@ -789,7 +697,7 @@
MultiLevelTemplateArgumentList &TemplateArgs
= const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
unsigned Depth, Index;
- llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+ std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
if (TemplateArgs.hasTemplateArgument(Depth, Index)) {
Result = TemplateArgs(Depth, Index);
TemplateArgs.setArgument(Depth, Index, TemplateArgument());
@@ -808,7 +716,7 @@
MultiLevelTemplateArgumentList &TemplateArgs
= const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
unsigned Depth, Index;
- llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+ std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
TemplateArgs.setArgument(Depth, Index, Arg);
}
}
@@ -929,8 +837,6 @@
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.
@@ -940,7 +846,7 @@
return inherited::TransformLambdaScope(E, NewCallOperator,
InitCaptureExprsAndTypes);
}
- TemplateParameterList *TransformTemplateParameterList(
+ TemplateParameterList *TransformTemplateParameterList(
TemplateParameterList *OrigTPL) {
if (!OrigTPL || !OrigTPL->size()) return OrigTPL;
@@ -1628,8 +1534,8 @@
return false;
FunctionProtoTypeLoc FP = TL.castAs<FunctionProtoTypeLoc>();
- for (unsigned I = 0, E = FP.getNumArgs(); I != E; ++I) {
- ParmVarDecl *P = FP.getArg(I);
+ for (unsigned I = 0, E = FP.getNumParams(); I != E; ++I) {
+ ParmVarDecl *P = FP.getParam(I);
// This must be synthesized from a typedef.
if (!P) continue;
@@ -1808,31 +1714,29 @@
const MultiLevelTemplateArgumentList &TemplateArgs) {
bool Invalid = false;
SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
- for (ClassTemplateSpecializationDecl::base_class_iterator
- Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end();
- Base != BaseEnd; ++Base) {
- if (!Base->getType()->isDependentType()) {
- if (const CXXRecordDecl *RD = Base->getType()->getAsCXXRecordDecl()) {
+ for (const auto Base : Pattern->bases()) {
+ if (!Base.getType()->isDependentType()) {
+ if (const CXXRecordDecl *RD = Base.getType()->getAsCXXRecordDecl()) {
if (RD->isInvalidDecl())
Instantiation->setInvalidDecl();
}
- InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base));
+ InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(Base));
continue;
}
SourceLocation EllipsisLoc;
TypeSourceInfo *BaseTypeLoc;
- if (Base->isPackExpansion()) {
+ if (Base.isPackExpansion()) {
// This is a pack expansion. See whether we should expand it now, or
// wait until later.
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- collectUnexpandedParameterPacks(Base->getTypeSourceInfo()->getTypeLoc(),
+ collectUnexpandedParameterPacks(Base.getTypeSourceInfo()->getTypeLoc(),
Unexpanded);
bool ShouldExpand = false;
bool RetainExpansion = false;
Optional<unsigned> NumExpansions;
- if (CheckParameterPacksForExpansion(Base->getEllipsisLoc(),
- Base->getSourceRange(),
+ if (CheckParameterPacksForExpansion(Base.getEllipsisLoc(),
+ Base.getSourceRange(),
Unexpanded,
TemplateArgs, ShouldExpand,
RetainExpansion,
@@ -1846,9 +1750,9 @@
for (unsigned I = 0; I != *NumExpansions; ++I) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
- TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+ TypeSourceInfo *BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
TemplateArgs,
- Base->getSourceRange().getBegin(),
+ Base.getSourceRange().getBegin(),
DeclarationName());
if (!BaseTypeLoc) {
Invalid = true;
@@ -1857,9 +1761,9 @@
if (CXXBaseSpecifier *InstantiatedBase
= CheckBaseSpecifier(Instantiation,
- Base->getSourceRange(),
- Base->isVirtual(),
- Base->getAccessSpecifierAsWritten(),
+ Base.getSourceRange(),
+ Base.isVirtual(),
+ Base.getAccessSpecifierAsWritten(),
BaseTypeLoc,
SourceLocation()))
InstantiatedBases.push_back(InstantiatedBase);
@@ -1871,16 +1775,16 @@
}
// The resulting base specifier will (still) be a pack expansion.
- EllipsisLoc = Base->getEllipsisLoc();
+ EllipsisLoc = Base.getEllipsisLoc();
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
- BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+ BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
TemplateArgs,
- Base->getSourceRange().getBegin(),
+ Base.getSourceRange().getBegin(),
DeclarationName());
} else {
- BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+ BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
TemplateArgs,
- Base->getSourceRange().getBegin(),
+ Base.getSourceRange().getBegin(),
DeclarationName());
}
@@ -1891,9 +1795,9 @@
if (CXXBaseSpecifier *InstantiatedBase
= CheckBaseSpecifier(Instantiation,
- Base->getSourceRange(),
- Base->isVirtual(),
- Base->getAccessSpecifierAsWritten(),
+ Base.getSourceRange(),
+ Base.isVirtual(),
+ Base.getAccessSpecifierAsWritten(),
BaseTypeLoc,
EllipsisLoc))
InstantiatedBases.push_back(InstantiatedBase);
@@ -2008,7 +1912,7 @@
Spec->setTemplateSpecializationKind(TSK);
Spec->setPointOfInstantiation(PointOfInstantiation);
}
-
+
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
@@ -2030,7 +1934,12 @@
// Start the definition of this instantiation.
Instantiation->startDefinition();
-
+
+ // The instantiation is visible here, even if it was first declared in an
+ // unimported module.
+ Instantiation->setHidden(false);
+
+ // FIXME: This loses the as-written tag kind for an explicit instantiation.
Instantiation->setTagKind(Pattern->getTagKind());
// Do substitution on the base class specifiers.
@@ -2045,9 +1954,7 @@
LateInstantiatedAttrVec LateAttrs;
Instantiator.enableLateAttributeInstantiation(&LateAttrs);
- for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
- MemberEnd = Pattern->decls_end();
- Member != MemberEnd; ++Member) {
+ for (auto *Member : Pattern->decls()) {
// Don't instantiate members not belonging in this semantic context.
// e.g. for:
// @code
@@ -2057,19 +1964,19 @@
// @endcode
// 'class B' has the template as lexical context but semantically it is
// introduced in namespace scope.
- if ((*Member)->getDeclContext() != Pattern)
+ if (Member->getDeclContext() != Pattern)
continue;
- if ((*Member)->isInvalidDecl()) {
+ if (Member->isInvalidDecl()) {
Instantiation->setInvalidDecl();
continue;
}
- Decl *NewMember = Instantiator.Visit(*Member);
+ Decl *NewMember = Instantiator.Visit(Member);
if (NewMember) {
if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) {
Fields.push_back(Field);
- FieldDecl *OldField = cast<FieldDecl>(*Member);
+ FieldDecl *OldField = cast<FieldDecl>(Member);
if (OldField->getInClassInitializer())
FieldsWithMemberInitializers.push_back(std::make_pair(OldField,
Field));
@@ -2124,16 +2031,14 @@
FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
Expr *OldInit = OldField->getInClassInitializer();
+ ActOnStartCXXInClassMemberInitializer();
ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
/*CXXDirectInit=*/false);
- if (NewInit.isInvalid())
- NewField->setInvalidDecl();
- else {
- Expr *Init = NewInit.take();
- assert(Init && "no-argument initializer in class");
- assert(!isa<ParenListExpr>(Init) && "call-style init in class");
- ActOnCXXInClassMemberInitializer(NewField, Init->getLocStart(), Init);
- }
+ Expr *Init = NewInit.take();
+ assert((!Init || !isa<ParenListExpr>(Init)) &&
+ "call-style init in class");
+ ActOnFinishCXXInClassMemberInitializer(NewField, Init->getLocStart(),
+ Init);
}
}
// Instantiate late parsed attributes, and attach them to their decls.
@@ -2161,6 +2066,8 @@
ActOnFinishDelayedMemberInitializers(Instantiation);
+ // FIXME: We should do something similar for explicit instantiations so they
+ // end up in the right module.
if (TSK == TSK_ImplicitInstantiation) {
Instantiation->setLocation(Pattern->getLocation());
Instantiation->setLocStart(Pattern->getInnerLocStart());
@@ -2250,6 +2157,10 @@
if (Inst.isInvalid())
return true;
+ // The instantiation is visible here, even if it was first declared in an
+ // unimported module.
+ Instantiation->setHidden(false);
+
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
ContextRAII SavedContext(*this, Instantiation);
@@ -2354,8 +2265,7 @@
// 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) {
SmallVectorImpl<MatchResult>::iterator Best = Matched.begin();
if (Matched.size() == 1) {
@@ -2464,11 +2374,9 @@
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) {
+ for (auto *D : Instantiation->decls()) {
bool SuppressNew = false;
- if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
+ if (auto *Function = dyn_cast<FunctionDecl>(D)) {
if (FunctionDecl *Pattern
= Function->getInstantiatedFromMemberFunction()) {
MemberSpecializationInfo *MSInfo
@@ -2509,7 +2417,7 @@
std::make_pair(Function, PointOfInstantiation));
}
}
- } else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
+ } else if (auto *Var = dyn_cast<VarDecl>(D)) {
if (isa<VarTemplateSpecializationDecl>(Var))
continue;
@@ -2545,7 +2453,7 @@
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
}
}
- } else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) {
+ } else if (auto *Record = dyn_cast<CXXRecordDecl>(D)) {
// Always skip the injected-class-name, along with any
// redeclarations of nested classes, since both would cause us
// to try to instantiate the members of a class twice.
@@ -2602,7 +2510,7 @@
if (Pattern)
InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs,
TSK);
- } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(*D)) {
+ } else if (auto *Enum = dyn_cast<EnumDecl>(D)) {
MemberSpecializationInfo *MSInfo = Enum->getMemberSpecializationInfo();
assert(MSInfo && "No member specialization information?");
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 5c28e3b..316b574 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.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/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/DependentDiagnostic.h"
@@ -129,14 +130,46 @@
}
}
+static void instantiateDependentEnableIfAttr(
+ Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
+ const EnableIfAttr *A, const Decl *Tmpl, Decl *New) {
+ Expr *Cond = 0;
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
+ ExprResult Result = S.SubstExpr(A->getCond(), TemplateArgs);
+ if (Result.isInvalid())
+ return;
+ Cond = Result.takeAs<Expr>();
+ }
+ if (A->getCond()->isTypeDependent() && !Cond->isTypeDependent()) {
+ ExprResult Converted = S.PerformContextuallyConvertToBool(Cond);
+ if (Converted.isInvalid())
+ return;
+ Cond = Converted.take();
+ }
+
+ SmallVector<PartialDiagnosticAt, 8> Diags;
+ if (A->getCond()->isValueDependent() && !Cond->isValueDependent() &&
+ !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(Tmpl),
+ Diags)) {
+ S.Diag(A->getLocation(), diag::err_enable_if_never_constant_expr);
+ for (int I = 0, N = Diags.size(); I != N; ++I)
+ S.Diag(Diags[I].first, Diags[I].second);
+ return;
+ }
+
+ EnableIfAttr *EIA = new (S.getASTContext())
+ EnableIfAttr(A->getLocation(), S.getASTContext(), Cond,
+ A->getMessage(),
+ A->getSpellingListIndex());
+ New->addAttr(EIA);
+}
+
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
const Decl *Tmpl, Decl *New,
LateInstantiatedAttrVec *LateAttrs,
LocalInstantiationScope *OuterMostScope) {
- for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end();
- i != e; ++i) {
- const Attr *TmplAttr = *i;
-
+ for (const auto *TmplAttr : Tmpl->attrs()) {
// FIXME: This should be generalized to more than just the AlignedAttr.
const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr);
if (Aligned && Aligned->isAlignmentDependent()) {
@@ -144,6 +177,13 @@
continue;
}
+ const EnableIfAttr *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr);
+ if (EnableIf && EnableIf->getCond()->isValueDependent()) {
+ instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl,
+ New);
+ continue;
+ }
+
assert(!TmplAttr->isPackExpansion());
if (TmplAttr->isLateParsed() && LateAttrs) {
// Late parsed attributes must be instantiated and attached after the
@@ -476,7 +516,7 @@
if (DI->getType()->isVariablyModifiedType()) {
SemaRef.Diag(D->getLocation(), diag::err_property_is_variably_modified)
- << D->getName();
+ << D;
Invalid = true;
} else if (DI->getType()->isInstantiationDependentType()) {
DI = SemaRef.SubstType(DI, TemplateArgs,
@@ -499,11 +539,9 @@
SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType());
}
- MSPropertyDecl *Property = new (SemaRef.Context)
- MSPropertyDecl(Owner, D->getLocation(),
- D->getDeclName(), DI->getType(), DI,
- D->getLocStart(),
- D->getGetterId(), D->getSetterId());
+ MSPropertyDecl *Property = MSPropertyDecl::Create(
+ SemaRef.Context, Owner, D->getLocation(), D->getDeclName(), DI->getType(),
+ DI, D->getLocStart(), D->getGetterId(), D->getSetterId());
SemaRef.InstantiateAttrs(TemplateArgs, D, Property, LateAttrs,
StartingScope);
@@ -522,10 +560,8 @@
new (SemaRef.Context)NamedDecl*[D->getChainingSize()];
int i = 0;
- for (IndirectFieldDecl::chain_iterator PI =
- D->chain_begin(), PE = D->chain_end();
- PI != PE; ++PI) {
- NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), *PI,
+ for (auto *PI : D->chain()) {
+ NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), PI,
TemplateArgs);
if (!Next)
return 0;
@@ -650,6 +686,8 @@
Enum->setInstantiationOfMemberEnum(D, TSK_ImplicitInstantiation);
Enum->setAccess(D->getAccess());
+ // Forward the mangling number from the template to the instantiated decl.
+ SemaRef.Context.setManglingNumber(Enum, SemaRef.Context.getManglingNumber(D));
if (SubstQualifier(D, Enum)) return 0;
Owner->addDecl(Enum);
@@ -693,9 +731,7 @@
SmallVector<Decl*, 4> Enumerators;
EnumConstantDecl *LastEnumConst = 0;
- for (EnumDecl::enumerator_iterator EC = Pattern->enumerator_begin(),
- ECEnd = Pattern->enumerator_end();
- EC != ECEnd; ++EC) {
+ for (auto *EC : Pattern->enumerators()) {
// The specified value for the enumerator.
ExprResult Value = SemaRef.Owned((Expr *)0);
if (Expr *UninstValue = EC->getInitExpr()) {
@@ -725,7 +761,7 @@
}
if (EnumConst) {
- SemaRef.InstantiateAttrs(TemplateArgs, *EC, EnumConst);
+ SemaRef.InstantiateAttrs(TemplateArgs, EC, EnumConst);
EnumConst->setAccess(Enum->getAccess());
Enum->addDecl(EnumConst);
@@ -736,7 +772,7 @@
!Enum->isScoped()) {
// If the enumeration is within a function or method, record the enum
// constant as a local.
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(*EC, EnumConst);
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(EC, EnumConst);
}
}
}
@@ -991,8 +1027,9 @@
VarTemplateDecl *Inst = VarTemplateDecl::Create(
SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams,
- VarInst, PrevVarTemplate);
+ VarInst);
VarInst->setDescribedVarTemplate(Inst);
+ Inst->setPreviousDecl(PrevVarTemplate);
Inst->setAccess(D->getAccess());
if (!PrevVarTemplate)
@@ -1135,19 +1172,20 @@
if (D->isLocalClass())
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record);
+ // Forward the mangling number from the template to the instantiated decl.
+ SemaRef.Context.setManglingNumber(Record,
+ SemaRef.Context.getManglingNumber(D));
+
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);
- }
+ SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs,
+ TSK_ImplicitInstantiation,
+ /*Complain=*/true);
+ SemaRef.InstantiateClassMembers(D->getLocation(), Record, TemplateArgs,
+ TSK_ImplicitInstantiation);
}
return Record;
}
@@ -1170,15 +1208,14 @@
FunctionProtoType::ExtProtoInfo NewEPI = NewFunc->getExtProtoInfo();
NewEPI.ExtInfo = OrigFunc->getExtInfo();
- return Context.getFunctionType(NewFunc->getResultType(),
- NewFunc->getArgTypes(), NewEPI);
+ return Context.getFunctionType(NewFunc->getReturnType(),
+ NewFunc->getParamTypes(), NewEPI);
}
/// Normal class members are of more specific types and therefore
/// don't make it here. This function serves two purposes:
/// 1) instantiating function templates
/// 2) substituting friend declarations
-/// FIXME: preserve function definitions in case #2
Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
TemplateParameterList *TemplateParams) {
// Check whether there is already a function template specialization for
@@ -1388,73 +1425,56 @@
PrincipalDecl->setObjectOfFriendDecl();
DC->makeDeclVisibleInContext(PrincipalDecl);
- bool queuedInstantiation = false;
+ bool QueuedInstantiation = false;
- // C++98 [temp.friend]p5: When a function is defined in a friend function
- // declaration in a class template, the function is defined at each
- // instantiation of the class template. The function is defined even if it
- // is never used.
- // C++11 [temp.friend]p4: When a function is defined in a friend function
- // declaration in a class template, the function is instantiated when the
- // function is odr-used.
- //
- // If -Wc++98-compat is enabled, we go through the motions of checking for a
- // redefinition, but don't instantiate the function.
- if ((!SemaRef.getLangOpts().CPlusPlus11 ||
- SemaRef.Diags.getDiagnosticLevel(
- diag::warn_cxx98_compat_friend_redefinition,
- Function->getLocation())
- != DiagnosticsEngine::Ignored) &&
- D->isThisDeclarationADefinition()) {
+ // C++11 [temp.friend]p4 (DR329):
+ // When a function is defined in a friend function declaration in a class
+ // template, the function is instantiated when the function is odr-used.
+ // The same restrictions on multiple declarations and definitions that
+ // apply to non-template function declarations and definitions also apply
+ // to these implicit definitions.
+ if (D->isThisDeclarationADefinition()) {
// Check for a function body.
const FunctionDecl *Definition = 0;
if (Function->isDefined(Definition) &&
Definition->getTemplateSpecializationKind() == TSK_Undeclared) {
- SemaRef.Diag(Function->getLocation(),
- SemaRef.getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_friend_redefinition :
- diag::err_redefinition) << Function->getDeclName();
+ SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
+ << Function->getDeclName();
SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition);
- if (!SemaRef.getLangOpts().CPlusPlus11)
- Function->setInvalidDecl();
}
// Check for redefinitions due to other instantiations of this or
// a similar friend function.
- else for (FunctionDecl::redecl_iterator R = Function->redecls_begin(),
- REnd = Function->redecls_end();
- R != REnd; ++R) {
- if (*R == Function)
+ else for (auto R : Function->redecls()) {
+ if (R == Function)
continue;
- switch (R->getFriendObjectKind()) {
- case Decl::FOK_None:
- if (!SemaRef.getLangOpts().CPlusPlus11 &&
- !queuedInstantiation && R->isUsed(false)) {
- if (MemberSpecializationInfo *MSInfo
- = Function->getMemberSpecializationInfo()) {
- if (MSInfo->getPointOfInstantiation().isInvalid()) {
- SourceLocation Loc = R->getLocation(); // FIXME
- MSInfo->setPointOfInstantiation(Loc);
- SemaRef.PendingLocalImplicitInstantiations.push_back(
- std::make_pair(Function, Loc));
- queuedInstantiation = true;
- }
+
+ // If some prior declaration of this function has been used, we need
+ // to instantiate its definition.
+ if (!QueuedInstantiation && R->isUsed(false)) {
+ if (MemberSpecializationInfo *MSInfo =
+ Function->getMemberSpecializationInfo()) {
+ if (MSInfo->getPointOfInstantiation().isInvalid()) {
+ SourceLocation Loc = R->getLocation(); // FIXME
+ MSInfo->setPointOfInstantiation(Loc);
+ SemaRef.PendingLocalImplicitInstantiations.push_back(
+ std::make_pair(Function, Loc));
+ QueuedInstantiation = true;
}
}
- break;
- default:
- if (const FunctionDecl *RPattern
- = R->getTemplateInstantiationPattern())
+ }
+
+ // If some prior declaration of this function was a friend with an
+ // uninstantiated definition, reject it.
+ if (R->getFriendObjectKind()) {
+ if (const FunctionDecl *RPattern =
+ R->getTemplateInstantiationPattern()) {
if (RPattern->isDefined(RPattern)) {
- SemaRef.Diag(Function->getLocation(),
- SemaRef.getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_friend_redefinition :
- diag::err_redefinition)
+ SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
<< Function->getDeclName();
SemaRef.Diag(R->getLocation(), diag::note_previous_definition);
- if (!SemaRef.getLangOpts().CPlusPlus11)
- Function->setInvalidDecl();
break;
}
+ }
}
}
}
@@ -2149,7 +2169,7 @@
}
if (!NewUD->isInvalidDecl() &&
- SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), SS,
+ SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), SS, NameInfo,
D->getLocation()))
NewUD->setInvalidDecl();
@@ -2170,9 +2190,7 @@
bool isFunctionScope = Owner->isFunctionOrMethod();
// Process the shadow decls.
- for (UsingDecl::shadow_iterator I = D->shadow_begin(), E = D->shadow_end();
- I != E; ++I) {
- UsingShadowDecl *Shadow = *I;
+ for (auto *Shadow : D->shadows()) {
NamedDecl *InstTarget =
cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl(
Shadow->getLocation(), Shadow->getTargetDecl(), TemplateArgs));
@@ -2288,10 +2306,8 @@
Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
OMPThreadPrivateDecl *D) {
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();
+ for (auto *I : D->varlists()) {
+ Expr *Var = SemaRef.SubstExpr(I, TemplateArgs).take();
assert(isa<DeclRefExpr>(Var) && "threadprivate arg is not a DeclRefExpr");
Vars.push_back(Var);
}
@@ -2299,6 +2315,9 @@
OMPThreadPrivateDecl *TD =
SemaRef.CheckOMPThreadPrivateDecl(D->getLocation(), Vars);
+ TD->setAccess(AS_public);
+ Owner->addDecl(TD);
+
return TD;
}
@@ -2476,11 +2495,10 @@
// 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))
+ Converted))
return 0;
// Find the variable template specialization declaration that
@@ -2887,9 +2905,9 @@
TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens();
FunctionProtoTypeLoc NewProtoLoc = NewTL.castAs<FunctionProtoTypeLoc>();
unsigned NewIdx = 0;
- for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc.getNumArgs();
+ for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc.getNumParams();
OldIdx != NumOldParams; ++OldIdx) {
- ParmVarDecl *OldParam = OldProtoLoc.getArg(OldIdx);
+ ParmVarDecl *OldParam = OldProtoLoc.getParam(OldIdx);
LocalInstantiationScope *Scope = SemaRef.CurrentInstantiationScope;
Optional<unsigned> NumArgumentsInExpansion;
@@ -2900,14 +2918,14 @@
if (!NumArgumentsInExpansion) {
// Simple case: normal parameter, or a parameter pack that's
// instantiated to a (still-dependent) parameter pack.
- ParmVarDecl *NewParam = NewProtoLoc.getArg(NewIdx++);
+ ParmVarDecl *NewParam = NewProtoLoc.getParam(NewIdx++);
Params.push_back(NewParam);
Scope->InstantiatedLocal(OldParam, NewParam);
} else {
// Parameter pack expansion: make the instantiation an argument pack.
Scope->MakeInstantiatedLocalArgPack(OldParam);
for (unsigned I = 0; I != *NumArgumentsInExpansion; ++I) {
- ParmVarDecl *NewParam = NewProtoLoc.getArg(NewIdx++);
+ ParmVarDecl *NewParam = NewProtoLoc.getParam(NewIdx++);
Params.push_back(NewParam);
Scope->InstantiatedLocalPackArg(OldParam, NewParam);
}
@@ -2919,11 +2937,12 @@
// the function parameters themselves.
const FunctionProtoType *OldProto =
cast<FunctionProtoType>(OldProtoLoc.getType());
- for (unsigned i = 0, i_end = OldProtoLoc.getNumArgs(); i != i_end; ++i) {
- ParmVarDecl *OldParam = OldProtoLoc.getArg(i);
+ for (unsigned i = 0, i_end = OldProtoLoc.getNumParams(); i != i_end;
+ ++i) {
+ ParmVarDecl *OldParam = OldProtoLoc.getParam(i);
if (!OldParam) {
Params.push_back(SemaRef.BuildParmVarDeclForTypedef(
- D, D->getLocation(), OldProto->getArgType(i)));
+ D, D->getLocation(), OldProto->getParamType(i)));
continue;
}
@@ -2969,6 +2988,14 @@
// Simple case: not a parameter pack.
assert(FParamIdx < Function->getNumParams());
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+ // If the parameter's type is not dependent, update it to match the type
+ // in the pattern. They can differ in top-level cv-qualifiers, and we want
+ // the pattern's type here. If the type is dependent, they can't differ,
+ // per core issue 1668.
+ // FIXME: Updating the type to work around this is at best fragile.
+ if (!PatternDecl->getType()->isDependentType())
+ FunctionParam->setType(PatternParam->getType());
+
FunctionParam->setDeclName(PatternParam->getDeclName());
Scope.InstantiatedLocal(PatternParam, FunctionParam);
++FParamIdx;
@@ -2983,6 +3010,9 @@
"should only be called when all template arguments are known");
for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) {
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+ if (!PatternDecl->getType()->isDependentType())
+ FunctionParam->setType(PatternParam->getType());
+
FunctionParam->setDeclName(PatternParam->getDeclName());
Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
++FParamIdx;
@@ -3102,19 +3132,13 @@
}
}
- // Rebuild the function type
- const FunctionProtoType *NewProto
- = New->getType()->getAs<FunctionProtoType>();
- assert(NewProto && "Template instantiation without function prototype?");
-
- FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
+ FunctionProtoType::ExtProtoInfo EPI;
EPI.ExceptionSpecType = Proto->getExceptionSpecType();
EPI.NumExceptions = Exceptions.size();
EPI.Exceptions = Exceptions.data();
EPI.NoexceptExpr = NoexceptExpr;
- New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
- NewProto->getArgTypes(), EPI));
+ SemaRef.UpdateExceptionSpec(New, EPI);
}
void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
@@ -3128,10 +3152,9 @@
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();
+ FunctionProtoType::ExtProtoInfo EPI;
EPI.ExceptionSpecType = EST_None;
- Decl->setType(Context.getFunctionType(Proto->getResultType(),
- Proto->getArgTypes(), EPI));
+ UpdateExceptionSpec(Decl, EPI);
return;
}
@@ -3161,6 +3184,10 @@
if (Tmpl->isDeleted())
New->setDeletedAsWritten();
+ // Forward the mangling number from the template to the instantiated decl.
+ SemaRef.Context.setManglingNumber(New,
+ SemaRef.Context.getManglingNumber(Tmpl));
+
// If we are performing substituting explicitly-specified template arguments
// or deduced template arguments into a function template and we reach this
// point, we are now past the point where SFINAE applies and have committed
@@ -3211,7 +3238,7 @@
EPI.ExceptionSpecDecl = New;
EPI.ExceptionSpecTemplate = ExceptionSpecTemplate;
New->setType(SemaRef.Context.getFunctionType(
- NewProto->getResultType(), NewProto->getArgTypes(), EPI));
+ NewProto->getReturnType(), NewProto->getParamTypes(), EPI));
} else {
::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs);
}
@@ -3339,10 +3366,10 @@
// initializer or return value, and class template specializations, other
// explicit instantiation declarations have the effect of suppressing the
// implicit instantiation of the entity to which they refer.
- if (Function->getTemplateSpecializationKind()
- == TSK_ExplicitInstantiationDeclaration &&
+ if (Function->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDeclaration &&
!PatternDecl->isInlined() &&
- !PatternDecl->getResultType()->getContainedAutoType())
+ !PatternDecl->getReturnType()->getContainedAutoType())
return;
if (PatternDecl->isInlined())
@@ -3413,6 +3440,9 @@
PerformDependentDiagnostics(PatternDecl, TemplateArgs);
+ if (auto *Listener = getASTMutationListener())
+ Listener->FunctionDefinitionInstantiated(Function);
+
savedContext.pop();
}
@@ -3467,7 +3497,18 @@
// 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();
+ //
+ // If we're instantiating an explicitly-specialized member template or member
+ // partial specialization, don't do this. The member specialization completely
+ // replaces the original declaration in this case.
+ bool IsMemberSpec = false;
+ if (VarTemplatePartialSpecializationDecl *PartialSpec =
+ dyn_cast<VarTemplatePartialSpecializationDecl>(FromVar))
+ IsMemberSpec = PartialSpec->isMemberSpecialization();
+ else if (VarTemplateDecl *FromTemplate = FromVar->getDescribedVarTemplate())
+ IsMemberSpec = FromTemplate->isMemberSpecialization();
+ if (!IsMemberSpec)
+ FromVar = FromVar->getFirstDecl();
MultiLevelTemplateArgumentList MultiLevelList(TemplateArgList);
TemplateDeclInstantiator Instantiator(*this, FromVar->getDeclContext(),
@@ -3552,16 +3593,15 @@
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()) {
+ if (NewVar->isLocalExternDecl() && OldVar->getPreviousDecl() &&
+ (!OldVar->getPreviousDecl()->getDeclContext()->isDependentContext() ||
+ OldVar->getPreviousDecl()->getDeclContext()==OldVar->getDeclContext())) {
// We have a previous declaration. Use that one, so we merge with the
// right type.
if (NamedDecl *NewPrev = FindInstantiatedDecl(
@@ -3589,9 +3629,16 @@
NewVar->setInstantiationOfStaticDataMember(OldVar,
TSK_ImplicitInstantiation);
+ // Forward the mangling number from the template to the instantiated decl.
+ Context.setManglingNumber(NewVar, Context.getManglingNumber(OldVar));
+ Context.setStaticLocalNumber(NewVar, Context.getStaticLocalNumber(OldVar));
+
// Delay instantiation of the initializer for variable templates until a
- // definition of the variable is needed.
- if (!isa<VarTemplateSpecializationDecl>(NewVar) && !InstantiatingVarTemplate)
+ // definition of the variable is needed. We need it right away if the type
+ // contains 'auto'.
+ if ((!isa<VarTemplateSpecializationDecl>(NewVar) &&
+ !InstantiatingVarTemplate) ||
+ NewVar->getType()->isUndeducedType())
InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs);
// Diagnose unused local variables with dependent types, where the diagnostic
@@ -3951,11 +3998,7 @@
bool AnyErrors = Tmpl->isInvalidDecl();
// Instantiate all the initializers.
- for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(),
- InitsEnd = Tmpl->init_end();
- Inits != InitsEnd; ++Inits) {
- CXXCtorInitializer *Init = *Inits;
-
+ for (const auto *Init : Tmpl->inits()) {
// Only instantiate written initializers, let Sema re-construct implicit
// ones.
if (!Init->isWritten())
@@ -4339,7 +4382,7 @@
// 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; }
+ // 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??
@@ -4550,14 +4593,6 @@
/// \brief Performs template instantiation for all implicit template
/// instantiations we have seen until this point.
void Sema::PerformPendingInstantiations(bool LocalOnly) {
- // Load pending instantiations from the external source.
- if (!LocalOnly && ExternalSource) {
- SmallVector<PendingImplicitInstantiation, 4> Pending;
- ExternalSource->ReadPendingInstantiations(Pending);
- PendingInstantiations.insert(PendingInstantiations.begin(),
- Pending.begin(), Pending.end());
- }
-
while (!PendingLocalImplicitInstantiations.empty() ||
(!LocalOnly && !PendingInstantiations.empty())) {
PendingImplicitInstantiation Inst;
@@ -4624,10 +4659,7 @@
void Sema::PerformDependentDiagnostics(const DeclContext *Pattern,
const MultiLevelTemplateArgumentList &TemplateArgs) {
- for (DeclContext::ddiag_iterator I = Pattern->ddiag_begin(),
- E = Pattern->ddiag_end(); I != E; ++I) {
- DependentDiagnostic *DD = *I;
-
+ for (auto DD : Pattern->ddiags()) {
switch (DD->getKind()) {
case DependentDiagnostic::Access:
HandleDependentAccessCheck(*DD, TemplateArgs);
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 78aa7f8..de850e3 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -10,6 +10,7 @@
//===----------------------------------------------------------------------===/
#include "clang/Sema/Sema.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeLoc.h"
@@ -18,7 +19,6 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
-#include "TypeLocBuilder.h"
using namespace clang;
@@ -554,8 +554,8 @@
if (isa<ParmVarDecl>(ND))
IsFunctionParameterPack = true;
else
- llvm::tie(Depth, Index) = getDepthAndIndex(ND);
-
+ std::tie(Depth, Index) = getDepthAndIndex(ND);
+
Name = ND->getIdentifier();
}
@@ -599,7 +599,7 @@
if (NamedDecl *PartialPack
= CurrentInstantiationScope->getPartiallySubstitutedPack()){
unsigned PartialDepth, PartialIndex;
- llvm::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
+ std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
if (PartialDepth == Depth && PartialIndex == Index)
RetainExpansion = true;
}
@@ -669,8 +669,8 @@
Result = Size;
continue;
}
-
- llvm::tie(Depth, Index) = getDepthAndIndex(ND);
+
+ std::tie(Depth, Index) = getDepthAndIndex(ND);
}
if (Depth >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(Depth, Index))
@@ -730,14 +730,6 @@
case TST_auto:
case TST_decltype_auto:
case TST_unknown_anytype:
- case TST_image1d_t:
- case TST_image1d_array_t:
- case TST_image1d_buffer_t:
- case TST_image2d_t:
- case TST_image2d_array_t:
- case TST_image3d_t:
- case TST_sampler_t:
- case TST_event_t:
case TST_error:
break;
}
@@ -775,7 +767,7 @@
// Callback to only accept typo corrections that refer to parameter packs.
class ParameterPackValidatorCCC : public CorrectionCandidateCallback {
public:
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
NamedDecl *ND = candidate.getCorrectionDecl();
return ND && ND->isParameterPack();
}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index aa7459d..e273cb6 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
@@ -21,7 +22,6 @@
#include "clang/AST/Expr.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeLocVisitor.h"
-#include "clang/Basic/OpenCL.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
@@ -34,7 +34,6 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
-#include "TypeLocBuilder.h"
using namespace clang;
@@ -728,13 +727,15 @@
Result = Context.WCharTy;
else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
- << DS.getSpecifierName(DS.getTypeSpecType());
+ << DS.getSpecifierName(DS.getTypeSpecType(),
+ Context.getPrintingPolicy());
Result = Context.getSignedWCharType();
} else {
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
"Unknown TSS value");
S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
- << DS.getSpecifierName(DS.getTypeSpecType());
+ << DS.getSpecifierName(DS.getTypeSpecType(),
+ Context.getPrintingPolicy());
Result = Context.getUnsignedWCharType();
}
break;
@@ -1058,38 +1059,6 @@
}
break;
- case DeclSpec::TST_image1d_t:
- Result = Context.OCLImage1dTy;
- break;
-
- case DeclSpec::TST_image1d_array_t:
- Result = Context.OCLImage1dArrayTy;
- break;
-
- case DeclSpec::TST_image1d_buffer_t:
- Result = Context.OCLImage1dBufferTy;
- break;
-
- case DeclSpec::TST_image2d_t:
- Result = Context.OCLImage2dTy;
- break;
-
- case DeclSpec::TST_image2d_array_t:
- Result = Context.OCLImage2dArrayTy;
- break;
-
- case DeclSpec::TST_image3d_t:
- Result = Context.OCLImage3dTy;
- break;
-
- case DeclSpec::TST_sampler_t:
- Result = Context.OCLSamplerTy;
- break;
-
- case DeclSpec::TST_event_t:
- Result = Context.OCLEventTy;
- break;
-
case DeclSpec::TST_error:
Result = Context.IntTy;
declarator.setInvalidType(true);
@@ -1148,17 +1117,33 @@
}
}
- // C++ [dcl.ref]p1:
+ // C++11 [dcl.ref]p1:
// Cv-qualified references are ill-formed except when the
- // cv-qualifiers are introduced through the use of a typedef
- // (7.1.3) or of a template type argument (14.3), in which
- // case the cv-qualifiers are ignored.
- // FIXME: Shouldn't we be checking SCS_typedef here?
+ // cv-qualifiers are introduced through the use of a typedef-name
+ // or decltype-specifier, in which case the cv-qualifiers are ignored.
+ //
+ // There don't appear to be any other contexts in which a cv-qualified
+ // reference type could be formed, so the 'ill-formed' clause here appears
+ // to never happen.
if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
TypeQuals && Result->isReferenceType()) {
- TypeQuals &= ~DeclSpec::TQ_const;
- TypeQuals &= ~DeclSpec::TQ_volatile;
- TypeQuals &= ~DeclSpec::TQ_atomic;
+ // If this occurs outside a template instantiation, warn the user about
+ // it; they probably didn't mean to specify a redundant qualifier.
+ typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc;
+ QualLoc Quals[] = {
+ QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()),
+ QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()),
+ QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())
+ };
+ for (unsigned I = 0, N = llvm::array_lengthof(Quals); I != N; ++I) {
+ if (S.ActiveTemplateInstantiations.empty()) {
+ if (TypeQuals & Quals[I].first)
+ S.Diag(Quals[I].second, diag::warn_typecheck_reference_qualifiers)
+ << DeclSpec::getSpecifierName(Quals[I].first) << Result
+ << FixItHint::CreateRemoval(Quals[I].second);
+ }
+ TypeQuals &= ~Quals[I].first;
+ }
}
// C90 6.5.3 constraints: "The same type qualifier shall not appear more
@@ -1427,10 +1412,10 @@
public:
VLADiagnoser() : Sema::VerifyICEDiagnoser(true) {}
- virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) {
+ void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
}
- virtual void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR) {
+ void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR) override {
S.Diag(Loc, diag::ext_vla_folded_to_constant) << SR;
}
} Diagnoser;
@@ -1487,6 +1472,13 @@
diag::err_array_of_abstract_type))
return QualType();
+ // Mentioning a member pointer type for an array type causes us to lock in
+ // an inheritance model, even if it's inside an unused typedef.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
+ if (!MPTy->getClass()->isDependentType())
+ RequireCompleteType(Loc, T, 0);
+
} else {
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
// reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
@@ -1614,6 +1606,7 @@
// Prohibit the use of non-POD types in VLAs.
QualType BaseT = Context.getBaseElementType(T);
if (!T->isDependentType() &&
+ !RequireCompleteType(Loc, BaseT, 0) &&
!BaseT.isPODType(Context) &&
!BaseT->isObjCLifetimeType()) {
Diag(Loc, diag::err_vla_non_pod)
@@ -1769,13 +1762,13 @@
// with reference type, or "cv void."
if (T->isReferenceType()) {
Diag(Loc, diag::err_illegal_decl_mempointer_to_reference)
- << (Entity? Entity.getAsString() : "type name") << T;
+ << getPrintableNameForEntity(Entity) << T;
return QualType();
}
if (T->isVoidType()) {
Diag(Loc, diag::err_illegal_decl_mempointer_to_void)
- << (Entity? Entity.getAsString() : "type name");
+ << getPrintableNameForEntity(Entity);
return QualType();
}
@@ -1784,35 +1777,10 @@
return QualType();
}
- // C++ allows the class type in a member pointer to be an incomplete type.
- // In the Microsoft ABI, the size of the member pointer can vary
- // according to the class type, which means that we really need a
- // complete type if possible, which means we need to instantiate templates.
- //
- // If template instantiation fails or the type is just incomplete, we have to
- // add an extra slot to the member pointer. Yes, this does cause problems
- // when passing pointers between TUs that disagree about the size.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- CXXRecordDecl *RD = Class->getAsCXXRecordDecl();
- if (RD && !RD->hasAttr<MSInheritanceAttr>()) {
- // Lock in the inheritance model on the first use of a member pointer.
- // Otherwise we may disagree about the size at different points in the TU.
- // FIXME: MSVC picks a model on the first use that needs to know the size,
- // rather than on the first mention of the type, e.g. typedefs.
- if (RequireCompleteType(Loc, Class, 0) && !RD->isBeingDefined()) {
- // We know it doesn't have an attribute and it's incomplete, so use the
- // unspecified inheritance model. If we're in the record body, we can
- // figure out the inheritance model.
- for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(),
- E = RD->redecls_end(); I != E; ++I) {
- I->addAttr(::new (Context) UnspecifiedInheritanceAttr(
- RD->getSourceRange(), Context));
- }
- }
- }
- }
-
- // FIXME: Adjust member function pointer calling conventions.
+ // Adjust the default free function calling convention to the default method
+ // calling convention.
+ if (T->isFunctionType())
+ adjustMemberFunctionCC(T, /*IsStatic=*/false);
return Context.getMemberPointerType(T, Class.getTypePtr());
}
@@ -2375,11 +2343,11 @@
return;
// An initializer for a non-class type can have at most one argument.
- if (!RT->isRecordType() && FTI.NumArgs > 1)
+ if (!RT->isRecordType() && FTI.NumParams > 1)
return;
// An initializer for a reference must have exactly one argument.
- if (RT->isReferenceType() && FTI.NumArgs != 1)
+ if (RT->isReferenceType() && FTI.NumParams != 1)
return;
// Only warn if this declarator is declaring a function at block scope, and
@@ -2399,9 +2367,9 @@
SourceRange ParenRange(DeclType.Loc, DeclType.EndLoc);
S.Diag(DeclType.Loc,
- FTI.NumArgs ? diag::warn_parens_disambiguated_as_function_declaration
- : diag::warn_empty_parens_are_function_decl)
- << ParenRange;
+ FTI.NumParams ? diag::warn_parens_disambiguated_as_function_declaration
+ : diag::warn_empty_parens_are_function_decl)
+ << ParenRange;
// If the declaration looks like:
// T var1,
@@ -2422,11 +2390,11 @@
}
}
- if (FTI.NumArgs > 0) {
+ if (FTI.NumParams > 0) {
// For a declaration with parameters, eg. "T var(T());", suggest adding parens
// around the first parameter to turn the declaration into a variable
// declaration.
- SourceRange Range = FTI.ArgInfo[0].Param->getSourceRange();
+ SourceRange Range = FTI.Params[0].Param->getSourceRange();
SourceLocation B = Range.getBegin();
SourceLocation E = S.PP.getLocForEndOfToken(Range.getEnd());
// FIXME: Maybe we should suggest adding braces instead of parens
@@ -2625,7 +2593,6 @@
}
T = S.BuildReferenceType(T, DeclType.Ref.LValueRef, DeclType.Loc, Name);
- Qualifiers Quals;
if (DeclType.Ref.HasRestrict)
T = S.BuildQualifiedType(T, DeclType.Loc, Qualifiers::Restrict);
break;
@@ -2727,11 +2694,13 @@
if (!D.isInvalidType()) {
// trailing-return-type is only required if we're declaring a function,
// and not, for instance, a pointer to a function.
- if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
+ if (D.getDeclSpec().containsPlaceholderType() &&
!FTI.hasTrailingReturnType() && chunkIndex == 0 &&
!S.getLangOpts().CPlusPlus1y) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
- diag::err_auto_missing_trailing_return);
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto
+ ? diag::err_auto_missing_trailing_return
+ : diag::err_deduced_return_type);
T = Context.IntTy;
D.setInvalidType(true);
} else if (FTI.hasTrailingReturnType()) {
@@ -2882,14 +2851,14 @@
FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex));
- if (!FTI.NumArgs && !FTI.isVariadic && !LangOpts.CPlusPlus) {
+ if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus) {
// Simple void foo(), where the incoming T is the result type.
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
// for this attribute now.
- if (!FTI.NumArgs && FTI.isVariadic && !LangOpts.CPlusPlus) {
+ if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) {
bool Overloadable = false;
for (const AttributeList *Attrs = D.getAttributes();
Attrs; Attrs = Attrs->getNext()) {
@@ -2903,10 +2872,11 @@
S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg);
}
- if (FTI.NumArgs && FTI.ArgInfo[0].Param == 0) {
+ if (FTI.NumParams && FTI.Params[0].Param == 0) {
// C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function
// definition.
- S.Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
+ S.Diag(FTI.Params[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, EI);
@@ -2925,14 +2895,14 @@
// Otherwise, we have a function with an argument list that is
// potentially variadic.
SmallVector<QualType, 16> ArgTys;
- ArgTys.reserve(FTI.NumArgs);
+ ArgTys.reserve(FTI.NumParams);
- SmallVector<bool, 16> ConsumedArguments;
- ConsumedArguments.reserve(FTI.NumArgs);
- bool HasAnyConsumedArguments = false;
+ SmallVector<bool, 16> ConsumedParameters;
+ ConsumedParameters.reserve(FTI.NumParams);
+ bool HasAnyConsumedParameters = false;
- for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
- ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
+ for (unsigned i = 0, e = FTI.NumParams; i != e; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
QualType ArgTy = Param->getType();
assert(!ArgTy.isNull() && "Couldn't parse type?");
@@ -2943,14 +2913,13 @@
// If this is something like 'float(int, void)', reject it. 'void'
// is an incomplete type (C99 6.2.5p19) and function decls cannot
// have arguments of incomplete type.
- if (FTI.NumArgs != 1 || FTI.isVariadic) {
+ if (FTI.NumParams != 1 || FTI.isVariadic) {
S.Diag(DeclType.Loc, diag::err_void_only_param);
ArgTy = Context.IntTy;
Param->setType(ArgTy);
- } else if (FTI.ArgInfo[i].Ident) {
+ } else if (FTI.Params[i].Ident) {
// Reject, but continue to parse 'int(void abc)'.
- S.Diag(FTI.ArgInfo[i].IdentLoc,
- diag::err_param_with_void_type);
+ S.Diag(FTI.Params[i].IdentLoc, diag::err_param_with_void_type);
ArgTy = Context.IntTy;
Param->setType(ArgTy);
} else {
@@ -2990,15 +2959,15 @@
if (LangOpts.ObjCAutoRefCount) {
bool Consumed = Param->hasAttr<NSConsumedAttr>();
- ConsumedArguments.push_back(Consumed);
- HasAnyConsumedArguments |= Consumed;
+ ConsumedParameters.push_back(Consumed);
+ HasAnyConsumedParameters |= Consumed;
}
ArgTys.push_back(ArgTy);
}
- if (HasAnyConsumedArguments)
- EPI.ConsumedArguments = ConsumedArguments.data();
+ if (HasAnyConsumedParameters)
+ EPI.ConsumedParameters = ConsumedParameters.data();
SmallVector<QualType, 4> Exceptions;
SmallVector<ParsedType, 2> DynamicExceptions;
@@ -3040,8 +3009,7 @@
D.setInvalidType(true);
} else if (S.isDependentScopeSpecifier(SS) ||
dyn_cast_or_null<CXXRecordDecl>(S.computeDeclContext(SS))) {
- NestedNameSpecifier *NNS
- = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+ NestedNameSpecifier *NNS = SS.getScopeRep();
NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
@@ -3165,7 +3133,7 @@
EPI.TypeQuals = 0;
EPI.RefQualifier = RQ_None;
- T = Context.getFunctionType(FnTy->getResultType(), FnTy->getArgTypes(),
+ T = Context.getFunctionType(FnTy->getReturnType(), FnTy->getParamTypes(),
EPI);
// Rebuild any parens around the identifier in the function type.
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
@@ -3476,10 +3444,17 @@
}
TL.setAttrNameLoc(attrs->getLoc());
- if (TL.hasAttrExprOperand() && attrs->isArgExpr(0))
+ if (TL.hasAttrExprOperand()) {
+ assert(attrs->isArgExpr(0) && "mismatched attribute operand kind");
TL.setAttrExprOperand(attrs->getArgAsExpr(0));
- else if (TL.hasAttrEnumOperand() && attrs->isArgIdent(0))
- TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc);
+ } else if (TL.hasAttrEnumOperand()) {
+ assert((attrs->isArgIdent(0) || attrs->isArgExpr(0)) &&
+ "unexpected attribute operand kind");
+ if (attrs->isArgIdent(0))
+ TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc);
+ else
+ TL.setAttrEnumOperandLoc(attrs->getArgAsExpr(0)->getExprLoc());
+ }
// FIXME: preserve this information to here.
if (TL.hasAttrOperand())
@@ -3682,6 +3657,9 @@
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
fillAttributedTypeLoc(TL, Chunk.getAttrs());
}
+ void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
+ // nothing
+ }
void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::BlockPointer);
TL.setCaretLoc(Chunk.Loc);
@@ -3763,9 +3741,9 @@
const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
TL.setLParenLoc(FTI.getLParenLoc());
TL.setRParenLoc(FTI.getRParenLoc());
- for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
- ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
- TL.setArg(tpi++, Param);
+ for (unsigned i = 0, e = TL.getNumParams(), tpi = 0; i != e; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
+ TL.setParam(tpi++, Param);
}
// FIXME: exception specs
}
@@ -3837,6 +3815,10 @@
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
}
+ // FIXME: Ordering here?
+ while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>())
+ CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
+
DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
@@ -3936,44 +3918,60 @@
return;
}
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
- Attr.setInvalid();
- return;
- }
- 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_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << ASArgExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
-
- // Bounds checking.
- if (addrSpace.isSigned()) {
- if (addrSpace.isNegative()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative)
+ unsigned ASIdx;
+ if (Attr.getKind() == AttributeList::AT_AddressSpace) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
+ Attr.setInvalid();
+ return;
+ }
+ 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_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
<< ASArgExpr->getSourceRange();
Attr.setInvalid();
return;
}
- addrSpace.setIsSigned(false);
- }
- llvm::APSInt max(addrSpace.getBitWidth());
- max = Qualifiers::MaxAddressSpace;
- if (addrSpace > max) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
- << int(Qualifiers::MaxAddressSpace) << ASArgExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- unsigned ASIdx = static_cast<unsigned>(addrSpace.getZExtValue());
+ // Bounds checking.
+ if (addrSpace.isSigned()) {
+ if (addrSpace.isNegative()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative)
+ << ASArgExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ addrSpace.setIsSigned(false);
+ }
+ llvm::APSInt max(addrSpace.getBitWidth());
+ max = Qualifiers::MaxAddressSpace;
+ if (addrSpace > max) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
+ << int(Qualifiers::MaxAddressSpace) << ASArgExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ ASIdx = static_cast<unsigned>(addrSpace.getZExtValue());
+ } else {
+ // The keyword-based type attributes imply which address space to use.
+ switch (Attr.getKind()) {
+ case AttributeList::AT_OpenCLGlobalAddressSpace:
+ ASIdx = LangAS::opencl_global; break;
+ case AttributeList::AT_OpenCLLocalAddressSpace:
+ ASIdx = LangAS::opencl_local; break;
+ case AttributeList::AT_OpenCLConstantAddressSpace:
+ ASIdx = LangAS::opencl_constant; break;
+ default:
+ assert(Attr.getKind() == AttributeList::AT_OpenCLPrivateAddressSpace);
+ ASIdx = 0; break;
+ }
+ }
+
Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
}
@@ -4586,73 +4584,38 @@
return true;
}
+bool Sema::hasExplicitCallingConv(QualType &T) {
+ QualType R = T.IgnoreParens();
+ while (const AttributedType *AT = dyn_cast<AttributedType>(R)) {
+ if (AT->isCallingConv())
+ return true;
+ R = AT->getModifiedType().IgnoreParens();
+ }
+ return false;
+}
+
void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) {
- const FunctionType *FT = T->castAs<FunctionType>();
+ FunctionTypeUnwrapper Unwrapped(*this, T);
+ const FunctionType *FT = Unwrapped.get();
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 =
+ CallingConv CurCC = FT->getCallConv();
+ CallingConv FromCC =
Context.getDefaultCallingConvention(IsVariadic, IsStatic);
- if (CC != DefaultCC)
+ CallingConv ToCC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
+ if (CurCC != FromCC || FromCC == ToCC)
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)
- << Attr.getName() << 1;
- Attr.setInvalid();
+ if (hasExplicitCallingConv(T))
return;
- }
- 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_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- unsigned iarg = static_cast<unsigned>(arg.getZExtValue());
- switch (iarg) {
- case CLIA_read_only:
- case CLIA_write_only:
- case CLIA_read_write:
- // Implemented in a separate patch
- break;
- default:
- // Implemented in a separate patch
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- break;
- }
+
+ FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(ToCC));
+ QualType Wrapped = Unwrapped.wrap(*this, FT);
+ T = Context.getAdjustedType(T, Wrapped);
}
/// HandleVectorSizeAttribute - this attribute is only applicable to integral
@@ -4757,17 +4720,24 @@
}
static bool isPermittedNeonBaseType(QualType &Ty,
- VectorType::VectorKind VecKind,
- bool IsAArch64) {
+ VectorType::VectorKind VecKind, Sema &S) {
const BuiltinType *BTy = Ty->getAs<BuiltinType>();
if (!BTy)
return false;
+ llvm::Triple Triple = S.Context.getTargetInfo().getTriple();
+
+ // Signed poly is mathematically wrong, but has been baked into some ABIs by
+ // now.
+ bool IsPolyUnsigned = Triple.getArch() == llvm::Triple::aarch64 ||
+ Triple.getArch() == llvm::Triple::aarch64_be ||
+ Triple.getArch() == llvm::Triple::arm64;
if (VecKind == VectorType::NeonPolyVector) {
- if (IsAArch64) {
+ if (IsPolyUnsigned) {
// AArch64 polynomial vectors are unsigned and support poly64.
return BTy->getKind() == BuiltinType::UChar ||
BTy->getKind() == BuiltinType::UShort ||
+ BTy->getKind() == BuiltinType::ULong ||
BTy->getKind() == BuiltinType::ULongLong;
} else {
// AArch32 polynomial vector are signed.
@@ -4778,7 +4748,11 @@
// Non-polynomial vector types: the usual suspects are allowed, as well as
// float64_t on AArch64.
- if (IsAArch64 && BTy->getKind() == BuiltinType::Double)
+ bool Is64Bit = Triple.getArch() == llvm::Triple::aarch64 ||
+ Triple.getArch() == llvm::Triple::aarch64_be ||
+ Triple.getArch() == llvm::Triple::arm64;
+
+ if (Is64Bit && BTy->getKind() == BuiltinType::Double)
return true;
return BTy->getKind() == BuiltinType::SChar ||
@@ -4787,6 +4761,8 @@
BTy->getKind() == BuiltinType::UShort ||
BTy->getKind() == BuiltinType::Int ||
BTy->getKind() == BuiltinType::UInt ||
+ BTy->getKind() == BuiltinType::Long ||
+ BTy->getKind() == BuiltinType::ULong ||
BTy->getKind() == BuiltinType::LongLong ||
BTy->getKind() == BuiltinType::ULongLong ||
BTy->getKind() == BuiltinType::Float ||
@@ -4828,10 +4804,7 @@
return;
}
// Only certain element types are supported for Neon vectors.
- llvm::Triple::ArchType Arch =
- S.Context.getTargetInfo().getTriple().getArch();
- if (!isPermittedNeonBaseType(CurType, VecKind,
- Arch == llvm::Triple::aarch64)) {
+ if (!isPermittedNeonBaseType(CurType, VecKind, S)) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
Attr.setInvalid();
return;
@@ -4911,6 +4884,10 @@
// it it breaks large amounts of Linux software.
attr.setUsedAsTypeAttr();
break;
+ case AttributeList::AT_OpenCLPrivateAddressSpace:
+ case AttributeList::AT_OpenCLGlobalAddressSpace:
+ case AttributeList::AT_OpenCLLocalAddressSpace:
+ case AttributeList::AT_OpenCLConstantAddressSpace:
case AttributeList::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
@@ -4939,13 +4916,11 @@
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_OpenCLImageAccess:
- HandleOpenCLImageAccessAttribute(type, attr, state.getSema());
+ // FIXME: there should be some type checking happening here, I would
+ // imagine, but the original handler's checking was entirely superfluous.
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_Win64:
- attr.setUsedAsTypeAttr();
- break;
MS_TYPE_ATTRS_CASELIST:
if (!handleMSPointerTypeQualifierAttr(state, attr, type))
attr.setUsedAsTypeAttr();
@@ -5058,7 +5033,7 @@
TypeDiagnoserDiag(unsigned DiagID)
: Sema::TypeDiagnoser(DiagID == 0), DiagID(DiagID) {}
- virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
if (Suppressed) return;
S.Diag(Loc, DiagID) << T;
}
@@ -5132,6 +5107,46 @@
}
}
+ // We lock in the inheritance model once somebody has asked us to ensure
+ // that a pointer-to-member type is complete.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
+ if (!MPTy->getClass()->isDependentType()) {
+ RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0);
+
+ CXXRecordDecl *RD = MPTy->getMostRecentCXXRecordDecl();
+ if (!RD->hasAttr<MSInheritanceAttr>()) {
+ MSInheritanceAttr::Spelling InheritanceModel;
+
+ switch (MSPointerToMemberRepresentationMethod) {
+ case LangOptions::PPTMK_BestCase:
+ InheritanceModel = RD->calculateInheritanceModel();
+ break;
+ case LangOptions::PPTMK_FullGeneralitySingleInheritance:
+ InheritanceModel = MSInheritanceAttr::Keyword_single_inheritance;
+ break;
+ case LangOptions::PPTMK_FullGeneralityMultipleInheritance:
+ InheritanceModel =
+ MSInheritanceAttr::Keyword_multiple_inheritance;
+ break;
+ case LangOptions::PPTMK_FullGeneralityVirtualInheritance:
+ InheritanceModel =
+ MSInheritanceAttr::Keyword_unspecified_inheritance;
+ break;
+ }
+
+ RD->addAttr(MSInheritanceAttr::CreateImplicit(
+ getASTContext(), InheritanceModel,
+ /*BestCase=*/MSPointerToMemberRepresentationMethod ==
+ LangOptions::PPTMK_BestCase,
+ ImplicitMSInheritanceAttrLoc.isValid()
+ ? ImplicitMSInheritanceAttrLoc
+ : RD->getSourceRange()));
+ }
+ }
+ }
+ }
+
return false;
}
@@ -5310,29 +5325,26 @@
if (RD->getNumVBases()) {
Diag(RD->getLocation(), diag::note_non_literal_virtual_base)
<< getLiteralDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
- for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
- E = RD->vbases_end(); I != E; ++I)
- Diag(I->getLocStart(),
- diag::note_constexpr_virtual_base_here) << I->getSourceRange();
+ for (const auto &I : RD->vbases())
+ Diag(I.getLocStart(), diag::note_constexpr_virtual_base_here)
+ << I.getSourceRange();
} else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor() &&
!RD->hasTrivialDefaultConstructor()) {
Diag(RD->getLocation(), diag::note_non_literal_no_constexpr_ctors) << RD;
} else if (RD->hasNonLiteralTypeFieldsOrBases()) {
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I) {
- if (!I->getType()->isLiteralType(Context)) {
- Diag(I->getLocStart(),
+ for (const auto &I : RD->bases()) {
+ if (!I.getType()->isLiteralType(Context)) {
+ Diag(I.getLocStart(),
diag::note_non_literal_base_class)
- << RD << I->getType() << I->getSourceRange();
+ << RD << I.getType() << I.getSourceRange();
return true;
}
}
- for (CXXRecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end(); I != E; ++I) {
+ for (const auto *I : RD->fields()) {
if (!I->getType()->isLiteralType(Context) ||
I->getType().isVolatileQualified()) {
Diag(I->getLocation(), diag::note_non_literal_field)
- << RD << *I << I->getType()
+ << RD << I << I->getType()
<< I->getType().isVolatileQualified();
return true;
}
@@ -5368,7 +5380,7 @@
return T;
NestedNameSpecifier *NNS;
if (SS.isValid())
- NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ NNS = SS.getScopeRep();
else {
if (Keyword == ETK_None)
return T;
diff --git a/lib/Sema/TargetAttributesSema.cpp b/lib/Sema/TargetAttributesSema.cpp
deleted file mode 100644
index 45067de..0000000
--- a/lib/Sema/TargetAttributesSema.cpp
+++ /dev/null
@@ -1,353 +0,0 @@
-//===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains semantic analysis implementation for target-specific
-// attributes.
-//
-//===----------------------------------------------------------------------===//
-
-#include "TargetAttributesSema.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Sema/SemaInternal.h"
-#include "llvm/ADT/Triple.h"
-
-using namespace clang;
-
-TargetAttributesSema::~TargetAttributesSema() {}
-bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const {
- 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)
- << Attr.getName() << 1;
- return;
- }
-
- // FIXME: Check for decl - it should be void ()(void).
-
- 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_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << NumParamsExpr->getSourceRange();
- return;
- }
-
- unsigned Num = NumParams.getLimitedValue(255);
- if ((Num & 1) || Num > 30) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << "interrupt" << (int)NumParams.getSExtValue()
- << NumParamsExpr->getSourceRange();
- return;
- }
-
- d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
- d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
- }
-
-namespace {
- class MSP430AttributesSema : public TargetAttributesSema {
- public:
- MSP430AttributesSema() { }
- bool ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const {
- if (Attr.getName()->getName() == "interrupt") {
- HandleMSP430InterruptAttr(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)
- << Attr.getName() << 0;
- return;
- }
-
- // If we try to apply it to a function pointer, don't warn, but don't
- // do anything, either. It doesn't matter anyway, because there's nothing
- // special about calling a force_align_arg_pointer function.
- ValueDecl *VD = dyn_cast<ValueDecl>(D);
- if (VD && VD->getType()->isFunctionPointerType())
- return;
- // Also don't warn on function pointer typedefs.
- TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
- if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
- TD->getUnderlyingType()->isFunctionType()))
- return;
- // Attribute can only be applied to function types.
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << /* function */0;
- return;
- }
-
- D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getRange(),
- S.Context));
-}
-
-DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex) {
- if (D->hasAttr<DLLExportAttr>()) {
- Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport";
- return NULL;
- }
-
- 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);
-}
-
-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)
- << Attr.getName() << 0;
- return;
- }
-
- // Attribute can be applied only to functions or variables.
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD && !isa<VarDecl>(D)) {
- // Apparently Visual C++ thinks it is okay to not emit a warning
- // in this case, so only emit a warning when -fms-extensions is not
- // specified.
- if (!S.getLangOpts().MicrosoftExt)
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 2 /*variable and function*/;
- return;
- }
-
- // Currently, the dllimport attribute is ignored for inlined functions.
- // Warning is emitted.
- if (FD && FD->isInlineSpecified()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
- return;
- }
-
- unsigned Index = Attr.getAttributeSpellingListIndex();
- DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index);
- if (NewAttr)
- D->addAttr(NewAttr);
-}
-
-DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex) {
- if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
- Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport";
- D->dropAttr<DLLImportAttr>();
- }
-
- if (D->hasAttr<DLLExportAttr>())
- return NULL;
-
- return ::new (Context) DLLExportAttr(Range, Context,
- AttrSpellingListIndex);
-}
-
-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)
- << Attr.getName() << 0;
- return;
- }
-
- // Attribute can be applied only to functions or variables.
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD && !isa<VarDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 2 /*variable and function*/;
- return;
- }
-
- // Currently, the dllexport attribute is ignored for inlined functions, unless
- // the -fkeep-inline-functions flag has been used. Warning is emitted;
- if (FD && FD->isInlineSpecified()) {
- // FIXME: ... unless the -fkeep-inline-functions flag has been used.
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
- return;
- }
-
- unsigned Index = Attr.getAttributeSpellingListIndex();
- DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index);
- if (NewAttr)
- D->addAttr(NewAttr);
-}
-
-namespace {
- class X86AttributesSema : public TargetAttributesSema {
- public:
- X86AttributesSema() { }
- bool ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const {
- const llvm::Triple &Triple(S.Context.getTargetInfo().getTriple());
- if (Triple.getOS() == llvm::Triple::Win32 ||
- Triple.getOS() == llvm::Triple::MinGW32) {
- switch (Attr.getKind()) {
- case AttributeList::AT_DLLImport: HandleDLLImportAttr(D, Attr, S);
- return true;
- case AttributeList::AT_DLLExport: HandleDLLExportAttr(D, Attr, S);
- return true;
- default: break;
- }
- }
- if (Triple.getArch() != llvm::Triple::x86_64 &&
- (Attr.getName()->getName() == "force_align_arg_pointer" ||
- Attr.getName()->getName() == "__force_align_arg_pointer__")) {
- HandleX86ForceAlignArgPointerAttr(D, Attr, S);
- return true;
- }
- return false;
- }
- };
-}
-
-static void HandleMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
- // check the attribute arguments.
- 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.
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << /* function */0;
- return;
- }
- D->addAttr(::new (S.Context) Mips16Attr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void HandleNoMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
- // check the attribute arguments.
- 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.
- if (!isa<FunctionDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << /* function */0;
- return;
- }
- D->addAttr(::new (S.Context)
- NoMips16Attr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
-
-namespace {
- class MipsAttributesSema : public TargetAttributesSema {
- public:
- MipsAttributesSema() { }
- bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr,
- Sema &S) const {
- if (Attr.getName()->getName() == "mips16") {
- HandleMips16Attr(D, Attr, S);
- return true;
- } else if (Attr.getName()->getName() == "nomips16") {
- HandleNoMips16Attr(D, Attr, S);
- return true;
- }
- return false;
- }
- };
-}
-
-const TargetAttributesSema &Sema::getTargetAttributesSema() const {
- if (TheTargetAttributesSema)
- return *TheTargetAttributesSema;
-
- 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::x86:
- case llvm::Triple::x86_64:
- return *(TheTargetAttributesSema = new X86AttributesSema);
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- return *(TheTargetAttributesSema = new MipsAttributesSema);
- default:
- return *(TheTargetAttributesSema = new TargetAttributesSema);
- }
-}
diff --git a/lib/Sema/TargetAttributesSema.h b/lib/Sema/TargetAttributesSema.h
deleted file mode 100644
index 410c900..0000000
--- a/lib/Sema/TargetAttributesSema.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//===--- TargetAttributesSema.h - Semantic Analysis For Target Attributes -===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_SEMA_TARGETSEMA_H
-#define CLANG_SEMA_TARGETSEMA_H
-
-namespace clang {
- class Scope;
- class Decl;
- class AttributeList;
- class Sema;
-
- class TargetAttributesSema {
- public:
- virtual ~TargetAttributesSema();
- virtual bool ProcessDeclAttribute(Scope *scope, Decl *D,
- const AttributeList &Attr, Sema &S) const;
- };
-}
-
-#endif
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 4351c25..f78fca7 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -607,6 +607,7 @@
ExprResult TransformAddressOfOperand(Expr *E);
ExprResult TransformDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E,
bool IsAddressOfOperand);
+ StmtResult TransformOMPExecutableDirective(OMPExecutableDirective *S);
// FIXME: We use LLVM_ATTRIBUTE_NOINLINE because inlining causes a ridiculous
// amount of stack usage with clang.
@@ -951,9 +952,8 @@
break;
}
default:
- // FIXME: Would be nice to highlight just the source range.
SemaRef.Diag(IdLoc, diag::err_not_tag_in_scope)
- << Kind << Id << DC;
+ << Kind << Id << DC << QualifierLoc.getSourceRange();
break;
}
return QualType();
@@ -1286,16 +1286,51 @@
return getSema().BuildObjCAtThrowStmt(AtLoc, Operand);
}
- /// \brief Build a new OpenMP parallel directive.
+ /// \brief Build a new OpenMP executable 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);
+ StmtResult RebuildOMPExecutableDirective(OpenMPDirectiveKind Kind,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPExecutableDirective(Kind, Clauses, AStmt,
+ StartLoc, EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'if' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPIfClause(Expr *Condition,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPIfClause(Condition, StartLoc,
+ LParenLoc, EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'num_threads' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPNumThreadsClause(Expr *NumThreads,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPNumThreadsClause(NumThreads, StartLoc,
+ LParenLoc, EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'safelen' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPSafelenClause(Expr *Len, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPSafelenClause(Len, StartLoc, LParenLoc, EndLoc);
}
/// \brief Build a new OpenMP 'default' clause.
@@ -1335,6 +1370,10 @@
EndLoc);
}
+ /// \brief Build a new OpenMP 'shared' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPSharedClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -1343,6 +1382,18 @@
EndLoc);
}
+ /// \brief Build a new OpenMP 'copyin' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPCopyinClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -2135,29 +2186,6 @@
Operand);
}
- /// \brief Build a new unary type trait expression.
- ///
- /// By default, performs semantic analysis to build the new expression.
- /// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildUnaryTypeTrait(UnaryTypeTrait Trait,
- SourceLocation StartLoc,
- TypeSourceInfo *T,
- SourceLocation RParenLoc) {
- return getSema().BuildUnaryTypeTrait(Trait, StartLoc, T, RParenLoc);
- }
-
- /// \brief Build a new binary type trait expression.
- ///
- /// By default, performs semantic analysis to build the new expression.
- /// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildBinaryTypeTrait(BinaryTypeTrait Trait,
- SourceLocation StartLoc,
- TypeSourceInfo *LhsT,
- TypeSourceInfo *RhsT,
- SourceLocation RParenLoc) {
- return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc);
- }
-
/// \brief Build a new type trait expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -2555,11 +2583,9 @@
CK_BuiltinFnToFnPtr).take();
// Build the CallExpr
- ExprResult TheCall = SemaRef.Owned(
- new (SemaRef.Context) CallExpr(SemaRef.Context, Callee, SubExprs,
- Builtin->getCallResultType(),
- Expr::getValueKindForType(Builtin->getResultType()),
- RParenLoc));
+ ExprResult TheCall = SemaRef.Owned(new (SemaRef.Context) CallExpr(
+ SemaRef.Context, Callee, SubExprs, Builtin->getCallResultType(),
+ Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc));
// Type-check the __builtin_shufflevector expression.
return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.take()));
@@ -2657,6 +2683,10 @@
QualType ObjectType,
NamedDecl *FirstQualifierInScope,
CXXScopeSpec &SS);
+
+ TypeSourceInfo *TransformTSIInObjectScope(TypeLoc TL, QualType ObjectType,
+ NamedDecl *FirstQualifierInScope,
+ CXXScopeSpec &SS);
};
template<typename Derived>
@@ -3564,52 +3594,14 @@
QualType ObjectType,
NamedDecl *UnqualLookup,
CXXScopeSpec &SS) {
- QualType T = TL.getType();
- if (getDerived().AlreadyTransformed(T))
+ if (getDerived().AlreadyTransformed(TL.getType()))
return TL;
- TypeLocBuilder TLB;
- QualType Result;
-
- if (isa<TemplateSpecializationType>(T)) {
- TemplateSpecializationTypeLoc SpecTL =
- TL.castAs<TemplateSpecializationTypeLoc>();
-
- TemplateName Template =
- getDerived().TransformTemplateName(SS,
- SpecTL.getTypePtr()->getTemplateName(),
- SpecTL.getTemplateNameLoc(),
- ObjectType, UnqualLookup);
- if (Template.isNull())
- return TypeLoc();
-
- Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL,
- Template);
- } else if (isa<DependentTemplateSpecializationType>(T)) {
- DependentTemplateSpecializationTypeLoc SpecTL =
- TL.castAs<DependentTemplateSpecializationTypeLoc>();
-
- TemplateName Template
- = getDerived().RebuildTemplateName(SS,
- *SpecTL.getTypePtr()->getIdentifier(),
- SpecTL.getTemplateNameLoc(),
- ObjectType, UnqualLookup);
- if (Template.isNull())
- return TypeLoc();
-
- Result = getDerived().TransformDependentTemplateSpecializationType(TLB,
- SpecTL,
- Template,
- SS);
- } else {
- // Nothing special needs to be done for these.
- Result = getDerived().TransformType(TLB, TL);
- }
-
- if (Result.isNull())
- return TypeLoc();
-
- return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc();
+ TypeSourceInfo *TSI =
+ TransformTSIInObjectScope(TL, ObjectType, UnqualLookup, SS);
+ if (TSI)
+ return TSI->getTypeLoc();
+ return TypeLoc();
}
template<typename Derived>
@@ -3618,16 +3610,23 @@
QualType ObjectType,
NamedDecl *UnqualLookup,
CXXScopeSpec &SS) {
- // FIXME: Painfully copy-paste from the above!
-
- QualType T = TSInfo->getType();
- if (getDerived().AlreadyTransformed(T))
+ if (getDerived().AlreadyTransformed(TSInfo->getType()))
return TSInfo;
+ return TransformTSIInObjectScope(TSInfo->getTypeLoc(), ObjectType,
+ UnqualLookup, SS);
+}
+
+template <typename Derived>
+TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope(
+ TypeLoc TL, QualType ObjectType, NamedDecl *UnqualLookup,
+ CXXScopeSpec &SS) {
+ QualType T = TL.getType();
+ assert(!getDerived().AlreadyTransformed(T));
+
TypeLocBuilder TLB;
QualType Result;
- TypeLoc TL = TSInfo->getTypeLoc();
if (isa<TemplateSpecializationType>(T)) {
TemplateSpecializationTypeLoc SpecTL =
TL.castAs<TemplateSpecializationTypeLoc>();
@@ -3693,6 +3692,13 @@
return TransformTypeSpecType(TLB, T);
}
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformAdjustedType(TypeLocBuilder &TLB,
+ AdjustedTypeLoc TL) {
+ // Adjustments applied during transformation are handled elsewhere.
+ return getDerived().TransformType(TLB, TL.getOriginalLoc());
+}
+
template<typename Derived>
QualType TreeTransform<Derived>::TransformDecayedType(TypeLocBuilder &TLB,
DecayedTypeLoc TL) {
@@ -3861,6 +3867,14 @@
return QualType();
}
+ // If we had to adjust the pointee type when building a member pointer, make
+ // sure to push TypeLoc info for it.
+ const MemberPointerType *MPT = Result->getAs<MemberPointerType>();
+ if (MPT && PointeeType != MPT->getPointeeType()) {
+ assert(isa<AdjustedType>(MPT->getPointeeType()));
+ TLB.push<AdjustedTypeLoc>(MPT->getPointeeType());
+ }
+
MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result);
NewTL.setSigilLoc(TL.getSigilLoc());
NewTL.setClassTInfo(NewClsTInfo);
@@ -3966,7 +3980,9 @@
return QualType();
}
- VariableArrayTypeLoc NewTL = TLB.push<VariableArrayTypeLoc>(Result);
+ // We might have constant size array now, but fortunately it has the same
+ // location layout.
+ ArrayTypeLoc NewTL = TLB.push<ArrayTypeLoc>(Result);
NewTL.setLBracketLoc(TL.getLBracketLoc());
NewTL.setRBracketLoc(TL.getRBracketLoc());
NewTL.setSizeExpr(Size);
@@ -4391,11 +4407,9 @@
QualType ResultType;
if (T->hasTrailingReturn()) {
- if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(),
- TL.getParmArray(),
- TL.getNumArgs(),
- TL.getTypePtr()->arg_type_begin(),
- ParamTypes, &ParamDecls))
+ if (getDerived().TransformFunctionTypeParams(
+ TL.getBeginLoc(), TL.getParmArray(), TL.getNumParams(),
+ TL.getTypePtr()->param_type_begin(), ParamTypes, &ParamDecls))
return QualType();
{
@@ -4407,31 +4421,29 @@
// declarator.
Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals);
- ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ ResultType = getDerived().TransformType(TLB, TL.getReturnLoc());
if (ResultType.isNull())
return QualType();
}
}
else {
- ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ ResultType = getDerived().TransformType(TLB, TL.getReturnLoc());
if (ResultType.isNull())
return QualType();
- if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(),
- TL.getParmArray(),
- TL.getNumArgs(),
- TL.getTypePtr()->arg_type_begin(),
- ParamTypes, &ParamDecls))
+ if (getDerived().TransformFunctionTypeParams(
+ TL.getBeginLoc(), TL.getParmArray(), TL.getNumParams(),
+ TL.getTypePtr()->param_type_begin(), ParamTypes, &ParamDecls))
return QualType();
}
// FIXME: Need to transform the exception-specification too.
QualType Result = TL.getType();
- if (getDerived().AlwaysRebuild() ||
- ResultType != T->getResultType() ||
- T->getNumArgs() != ParamTypes.size() ||
- !std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) {
+ if (getDerived().AlwaysRebuild() || ResultType != T->getReturnType() ||
+ T->getNumParams() != ParamTypes.size() ||
+ !std::equal(T->param_type_begin(), T->param_type_end(),
+ ParamTypes.begin())) {
Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes,
T->getExtProtoInfo());
if (Result.isNull())
@@ -4443,8 +4455,8 @@
NewTL.setLParenLoc(TL.getLParenLoc());
NewTL.setRParenLoc(TL.getRParenLoc());
NewTL.setLocalRangeEnd(TL.getLocalRangeEnd());
- for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i)
- NewTL.setArg(i, ParamDecls[i]);
+ for (unsigned i = 0, e = NewTL.getNumParams(); i != e; ++i)
+ NewTL.setParam(i, ParamDecls[i]);
return Result;
}
@@ -4454,13 +4466,12 @@
TypeLocBuilder &TLB,
FunctionNoProtoTypeLoc TL) {
const FunctionNoProtoType *T = TL.getTypePtr();
- QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ QualType ResultType = getDerived().TransformType(TLB, TL.getReturnLoc());
if (ResultType.isNull())
return QualType();
QualType Result = TL.getType();
- if (getDerived().AlwaysRebuild() ||
- ResultType != T->getResultType())
+ if (getDerived().AlwaysRebuild() || ResultType != T->getReturnType())
Result = getDerived().RebuildFunctionNoProtoType(ResultType);
FunctionNoProtoTypeLoc NewTL = TLB.push<FunctionNoProtoTypeLoc>(Result);
@@ -5284,13 +5295,12 @@
bool SubStmtInvalid = false;
bool SubStmtChanged = false;
SmallVector<Stmt*, 8> Statements;
- for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
- B != BEnd; ++B) {
- StmtResult Result = getDerived().TransformStmt(*B);
+ for (auto *B : S->body()) {
+ StmtResult Result = getDerived().TransformStmt(B);
if (Result.isInvalid()) {
// Immediately fail if this was a DeclStmt, since it's very
// likely that this will cause problems for future statements.
- if (isa<DeclStmt>(*B))
+ if (isa<DeclStmt>(B))
return StmtError();
// Otherwise, just keep processing substatements and fail later.
@@ -5298,7 +5308,7 @@
continue;
}
- SubStmtChanged = SubStmtChanged || Result.get() != *B;
+ SubStmtChanged = SubStmtChanged || Result.get() != B;
Statements.push_back(Result.takeAs<Stmt>());
}
@@ -5695,14 +5705,12 @@
TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) {
bool DeclChanged = false;
SmallVector<Decl *, 4> Decls;
- for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
- D != DEnd; ++D) {
- Decl *Transformed = getDerived().TransformDefinition((*D)->getLocation(),
- *D);
+ for (auto *D : S->decls()) {
+ Decl *Transformed = getDerived().TransformDefinition(D->getLocation(), D);
if (!Transformed)
return StmtError();
- if (Transformed != *D)
+ if (Transformed != D)
DeclChanged = true;
Decls.push_back(Transformed);
@@ -6276,9 +6284,8 @@
template<typename Derived>
StmtResult
-TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) {
- DeclarationNameInfo DirName;
- getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, 0);
+TreeTransform<Derived>::TransformOMPExecutableDirective(
+ OMPExecutableDirective *D) {
// Transform the clauses
llvm::SmallVector<OMPClause *, 16> TClauses;
@@ -6289,7 +6296,6 @@
if (*I) {
OMPClause *Clause = getDerived().TransformOMPClause(*I);
if (!Clause) {
- getSema().EndOpenMPDSABlock(0);
return StmtError();
}
TClauses.push_back(Clause);
@@ -6299,25 +6305,74 @@
}
}
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 getDerived().RebuildOMPExecutableDirective(D->getDirectiveKind(),
+ TClauses,
+ AssociatedStmt.take(),
+ D->getLocStart(),
+ D->getLocEnd());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, 0);
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
}
template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPSimdDirective(OMPSimdDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, 0);
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template<typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPIfClause(OMPIfClause *C) {
+ ExprResult Cond = getDerived().TransformExpr(C->getCondition());
+ if (Cond.isInvalid())
+ return 0;
+ return getDerived().RebuildOMPIfClause(Cond.take(), C->getLocStart(),
+ C->getLParenLoc(), C->getLocEnd());
+}
+
+template<typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPNumThreadsClause(OMPNumThreadsClause *C) {
+ ExprResult NumThreads = getDerived().TransformExpr(C->getNumThreads());
+ if (NumThreads.isInvalid())
+ return 0;
+ return getDerived().RebuildOMPNumThreadsClause(NumThreads.take(),
+ C->getLocStart(),
+ C->getLParenLoc(),
+ C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPSafelenClause(OMPSafelenClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getSafelen());
+ if (E.isInvalid())
+ return 0;
+ return getDerived().RebuildOMPSafelenClause(
+ E.take(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template<typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) {
return getDerived().RebuildOMPDefaultClause(C->getDefaultKind(),
@@ -6332,10 +6387,8 @@
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));
+ for (auto *I : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(I));
if (EVar.isInvalid())
return 0;
Vars.push_back(EVar.take());
@@ -6352,10 +6405,8 @@
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));
+ for (auto *I : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(I));
if (EVar.isInvalid())
return 0;
Vars.push_back(EVar.take());
@@ -6371,10 +6422,8 @@
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));
+ for (auto *I : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(I));
if (EVar.isInvalid())
return 0;
Vars.push_back(EVar.take());
@@ -6385,6 +6434,23 @@
C->getLocEnd());
}
+template<typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPCopyinClause(OMPCopyinClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *I : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(I));
+ if (EVar.isInvalid())
+ return 0;
+ Vars.push_back(EVar.take());
+ }
+ return getDerived().RebuildOMPCopyinClause(Vars,
+ C->getLocStart(),
+ C->getLParenLoc(),
+ C->getLocEnd());
+}
+
//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//
@@ -7829,9 +7895,8 @@
// Expand using declarations.
if (isa<UsingDecl>(InstD)) {
UsingDecl *UD = cast<UsingDecl>(InstD);
- for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
- E = UD->shadow_end(); I != E; ++I)
- R.addDecl(*I);
+ for (auto *I : UD->shadows())
+ R.addDecl(I);
continue;
}
@@ -7890,44 +7955,6 @@
template<typename Derived>
ExprResult
-TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
- TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo());
- if (!T)
- return ExprError();
-
- if (!getDerived().AlwaysRebuild() &&
- T == E->getQueriedTypeSourceInfo())
- return SemaRef.Owned(E);
-
- return getDerived().RebuildUnaryTypeTrait(E->getTrait(),
- E->getLocStart(),
- T,
- E->getLocEnd());
-}
-
-template<typename Derived>
-ExprResult
-TreeTransform<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
- TypeSourceInfo *LhsT = getDerived().TransformType(E->getLhsTypeSourceInfo());
- if (!LhsT)
- return ExprError();
-
- TypeSourceInfo *RhsT = getDerived().TransformType(E->getRhsTypeSourceInfo());
- if (!RhsT)
- return ExprError();
-
- if (!getDerived().AlwaysRebuild() &&
- LhsT == E->getLhsTypeSourceInfo() && RhsT == E->getRhsTypeSourceInfo())
- return SemaRef.Owned(E);
-
- return getDerived().RebuildBinaryTypeTrait(E->getTrait(),
- E->getLocStart(),
- LhsT, RhsT,
- E->getLocEnd());
-}
-
-template<typename Derived>
-ExprResult
TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) {
bool ArgChanged = false;
SmallVector<TypeSourceInfo *, 4> Args;
@@ -8353,7 +8380,7 @@
FunctionProtoTypeLoc NewCallOpFPTL =
NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
ParmVarDecl **NewParamDeclArray = NewCallOpFPTL.getParmArray();
- const unsigned NewNumArgs = NewCallOpFPTL.getNumArgs();
+ const unsigned NewNumArgs = NewCallOpFPTL.getNumParams();
for (unsigned I = 0; I < NewNumArgs; ++I) {
// If this call operator's type does not require transformation,
@@ -8416,7 +8443,8 @@
bool Invalid = false;
// Introduce the context of the call operator.
- Sema::ContextRAII SavedContext(getSema(), CallOperator);
+ Sema::ContextRAII SavedContext(getSema(), CallOperator,
+ /*NewThisContext*/false);
LambdaScopeInfo *const LSI = getSema().getCurLambda();
// Enter the scope of the lambda.
@@ -8734,9 +8762,8 @@
// Expand using declarations.
if (isa<UsingDecl>(InstD)) {
UsingDecl *UD = cast<UsingDecl>(InstD);
- for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
- E = UD->shadow_end(); I != E; ++I)
- R.addDecl(*I);
+ for (auto *I : UD->shadows())
+ R.addDecl(I);
continue;
}
@@ -9337,7 +9364,7 @@
const FunctionProtoType *exprFunctionType = E->getFunctionType();
QualType exprResultType =
- getDerived().TransformType(exprFunctionType->getResultType());
+ getDerived().TransformType(exprFunctionType->getReturnType());
QualType functionType =
getDerived().RebuildFunctionProtoType(exprResultType, paramTypes,
@@ -9364,9 +9391,8 @@
// In builds with assertions, make sure that we captured everything we
// captured before.
if (!SemaRef.getDiagnostics().hasErrorOccurred()) {
- for (BlockDecl::capture_iterator i = oldBlock->capture_begin(),
- e = oldBlock->capture_end(); i != e; ++i) {
- VarDecl *oldCapture = i->getVariable();
+ for (const auto &I : oldBlock->captures()) {
+ VarDecl *oldCapture = I.getVariable();
// Ignore parameter packs.
if (isa<ParmVarDecl>(oldCapture) &&
@@ -9443,8 +9469,8 @@
TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
QualType ClassType,
SourceLocation Sigil) {
- return SemaRef.BuildMemberPointerType(PointeeType, ClassType,
- Sigil, getDerived().getBaseEntity());
+ return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Sigil,
+ getDerived().getBaseEntity());
}
template<typename Derived>