aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp191
-rw-r--r--lib/Sema/AttributeList.cpp8
-rw-r--r--lib/Sema/CMakeLists.txt1
-rw-r--r--lib/Sema/DeclSpec.cpp49
-rw-r--r--lib/Sema/IdentifierResolver.cpp3
-rw-r--r--lib/Sema/JumpDiagnostics.cpp22
-rw-r--r--lib/Sema/MultiplexExternalSemaSource.cpp6
-rw-r--r--lib/Sema/Scope.cpp9
-rw-r--r--lib/Sema/ScopeInfo.cpp19
-rw-r--r--lib/Sema/Sema.cpp52
-rw-r--r--lib/Sema/SemaAccess.cpp4
-rw-r--r--lib/Sema/SemaAttr.cpp26
-rw-r--r--lib/Sema/SemaCUDA.cpp263
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp65
-rw-r--r--lib/Sema/SemaCast.cpp54
-rw-r--r--lib/Sema/SemaChecking.cpp716
-rw-r--r--lib/Sema/SemaCodeComplete.cpp111
-rw-r--r--lib/Sema/SemaDecl.cpp784
-rw-r--r--lib/Sema/SemaDeclAttr.cpp823
-rw-r--r--lib/Sema/SemaDeclCXX.cpp1207
-rw-r--r--lib/Sema/SemaDeclObjC.cpp184
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp117
-rw-r--r--lib/Sema/SemaExpr.cpp798
-rw-r--r--lib/Sema/SemaExprCXX.cpp411
-rw-r--r--lib/Sema/SemaExprMember.cpp132
-rw-r--r--lib/Sema/SemaExprObjC.cpp172
-rw-r--r--lib/Sema/SemaInit.cpp198
-rw-r--r--lib/Sema/SemaLambda.cpp27
-rw-r--r--lib/Sema/SemaLookup.cpp759
-rw-r--r--lib/Sema/SemaObjCProperty.cpp52
-rw-r--r--lib/Sema/SemaOpenMP.cpp1694
-rw-r--r--lib/Sema/SemaOverload.cpp616
-rw-r--r--lib/Sema/SemaPseudoObject.cpp9
-rw-r--r--lib/Sema/SemaStmt.cpp448
-rw-r--r--lib/Sema/SemaStmtAsm.cpp200
-rw-r--r--lib/Sema/SemaStmtAttr.cpp128
-rw-r--r--lib/Sema/SemaTemplate.cpp244
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp65
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp248
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp470
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp167
-rw-r--r--lib/Sema/SemaType.cpp215
-rw-r--r--lib/Sema/TreeTransform.h662
-rw-r--r--lib/Sema/TypeLocBuilder.h4
44 files changed, 8992 insertions, 3441 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 213d6fbffffc..f666a9b46384 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -530,44 +530,37 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
return;
- // FIXME: Function try block
- if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
- switch (CheckFallThrough(AC)) {
- case UnknownFallThrough:
- break;
+ SourceLocation LBrace = Body->getLocStart(), RBrace = Body->getLocEnd();
+ // Either in a function body compound statement, or a function-try-block.
+ switch (CheckFallThrough(AC)) {
+ case UnknownFallThrough:
+ break;
- case MaybeFallThrough:
- if (HasNoReturn)
- S.Diag(Compound->getRBracLoc(),
- CD.diag_MaybeFallThrough_HasNoReturn);
- else if (!ReturnsVoid)
- S.Diag(Compound->getRBracLoc(),
- CD.diag_MaybeFallThrough_ReturnsNonVoid);
- break;
- case AlwaysFallThrough:
- if (HasNoReturn)
- S.Diag(Compound->getRBracLoc(),
- CD.diag_AlwaysFallThrough_HasNoReturn);
- else if (!ReturnsVoid)
- S.Diag(Compound->getRBracLoc(),
- CD.diag_AlwaysFallThrough_ReturnsNonVoid);
- break;
- case NeverFallThroughOrReturn:
- if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn)
- << 0 << FD;
- } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
- S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn)
- << 1 << MD;
- } else {
- S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn);
- }
+ case MaybeFallThrough:
+ if (HasNoReturn)
+ S.Diag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn);
+ else if (!ReturnsVoid)
+ S.Diag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid);
+ break;
+ case AlwaysFallThrough:
+ if (HasNoReturn)
+ S.Diag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn);
+ else if (!ReturnsVoid)
+ S.Diag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid);
+ break;
+ case NeverFallThroughOrReturn:
+ if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD;
+ } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD;
+ } else {
+ S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn);
}
- break;
- case NeverFallThrough:
- break;
- }
+ }
+ break;
+ case NeverFallThrough:
+ break;
}
}
@@ -923,7 +916,7 @@ namespace {
// issue a warn_fallthrough_attr_unreachable for them.
for (const auto *B : *Cfg) {
const Stmt *L = B->getLabel();
- if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B))
+ if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second)
BlockQueue.push_back(B);
}
@@ -933,7 +926,7 @@ namespace {
for (CFGBlock::const_succ_iterator I = P->succ_begin(),
E = P->succ_end();
I != E; ++I) {
- if (*I && ReachableBlocks.insert(*I))
+ if (*I && ReachableBlocks.insert(*I).second)
BlockQueue.push_back(*I);
}
}
@@ -1444,13 +1437,51 @@ struct SortDiagBySourceLocation {
// -Wthread-safety
//===----------------------------------------------------------------------===//
namespace clang {
-namespace thread_safety {
-namespace {
-class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
+namespace threadSafety {
+
+class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
Sema &S;
DiagList Warnings;
SourceLocation FunLocation, FunEndLocation;
+ const FunctionDecl *CurrentFunction;
+ bool Verbose;
+
+ OptionalNotes getNotes() const {
+ if (Verbose && CurrentFunction) {
+ PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
+ S.PDiag(diag::note_thread_warning_in_fun)
+ << CurrentFunction->getNameAsString());
+ return OptionalNotes(1, FNote);
+ }
+ return OptionalNotes();
+ }
+
+ OptionalNotes getNotes(const PartialDiagnosticAt &Note) const {
+ OptionalNotes ONS(1, Note);
+ if (Verbose && CurrentFunction) {
+ PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
+ S.PDiag(diag::note_thread_warning_in_fun)
+ << CurrentFunction->getNameAsString());
+ ONS.push_back(FNote);
+ }
+ return ONS;
+ }
+
+ OptionalNotes getNotes(const PartialDiagnosticAt &Note1,
+ const PartialDiagnosticAt &Note2) const {
+ OptionalNotes ONS;
+ ONS.push_back(Note1);
+ ONS.push_back(Note2);
+ if (Verbose && CurrentFunction) {
+ PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(),
+ S.PDiag(diag::note_thread_warning_in_fun)
+ << CurrentFunction->getNameAsString());
+ ONS.push_back(FNote);
+ }
+ return ONS;
+ }
+
// Helper functions
void warnLockMismatch(unsigned DiagID, StringRef Kind, Name LockName,
SourceLocation Loc) {
@@ -1459,12 +1490,15 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
if (!Loc.isValid())
Loc = FunLocation;
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind << LockName);
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ Warnings.push_back(DelayedDiag(Warning, getNotes()));
}
public:
ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL)
- : S(S), FunLocation(FL), FunEndLocation(FEL) {}
+ : S(S), FunLocation(FL), FunEndLocation(FEL),
+ CurrentFunction(nullptr), Verbose(false) {}
+
+ void setVerbose(bool b) { Verbose = b; }
/// \brief Emit all buffered diagnostics in order of sourcelocation.
/// We need to output diagnostics produced while iterating through
@@ -1482,12 +1516,14 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
void handleInvalidLockExp(StringRef Kind, SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_cannot_resolve_lock)
<< Loc);
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ Warnings.push_back(DelayedDiag(Warning, getNotes()));
}
+
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 {
@@ -1496,8 +1532,9 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unlock_kind_mismatch)
<< Kind << LockName << Received
<< Expected);
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ Warnings.push_back(DelayedDiag(Warning, getNotes()));
}
+
void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation Loc) override {
warnLockMismatch(diag::warn_double_lock, Kind, LockName, Loc);
}
@@ -1529,10 +1566,10 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
if (LocLocked.isValid()) {
PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here)
<< Kind);
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
+ Warnings.push_back(DelayedDiag(Warning, getNotes(Note)));
return;
}
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ Warnings.push_back(DelayedDiag(Warning, getNotes()));
}
void handleExclusiveAndShared(StringRef Kind, Name LockName,
@@ -1543,7 +1580,7 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
<< Kind << LockName);
PartialDiagnosticAt Note(Loc2, S.PDiag(diag::note_lock_exclusive_and_shared)
<< Kind << LockName);
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
+ Warnings.push_back(DelayedDiag(Warning, getNotes(Note)));
}
void handleNoMutexHeld(StringRef Kind, const NamedDecl *D,
@@ -1556,7 +1593,7 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
diag::warn_var_deref_requires_any_lock;
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
<< D->getNameAsString() << getLockKindFromAccessKind(AK));
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ Warnings.push_back(DelayedDiag(Warning, getNotes()));
}
void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
@@ -1575,13 +1612,25 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
case POK_FunctionCall:
DiagID = diag::warn_fun_requires_lock_precise;
break;
+ case POK_PassByRef:
+ DiagID = diag::warn_guarded_pass_by_reference;
+ break;
+ case POK_PtPassByRef:
+ DiagID = diag::warn_pt_guarded_pass_by_reference;
+ break;
}
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
<< D->getNameAsString()
<< LockName << LK);
PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match)
<< *PossibleMatch);
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
+ if (Verbose && POK == POK_VarAccess) {
+ PartialDiagnosticAt VNote(D->getLocation(),
+ S.PDiag(diag::note_guarded_by_declared_here)
+ << D->getNameAsString());
+ Warnings.push_back(DelayedDiag(Warning, getNotes(Note, VNote)));
+ } else
+ Warnings.push_back(DelayedDiag(Warning, getNotes(Note)));
} else {
switch (POK) {
case POK_VarAccess:
@@ -1593,22 +1642,52 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
case POK_FunctionCall:
DiagID = diag::warn_fun_requires_lock;
break;
+ case POK_PassByRef:
+ DiagID = diag::warn_guarded_pass_by_reference;
+ break;
+ case POK_PtPassByRef:
+ DiagID = diag::warn_pt_guarded_pass_by_reference;
+ break;
}
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind
<< D->getNameAsString()
<< LockName << LK);
- Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+ if (Verbose && POK == POK_VarAccess) {
+ PartialDiagnosticAt Note(D->getLocation(),
+ S.PDiag(diag::note_guarded_by_declared_here)
+ << D->getNameAsString());
+ Warnings.push_back(DelayedDiag(Warning, getNotes(Note)));
+ } else
+ Warnings.push_back(DelayedDiag(Warning, getNotes()));
}
}
+
+ virtual void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
+ SourceLocation Loc) override {
+ PartialDiagnosticAt Warning(Loc,
+ S.PDiag(diag::warn_acquire_requires_negative_cap)
+ << Kind << LockName << Neg);
+ Warnings.push_back(DelayedDiag(Warning, getNotes()));
+ }
+
+
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()));
+ Warnings.push_back(DelayedDiag(Warning, getNotes()));
+ }
+
+ void enterFunction(const FunctionDecl* FD) override {
+ CurrentFunction = FD;
+ }
+
+ void leaveFunction(const FunctionDecl* FD) override {
+ CurrentFunction = 0;
}
};
-}
+
}
}
@@ -1896,11 +1975,13 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
if (P.enableThreadSafetyAnalysis) {
SourceLocation FL = AC.getDecl()->getLocation();
SourceLocation FEL = AC.getDecl()->getLocEnd();
- thread_safety::ThreadSafetyReporter Reporter(S, FL, FEL);
+ threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL);
if (!Diags.isIgnored(diag::warn_thread_safety_beta, D->getLocStart()))
Reporter.setIssueBetaWarnings(true);
+ if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getLocStart()))
+ Reporter.setVerbose(true);
- thread_safety::runThreadSafetyAnalysis(AC, Reporter);
+ threadSafety::runThreadSafetyAnalysis(AC, Reporter);
Reporter.emitDiagnostics();
}
diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp
index 476a22b628ad..34af6cf63c87 100644
--- a/lib/Sema/AttributeList.cpp
+++ b/lib/Sema/AttributeList.cpp
@@ -206,3 +206,11 @@ bool AttributeList::isKnownToGCC() const {
unsigned AttributeList::getSemanticSpelling() const {
return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
}
+
+bool AttributeList::hasVariadicArg() const {
+ // If the attribute has the maximum number of optional arguments, we will
+ // claim that as being variadic. If we someday get an attribute that
+ // legitimately bumps up against that maximum, we can use another bit to track
+ // whether it's truly variadic or not.
+ return getInfo(*this).OptArgs == 15;
+}
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 7847d2c36e5b..4a772d8972a9 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangSema
SemaChecking.cpp
SemaCodeComplete.cpp
SemaConsumer.cpp
+ SemaCUDA.cpp
SemaDecl.cpp
SemaDeclAttr.cpp
SemaDeclCXX.cpp
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index d7372b7a2768..7bf3e51999b6 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
#include "clang/Sema/LocInfoType.h"
@@ -113,6 +114,18 @@ void CXXScopeSpec::MakeGlobal(ASTContext &Context,
"NestedNameSpecifierLoc range computation incorrect");
}
+void CXXScopeSpec::MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
+ SourceLocation SuperLoc,
+ SourceLocation ColonColonLoc) {
+ Builder.MakeSuper(Context, RD, SuperLoc, ColonColonLoc);
+
+ Range.setBegin(SuperLoc);
+ Range.setEnd(ColonColonLoc);
+
+ assert(Range == Builder.getSourceRange() &&
+ "NestedNameSpecifierLoc range computation incorrect");
+}
+
void CXXScopeSpec::MakeTrivial(ASTContext &Context,
NestedNameSpecifier *Qualifier, SourceRange R) {
Builder.MakeTrivial(Context, Qualifier, R);
@@ -159,6 +172,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
SourceLocation ConstQualifierLoc,
SourceLocation
VolatileQualifierLoc,
+ SourceLocation
+ RestrictQualifierLoc,
SourceLocation MutableLoc,
ExceptionSpecificationType
ESpecType,
@@ -167,6 +182,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
Expr *NoexceptExpr,
+ CachedTokens *ExceptionSpecTokens,
SourceLocation LocalRangeBegin,
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
@@ -193,6 +209,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
I.Fun.ConstQualifierLoc = ConstQualifierLoc.getRawEncoding();
I.Fun.VolatileQualifierLoc = VolatileQualifierLoc.getRawEncoding();
+ I.Fun.RestrictQualifierLoc = RestrictQualifierLoc.getRawEncoding();
I.Fun.MutableLoc = MutableLoc.getRawEncoding();
I.Fun.ExceptionSpecType = ESpecType;
I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding();
@@ -203,6 +220,9 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
TrailingReturnType.isInvalid();
I.Fun.TrailingReturnType = TrailingReturnType.get();
+ assert(I.Fun.TypeQuals == TypeQuals && "bitfield overflow");
+ assert(I.Fun.ExceptionSpecType == ESpecType && "bitfield overflow");
+
// new[] a parameter array if needed.
if (NumParams) {
// If the 'InlineParams' in Declarator is unused and big enough, put our
@@ -239,6 +259,10 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
case EST_ComputedNoexcept:
I.Fun.NoexceptExpr = NoexceptExpr;
break;
+
+ case EST_Unparsed:
+ I.Fun.ExceptionSpecTokens = ExceptionSpecTokens;
+ break;
}
return I;
}
@@ -484,14 +508,14 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
case SCS_private_extern:
case SCS_static:
if (S.getLangOpts().OpenCLVersion < 120) {
- DiagID = diag::err_not_opencl_storage_class_specifier;
+ DiagID = diag::err_opencl_unknown_type_specifier;
PrevSpec = getSpecifierName(SC);
return true;
}
break;
case SCS_auto:
case SCS_register:
- DiagID = diag::err_not_opencl_storage_class_specifier;
+ DiagID = diag::err_opencl_unknown_type_specifier;
PrevSpec = getSpecifierName(SC);
return true;
default:
@@ -553,12 +577,6 @@ bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
else if (W != TSW_longlong || TypeSpecWidth != TSW_long)
return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
TypeSpecWidth = W;
- if (TypeAltiVecVector && !TypeAltiVecBool &&
- ((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
- DiagID = diag::warn_vector_long_decl_spec_combination;
- return true;
- }
return false;
}
@@ -680,11 +698,6 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
}
TypeSpecType = T;
TypeSpecOwned = false;
- if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) {
- PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
- DiagID = diag::err_invalid_vector_decl_spec;
- return true;
- }
return false;
}
@@ -978,6 +991,16 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) ||
(TypeSpecWidth != TSW_unspecified))
TypeSpecSign = TSS_unsigned;
+ } else if (TypeSpecType == TST_double) {
+ // vector long double and vector long long double are never allowed.
+ // vector double is OK for Power7 and later.
+ if (TypeSpecWidth == TSW_long || TypeSpecWidth == TSW_longlong)
+ Diag(D, TSWLoc, diag::err_invalid_vector_long_double_decl_spec);
+ else if (!PP.getTargetInfo().hasFeature("vsx"))
+ Diag(D, TSTLoc, diag::err_invalid_vector_double_decl_spec);
+ } else if (TypeSpecWidth == TSW_long) {
+ Diag(D, TSWLoc, diag::warn_vector_long_decl_spec_combination)
+ << getSpecifierName((TST)TypeSpecType, Policy);
}
if (TypeAltiVecPixel) {
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index 2a5bacff0d93..6586fb32787c 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -130,6 +130,9 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S,
return false;
}
+ // FIXME: If D is a local extern declaration, this check doesn't make sense;
+ // we should be checking its lexical context instead in that case, because
+ // that is its scope.
DeclContext *DCtx = D->getDeclContext()->getRedeclContext();
return AllowInlineNamespace ? Ctx->InEnclosingNamespaceSetOf(DCtx)
: Ctx->Equals(DCtx);
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index 255845282dfa..fd75c02bb1ed 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -84,6 +84,7 @@ private:
void CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
unsigned JumpDiag, unsigned JumpDiagWarning,
unsigned JumpDiagCXX98Compat);
+ void CheckGotoStmt(GotoStmt *GS);
unsigned GetDeepestCommonScope(unsigned A, unsigned B);
};
@@ -489,10 +490,14 @@ void JumpScopeChecker::VerifyJumps() {
// With a goto,
if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
- CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
- diag::err_goto_into_protected_scope,
- diag::ext_goto_into_protected_scope,
- diag::warn_cxx98_compat_goto_into_protected_scope);
+ // The label may not have a statement if it's coming from inline MS ASM.
+ if (GS->getLabel()->getStmt()) {
+ CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
+ diag::err_goto_into_protected_scope,
+ diag::ext_goto_into_protected_scope,
+ diag::warn_cxx98_compat_goto_into_protected_scope);
+ }
+ CheckGotoStmt(GS);
continue;
}
@@ -789,6 +794,15 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
}
}
+void JumpScopeChecker::CheckGotoStmt(GotoStmt *GS) {
+ if (GS->getLabel()->isMSAsmLabel()) {
+ S.Diag(GS->getGotoLoc(), diag::err_goto_ms_asm_label)
+ << GS->getLabel()->getIdentifier();
+ S.Diag(GS->getLabel()->getLocation(), diag::note_goto_ms_asm_label)
+ << GS->getLabel()->getIdentifier();
+ }
+}
+
void Sema::DiagnoseInvalidJumps(Stmt *Body) {
(void)JumpScopeChecker(Body, *this);
}
diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp
index 97237dbf097d..449ddf43114d 100644
--- a/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -242,6 +242,12 @@ void MultiplexExternalSemaSource::ReadDynamicClasses(
Sources[i]->ReadDynamicClasses(Decls);
}
+void MultiplexExternalSemaSource::ReadUnusedLocalTypedefNameCandidates(
+ llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {
+ for(size_t i = 0; i < Sources.size(); ++i)
+ Sources[i]->ReadUnusedLocalTypedefNameCandidates(Decls);
+}
+
void MultiplexExternalSemaSource::ReadLocallyScopedExternCDecls(
SmallVectorImpl<NamedDecl*> &Decls) {
for(size_t i = 0; i < Sources.size(); ++i)
diff --git a/lib/Sema/Scope.cpp b/lib/Sema/Scope.cpp
index 35e2075b3826..6c7977882386 100644
--- a/lib/Sema/Scope.cpp
+++ b/lib/Sema/Scope.cpp
@@ -39,9 +39,6 @@ void Scope::Init(Scope *parent, unsigned flags) {
BlockParent = parent->BlockParent;
TemplateParamParent = parent->TemplateParamParent;
MSLocalManglingParent = parent->MSLocalManglingParent;
- SEHTryParent = parent->SEHTryParent;
- if (parent->Flags & SEHTryScope)
- SEHTryParent = parent;
if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope |
FunctionPrototypeScope | AtCatchScope | ObjCMethodScope)) ==
0)
@@ -50,17 +47,13 @@ void Scope::Init(Scope *parent, unsigned flags) {
Depth = 0;
PrototypeDepth = 0;
PrototypeIndex = 0;
- SEHTryParent = MSLocalManglingParent = FnParent = BlockParent = nullptr;
+ MSLocalManglingParent = FnParent = BlockParent = nullptr;
TemplateParamParent = nullptr;
MSLocalManglingNumber = 1;
}
// If this scope is a function or contains breaks/continues, remember it.
if (flags & FnScope) FnParent = this;
- SEHTryIndexPool = 0;
- SEHTryIndex = -1;
- if (flags & SEHTryScope)
- SEHTryIndex = FnParent ? FnParent->SEHTryIndexPool++ : -1;
// The MS mangler uses the number of scopes that can hold declarations as
// part of an external name.
if (Flags & (ClassScope | FnScope)) {
diff --git a/lib/Sema/ScopeInfo.cpp b/lib/Sema/ScopeInfo.cpp
index 4d079e705f62..63ef3b2355fb 100644
--- a/lib/Sema/ScopeInfo.cpp
+++ b/lib/Sema/ScopeInfo.cpp
@@ -14,6 +14,7 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
@@ -38,6 +39,7 @@ void FunctionScopeInfo::Clear() {
ErrorTrap.reset();
PossiblyUnreachableDiags.clear();
WeakObjectUses.clear();
+ ModifiedNonNullParams.clear();
}
static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) {
@@ -93,6 +95,21 @@ FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) {
return BaseInfoTy(D, IsExact);
}
+bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const {
+ RecordDecl *RD = nullptr;
+ if (auto *LSI = dyn_cast<LambdaScopeInfo>(this))
+ RD = LSI->Lambda;
+ else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(this))
+ RD = CRSI->TheRecordDecl;
+
+ if (RD)
+ for (auto *FD : RD->fields()) {
+ if (FD->hasCapturedVLAType() && FD->getCapturedVLAType() == VAT)
+ return true;
+ }
+ return false;
+}
+
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
const ObjCPropertyRefExpr *PropE)
: Base(nullptr, true), Property(getBestPropertyDecl(PropE)) {
@@ -159,6 +176,8 @@ void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
// Has this weak object been seen before?
FunctionScopeInfo::WeakObjectUseMap::iterator Uses;
if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) {
+ if (!RefExpr->isObjectReceiver())
+ return;
if (isa<OpaqueValueExpr>(RefExpr->getBase()))
Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr));
else {
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 2c653325b37b..b9aaf1616d68 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -69,8 +69,6 @@ PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
void Sema::ActOnTranslationUnitScope(Scope *S) {
TUScope = S;
PushDeclContext(S, Context.getTranslationUnitDecl());
-
- VAListTagName = PP.getIdentifierInfo("__va_list_tag");
}
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
@@ -90,12 +88,14 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
CodeSegStack(nullptr), CurInitSeg(nullptr), VisContext(nullptr),
IsBuildingRecoveryCallExpr(false),
ExprNeedsCleanups(false), LateTemplateParser(nullptr),
+ LateTemplateParserCleanup(nullptr),
OpaqueParser(nullptr), IdResolver(pp), StdInitializerList(nullptr),
CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr),
NSNumberDecl(nullptr),
NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),
NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr),
NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr),
+ MSAsmLabelNameCounter(0),
GlobalNewDeleteDeclared(false),
TUKind(TUKind),
NumSFINAEErrors(0),
@@ -151,6 +151,10 @@ void Sema::Initialize() {
= dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
ExternalSema->InitializeSema(*this);
+ // This needs to happen after ExternalSemaSource::InitializeSema(this) or we
+ // will not be able to merge any duplicate __va_list_tag decls correctly.
+ VAListTagName = PP.getIdentifierInfo("__va_list_tag");
+
// Initialize predefined 128-bit integer types, if needed.
if (Context.getTargetInfo().hasInt128Type()) {
// If either of the 128-bit integer types are unavailable to name lookup,
@@ -241,6 +245,8 @@ Sema::~Sema() {
// Destroys data sharing attributes stack for OpenMP
DestroyDataSharingAttributesStack();
+
+ assert(DelayedTypos.empty() && "Uncorrected typos!");
}
/// makeUnavailableInSystemHeader - There is an error in the current
@@ -538,7 +544,12 @@ static bool MethodsAndNestedClassesComplete(const CXXRecordDecl *RD,
if (const CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(*I))
Complete = M->isDefined() || (M->isPure() && !isa<CXXDestructorDecl>(M));
else if (const FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(*I))
- Complete = F->getTemplatedDecl()->isDefined();
+ // If the template function is marked as late template parsed at this point,
+ // it has not been instantiated and therefore we have not performed semantic
+ // analysis on it yet, so we cannot know if the type can be considered
+ // complete.
+ Complete = !F->getTemplatedDecl()->isLateTemplateParsed() &&
+ F->getTemplatedDecl()->isDefined();
else if (const CXXRecordDecl *R = dyn_cast<CXXRecordDecl>(*I)) {
if (R->isInjectedClassName())
continue;
@@ -591,6 +602,19 @@ static bool IsRecordFullyDefined(const CXXRecordDecl *RD,
return Complete;
}
+void Sema::emitAndClearUnusedLocalTypedefWarnings() {
+ if (ExternalSource)
+ ExternalSource->ReadUnusedLocalTypedefNameCandidates(
+ UnusedLocalTypedefNameCandidates);
+ for (const TypedefNameDecl *TD : UnusedLocalTypedefNameCandidates) {
+ if (TD->isReferenced())
+ continue;
+ Diag(TD->getLocation(), diag::warn_unused_local_typedef)
+ << isa<TypeAliasDecl>(TD) << TD->getDeclName();
+ }
+ UnusedLocalTypedefNameCandidates.clear();
+}
+
/// ActOnEndOfTranslationUnit - This is called at the very end of the
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
@@ -647,13 +671,16 @@ void Sema::ActOnEndOfTranslationUnit() {
}
PerformPendingInstantiations();
+ if (LateTemplateParserCleanup)
+ LateTemplateParserCleanup(OpaqueParser);
+
CheckDelayedMemberExceptionSpecs();
}
// All delayed member exception specs should be checked or we end up accepting
// incompatible declarations.
assert(DelayedDefaultedMemberExceptionSpecs.empty());
- assert(DelayedDestructorExceptionSpecChecks.empty());
+ assert(DelayedExceptionSpecChecks.empty());
// Remove file scoped decls that turned out to be used.
UnusedFileScopedDecls.erase(
@@ -713,6 +740,10 @@ void Sema::ActOnEndOfTranslationUnit() {
}
}
+ // Warnings emitted in ActOnEndOfTranslationUnit() should be emitted for
+ // modules when they are built, not every time they are used.
+ emitAndClearUnusedLocalTypedefWarnings();
+
// Modules don't need any of the checking below.
TUScope = nullptr;
return;
@@ -740,7 +771,7 @@ void Sema::ActOnEndOfTranslationUnit() {
// If the tentative definition was completed, getActingDefinition() returns
// null. If we've already seen this variable before, insert()'s second
// return value is false.
- if (!VD || VD->isInvalidDecl() || !Seen.insert(VD))
+ if (!VD || VD->isInvalidDecl() || !Seen.insert(VD).second)
continue;
if (const IncompleteArrayType *ArrayT
@@ -788,8 +819,9 @@ void Sema::ActOnEndOfTranslationUnit() {
!FD->isInlineSpecified() &&
!SourceMgr.isInMainFile(
SourceMgr.getExpansionLoc(FD->getLocation())))
- Diag(DiagD->getLocation(), diag::warn_unneeded_static_internal_decl)
- << DiagD->getDeclName();
+ Diag(DiagD->getLocation(),
+ diag::warn_unneeded_static_internal_decl)
+ << DiagD->getDeclName();
else
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
<< /*function*/0 << DiagD->getDeclName();
@@ -820,6 +852,8 @@ void Sema::ActOnEndOfTranslationUnit() {
if (ExternalSource)
ExternalSource->ReadUndefinedButUsed(UndefinedButUsed);
checkUndefinedButUsed(*this);
+
+ emitAndClearUnusedLocalTypedefWarnings();
}
if (!Diags.isIgnored(diag::warn_unused_private_field, SourceLocation())) {
@@ -1432,8 +1466,8 @@ IdentifierInfo *Sema::getFloat128Identifier() const {
void Sema::PushCapturedRegionScope(Scope *S, CapturedDecl *CD, RecordDecl *RD,
CapturedRegionKind K) {
- CapturingScopeInfo *CSI = new CapturedRegionScopeInfo(getDiagnostics(), S, CD, RD,
- CD->getContextParam(), K);
+ CapturingScopeInfo *CSI = new CapturedRegionScopeInfo(
+ getDiagnostics(), S, CD, RD, CD->getContextParam(), K);
CSI->ReturnType = Context.VoidTy;
FunctionScopes.push_back(CSI);
}
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index ffdb0aa27a6b..37240c23b691 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -1749,14 +1749,14 @@ Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) {
return AR_accessible;
CXXMethodDecl *method = cast<CXXMethodDecl>(target->getAsFunction());
- assert(method->getQualifier());
AccessTarget entity(Context, AccessTarget::Member,
cast<CXXRecordDecl>(target->getDeclContext()),
DeclAccessPair::make(target, access),
/*no instance context*/ QualType());
entity.setDiag(diag::err_access_friend_function)
- << method->getQualifierLoc().getSourceRange();
+ << (method->getQualifier() ? method->getQualifierLoc().getSourceRange()
+ : method->getNameInfo().getSourceRange());
// We need to bypass delayed-diagnostics because we might be called
// while the ParsingDeclarator is active.
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index a7d606d545ca..76297977ea0e 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -360,18 +360,18 @@ void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation,
}
}
-bool Sema::UnifySection(const StringRef &SectionName,
+bool Sema::UnifySection(StringRef SectionName,
int SectionFlags,
DeclaratorDecl *Decl) {
- auto Section = SectionInfos.find(SectionName);
- if (Section == SectionInfos.end()) {
- SectionInfos[SectionName] =
- SectionInfo(Decl, SourceLocation(), SectionFlags);
+ auto Section = Context.SectionInfos.find(SectionName);
+ if (Section == Context.SectionInfos.end()) {
+ Context.SectionInfos[SectionName] =
+ ASTContext::SectionInfo(Decl, SourceLocation(), SectionFlags);
return false;
}
// A pre-declared section takes precedence w/o diagnostic.
if (Section->second.SectionFlags == SectionFlags ||
- !(Section->second.SectionFlags & PSF_Implicit))
+ !(Section->second.SectionFlags & ASTContext::PSF_Implicit))
return false;
auto OtherDecl = Section->second.Decl;
Diag(Decl->getLocation(), diag::err_section_conflict)
@@ -384,17 +384,17 @@ bool Sema::UnifySection(const StringRef &SectionName,
if (auto A = OtherDecl->getAttr<SectionAttr>())
if (A->isImplicit())
Diag(A->getLocation(), diag::note_pragma_entered_here);
- return false;
+ return true;
}
-bool Sema::UnifySection(const StringRef &SectionName,
+bool Sema::UnifySection(StringRef SectionName,
int SectionFlags,
SourceLocation PragmaSectionLocation) {
- auto Section = SectionInfos.find(SectionName);
- if (Section != SectionInfos.end()) {
+ auto Section = Context.SectionInfos.find(SectionName);
+ if (Section != Context.SectionInfos.end()) {
if (Section->second.SectionFlags == SectionFlags)
return false;
- if (!(Section->second.SectionFlags & PSF_Implicit)) {
+ if (!(Section->second.SectionFlags & ASTContext::PSF_Implicit)) {
Diag(PragmaSectionLocation, diag::err_section_conflict)
<< "this" << "a prior #pragma section";
Diag(Section->second.PragmaSectionLocation,
@@ -402,8 +402,8 @@ bool Sema::UnifySection(const StringRef &SectionName,
return true;
}
}
- SectionInfos[SectionName] =
- SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);
+ Context.SectionInfos[SectionName] =
+ ASTContext::SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);
return false;
}
diff --git a/lib/Sema/SemaCUDA.cpp b/lib/Sema/SemaCUDA.cpp
new file mode 100644
index 000000000000..64222fbf8ac8
--- /dev/null
+++ b/lib/Sema/SemaCUDA.cpp
@@ -0,0 +1,263 @@
+//===--- SemaCUDA.cpp - Semantic Analysis for CUDA constructs -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief This file implements semantic analysis for CUDA constructs.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/Sema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+using namespace clang;
+
+ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
+ MultiExprArg ExecConfig,
+ SourceLocation GGGLoc) {
+ FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl();
+ if (!ConfigDecl)
+ return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)
+ << "cudaConfigureCall");
+ QualType ConfigQTy = ConfigDecl->getType();
+
+ DeclRefExpr *ConfigDR = new (Context)
+ DeclRefExpr(ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc);
+ MarkFunctionReferenced(LLLLoc, ConfigDecl);
+
+ return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr,
+ /*IsExecConfig=*/true);
+}
+
+/// IdentifyCUDATarget - Determine the CUDA compilation target for this function
+Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
+ if (D->hasAttr<CUDAInvalidTargetAttr>())
+ return CFT_InvalidTarget;
+
+ if (D->hasAttr<CUDAGlobalAttr>())
+ return CFT_Global;
+
+ if (D->hasAttr<CUDADeviceAttr>()) {
+ if (D->hasAttr<CUDAHostAttr>())
+ return CFT_HostDevice;
+ return CFT_Device;
+ } else if (D->hasAttr<CUDAHostAttr>()) {
+ return CFT_Host;
+ } else if (D->isImplicit()) {
+ // Some implicit declarations (like intrinsic functions) are not marked.
+ // Set the most lenient target on them for maximal flexibility.
+ return CFT_HostDevice;
+ }
+
+ return CFT_Host;
+}
+
+bool Sema::CheckCUDATarget(const FunctionDecl *Caller,
+ const FunctionDecl *Callee) {
+ CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller),
+ CalleeTarget = IdentifyCUDATarget(Callee);
+
+ // If one of the targets is invalid, the check always fails, no matter what
+ // the other target is.
+ if (CallerTarget == CFT_InvalidTarget || CalleeTarget == CFT_InvalidTarget)
+ return true;
+
+ // CUDA B.1.1 "The __device__ qualifier declares a function that is [...]
+ // Callable from the device only."
+ if (CallerTarget == CFT_Host && CalleeTarget == CFT_Device)
+ return true;
+
+ // CUDA B.1.2 "The __global__ qualifier declares a function that is [...]
+ // Callable from the host only."
+ // CUDA B.1.3 "The __host__ qualifier declares a function that is [...]
+ // Callable from the host only."
+ if ((CallerTarget == CFT_Device || CallerTarget == CFT_Global) &&
+ (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global))
+ return true;
+
+ // CUDA B.1.3 "The __device__ and __host__ qualifiers can be used together
+ // however, in which case the function is compiled for both the host and the
+ // device. The __CUDA_ARCH__ macro [...] can be used to differentiate code
+ // paths between host and device."
+ if (CallerTarget == CFT_HostDevice && CalleeTarget != CFT_HostDevice) {
+ // If the caller is implicit then the check always passes.
+ if (Caller->isImplicit()) return false;
+
+ bool InDeviceMode = getLangOpts().CUDAIsDevice;
+ if ((InDeviceMode && CalleeTarget != CFT_Device) ||
+ (!InDeviceMode && CalleeTarget != CFT_Host))
+ return true;
+ }
+
+ return false;
+}
+
+/// When an implicitly-declared special member has to invoke more than one
+/// base/field special member, conflicts may occur in the targets of these
+/// members. For example, if one base's member __host__ and another's is
+/// __device__, it's a conflict.
+/// This function figures out if the given targets \param Target1 and
+/// \param Target2 conflict, and if they do not it fills in
+/// \param ResolvedTarget with a target that resolves for both calls.
+/// \return true if there's a conflict, false otherwise.
+static bool
+resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1,
+ Sema::CUDAFunctionTarget Target2,
+ Sema::CUDAFunctionTarget *ResolvedTarget) {
+ if (Target1 == Sema::CFT_Global && Target2 == Sema::CFT_Global) {
+ // TODO: this shouldn't happen, really. Methods cannot be marked __global__.
+ // Clang should detect this earlier and produce an error. Then this
+ // condition can be changed to an assertion.
+ return true;
+ }
+
+ if (Target1 == Sema::CFT_HostDevice) {
+ *ResolvedTarget = Target2;
+ } else if (Target2 == Sema::CFT_HostDevice) {
+ *ResolvedTarget = Target1;
+ } else if (Target1 != Target2) {
+ return true;
+ } else {
+ *ResolvedTarget = Target1;
+ }
+
+ return false;
+}
+
+bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl,
+ CXXSpecialMember CSM,
+ CXXMethodDecl *MemberDecl,
+ bool ConstRHS,
+ bool Diagnose) {
+ llvm::Optional<CUDAFunctionTarget> InferredTarget;
+
+ // We're going to invoke special member lookup; mark that these special
+ // members are called from this one, and not from its caller.
+ ContextRAII MethodContext(*this, MemberDecl);
+
+ // Look for special members in base classes that should be invoked from here.
+ // Infer the target of this member base on the ones it should call.
+ // Skip direct and indirect virtual bases for abstract classes.
+ llvm::SmallVector<const CXXBaseSpecifier *, 16> Bases;
+ for (const auto &B : ClassDecl->bases()) {
+ if (!B.isVirtual()) {
+ Bases.push_back(&B);
+ }
+ }
+
+ if (!ClassDecl->isAbstract()) {
+ for (const auto &VB : ClassDecl->vbases()) {
+ Bases.push_back(&VB);
+ }
+ }
+
+ for (const auto *B : Bases) {
+ const RecordType *BaseType = B->getType()->getAs<RecordType>();
+ if (!BaseType) {
+ continue;
+ }
+
+ CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+ Sema::SpecialMemberOverloadResult *SMOR =
+ LookupSpecialMember(BaseClassDecl, CSM,
+ /* ConstArg */ ConstRHS,
+ /* VolatileArg */ false,
+ /* RValueThis */ false,
+ /* ConstThis */ false,
+ /* VolatileThis */ false);
+
+ if (!SMOR || !SMOR->getMethod()) {
+ continue;
+ }
+
+ CUDAFunctionTarget BaseMethodTarget = IdentifyCUDATarget(SMOR->getMethod());
+ if (!InferredTarget.hasValue()) {
+ InferredTarget = BaseMethodTarget;
+ } else {
+ bool ResolutionError = resolveCalleeCUDATargetConflict(
+ InferredTarget.getValue(), BaseMethodTarget,
+ InferredTarget.getPointer());
+ if (ResolutionError) {
+ if (Diagnose) {
+ Diag(ClassDecl->getLocation(),
+ diag::note_implicit_member_target_infer_collision)
+ << (unsigned)CSM << InferredTarget.getValue() << BaseMethodTarget;
+ }
+ MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context));
+ return true;
+ }
+ }
+ }
+
+ // Same as for bases, but now for special members of fields.
+ for (const auto *F : ClassDecl->fields()) {
+ if (F->isInvalidDecl()) {
+ continue;
+ }
+
+ const RecordType *FieldType =
+ Context.getBaseElementType(F->getType())->getAs<RecordType>();
+ if (!FieldType) {
+ continue;
+ }
+
+ CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(FieldType->getDecl());
+ Sema::SpecialMemberOverloadResult *SMOR =
+ LookupSpecialMember(FieldRecDecl, CSM,
+ /* ConstArg */ ConstRHS && !F->isMutable(),
+ /* VolatileArg */ false,
+ /* RValueThis */ false,
+ /* ConstThis */ false,
+ /* VolatileThis */ false);
+
+ if (!SMOR || !SMOR->getMethod()) {
+ continue;
+ }
+
+ CUDAFunctionTarget FieldMethodTarget =
+ IdentifyCUDATarget(SMOR->getMethod());
+ if (!InferredTarget.hasValue()) {
+ InferredTarget = FieldMethodTarget;
+ } else {
+ bool ResolutionError = resolveCalleeCUDATargetConflict(
+ InferredTarget.getValue(), FieldMethodTarget,
+ InferredTarget.getPointer());
+ if (ResolutionError) {
+ if (Diagnose) {
+ Diag(ClassDecl->getLocation(),
+ diag::note_implicit_member_target_infer_collision)
+ << (unsigned)CSM << InferredTarget.getValue()
+ << FieldMethodTarget;
+ }
+ MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context));
+ return true;
+ }
+ }
+ }
+
+ if (InferredTarget.hasValue()) {
+ if (InferredTarget.getValue() == CFT_Device) {
+ MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
+ } else if (InferredTarget.getValue() == CFT_Host) {
+ MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
+ } else {
+ MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
+ MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
+ }
+ } else {
+ // If no target was inferred, mark this member as __host__ __device__;
+ // it's the least restrictive option that can be invoked from any target.
+ MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context));
+ MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context));
+ }
+
+ return false;
+}
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index a70aca2ad86a..3e56e676a15c 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -148,6 +148,9 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
case NestedNameSpecifier::Global:
return Context.getTranslationUnitDecl();
+
+ case NestedNameSpecifier::Super:
+ return NNS->getAsRecordDecl();
}
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
@@ -240,12 +243,43 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
return true;
}
-bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
+bool Sema::ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc,
CXXScopeSpec &SS) {
SS.MakeGlobal(Context, CCLoc);
return false;
}
+bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
+ SourceLocation ColonColonLoc,
+ CXXScopeSpec &SS) {
+ CXXRecordDecl *RD = nullptr;
+ for (Scope *S = getCurScope(); S; S = S->getParent()) {
+ if (S->isFunctionScope()) {
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(S->getEntity()))
+ RD = MD->getParent();
+ break;
+ }
+ if (S->isClassScope()) {
+ RD = cast<CXXRecordDecl>(S->getEntity());
+ break;
+ }
+ }
+
+ if (!RD) {
+ Diag(SuperLoc, diag::err_invalid_super_scope);
+ return true;
+ } else if (RD->isLambda()) {
+ Diag(SuperLoc, diag::err_super_in_lambda_unsupported);
+ return true;
+ } else if (RD->getNumBases() == 0) {
+ Diag(SuperLoc, diag::err_no_base_classes) << RD->getName();
+ return true;
+ }
+
+ SS.MakeSuper(Context, RD, SuperLoc, ColonColonLoc);
+ return false;
+}
+
/// \brief Determines whether the given declaration is an valid acceptable
/// result for name lookup of a nested-name-specifier.
bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD) {
@@ -376,9 +410,6 @@ class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback {
/// \brief Build a new nested-name-specifier for "identifier::", as described
/// by ActOnCXXNestedNameSpecifier.
///
-/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in
-/// that it contains an extra parameter \p ScopeLookupResult.
-///
/// \param S Scope in which the nested-name-specifier occurs.
/// \param Identifier Identifier in the sequence "identifier" "::".
/// \param IdentifierLoc Location of the \p Identifier.
@@ -541,12 +572,11 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
// We haven't found anything, and we're not recovering from a
// different kind of error, so look for typos.
DeclarationName Name = Found.getLookupName();
- NestedNameSpecifierValidatorCCC Validator(*this);
Found.clear();
- if (TypoCorrection Corrected =
- CorrectTypo(Found.getLookupNameInfo(), Found.getLookupKind(), S,
- &SS, Validator, CTK_ErrorRecovery, LookupCtx,
- EnteringContext)) {
+ if (TypoCorrection Corrected = CorrectTypo(
+ Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS,
+ llvm::make_unique<NestedNameSpecifierValidatorCCC>(*this),
+ CTK_ErrorRecovery, LookupCtx, EnteringContext)) {
if (LookupCtx) {
bool DroppedSpecifier =
Corrected.WillReplaceSpecifier() &&
@@ -612,10 +642,17 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
}
}
+ if (auto *TD = dyn_cast_or_null<TypedefNameDecl>(SD))
+ MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
+
// If we're just performing this lookup for error-recovery purposes,
// don't extend the nested-name-specifier. Just return now.
if (ErrorRecoveryLookup)
return false;
+
+ // The use of a nested name specifier may trigger deprecation warnings.
+ DiagnoseUseOfDecl(SD, CCLoc);
+
if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) {
SS.Extend(Context, Namespace, IdentifierLoc, CCLoc);
@@ -703,8 +740,13 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
if (getLangOpts().MSVCCompat) {
DeclContext *DC = LookupCtx ? LookupCtx : CurContext;
if (DC->isDependentContext() && DC->isFunctionOrMethod()) {
- SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
- return false;
+ CXXRecordDecl *ContainingClass = dyn_cast<CXXRecordDecl>(DC->getParent());
+ if (ContainingClass && ContainingClass->hasAnyDependentBases()) {
+ Diag(IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base)
+ << &Identifier << ContainingClass;
+ SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
+ return false;
+ }
}
}
@@ -945,6 +987,7 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::Super:
// These are never namespace scopes.
return true;
}
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index ae5436cf415c..a4c2d9b51c26 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/lib/Sema/SemaCast.cpp
@@ -142,9 +142,6 @@ namespace {
};
}
-static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
- bool CheckCVR, bool CheckObjCLifetime);
-
// The Try functions attempt a specific way of casting. If they succeed, they
// return TC_Success. If their way of casting is not appropriate for the given
// arguments, they return TC_NotApplicable and *may* set diag to a diagnostic
@@ -243,10 +240,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
QualType DestType = DestTInfo->getType();
// If the type is dependent, we won't do the semantic analysis now.
- // FIXME: should we check this in a more fine-grained manner?
- bool TypeDependent = DestType->isDependentType() ||
- Ex.get()->isTypeDependent() ||
- Ex.get()->isValueDependent();
+ bool TypeDependent =
+ DestType->isDependentType() || Ex.get()->isTypeDependent();
CastOperation Op(*this, DestType, E);
Op.OpRange = SourceRange(OpLoc, Parens.getEnd());
@@ -462,7 +457,10 @@ static bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) {
/// \param CheckObjCLifetime Whether to check Objective-C lifetime qualifiers.
static bool
CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
- bool CheckCVR, bool CheckObjCLifetime) {
+ bool CheckCVR, bool CheckObjCLifetime,
+ QualType *TheOffendingSrcType = nullptr,
+ QualType *TheOffendingDestType = nullptr,
+ Qualifiers *CastAwayQualifiers = nullptr) {
// If the only checking we care about is for Objective-C lifetime qualifiers,
// and we're not in ARC mode, there's nothing to check.
if (!CheckCVR && CheckObjCLifetime &&
@@ -487,6 +485,8 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
// Find the qualifiers. We only care about cvr-qualifiers for the
// purpose of this check, because other qualifiers (address spaces,
// Objective-C GC, etc.) are part of the type's identity.
+ QualType PrevUnwrappedSrcType = UnwrappedSrcType;
+ QualType PrevUnwrappedDestType = UnwrappedDestType;
while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
// Determine the relevant qualifiers at this level.
Qualifiers SrcQuals, DestQuals;
@@ -497,6 +497,13 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
if (CheckCVR) {
RetainedSrcQuals.setCVRQualifiers(SrcQuals.getCVRQualifiers());
RetainedDestQuals.setCVRQualifiers(DestQuals.getCVRQualifiers());
+
+ if (RetainedSrcQuals != RetainedDestQuals && TheOffendingSrcType &&
+ TheOffendingDestType && CastAwayQualifiers) {
+ *TheOffendingSrcType = PrevUnwrappedSrcType;
+ *TheOffendingDestType = PrevUnwrappedDestType;
+ *CastAwayQualifiers = RetainedSrcQuals - RetainedDestQuals;
+ }
}
if (CheckObjCLifetime &&
@@ -505,6 +512,9 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
cv1.push_back(RetainedSrcQuals);
cv2.push_back(RetainedDestQuals);
+
+ PrevUnwrappedSrcType = UnwrappedSrcType;
+ PrevUnwrappedDestType = UnwrappedDestType;
}
if (cv1.empty())
return false;
@@ -2200,8 +2210,8 @@ void CastOperation::CheckCStyleCast() {
// address space B is illegal.
if (Self.getLangOpts().OpenCL && DestType->isPointerType() &&
SrcType->isPointerType()) {
- if (DestType->getPointeeType().getAddressSpace() !=
- SrcType->getPointeeType().getAddressSpace()) {
+ const PointerType *DestPtr = DestType->getAs<PointerType>();
+ if (!DestPtr->isAddressSpaceOverlapping(*SrcType->getAs<PointerType>())) {
Self.Diag(OpRange.getBegin(),
diag::err_typecheck_incompatible_address_space)
<< SrcType << DestType << Sema::AA_Casting
@@ -2371,6 +2381,30 @@ void CastOperation::CheckCStyleCast() {
if (Kind == CK_BitCast)
checkCastAlign();
+
+ // -Wcast-qual
+ QualType TheOffendingSrcType, TheOffendingDestType;
+ Qualifiers CastAwayQualifiers;
+ if (SrcType->isAnyPointerType() && DestType->isAnyPointerType() &&
+ CastsAwayConstness(Self, SrcType, DestType, true, false,
+ &TheOffendingSrcType, &TheOffendingDestType,
+ &CastAwayQualifiers)) {
+ int qualifiers = -1;
+ if (CastAwayQualifiers.hasConst() && CastAwayQualifiers.hasVolatile()) {
+ qualifiers = 0;
+ } else if (CastAwayQualifiers.hasConst()) {
+ qualifiers = 1;
+ } else if (CastAwayQualifiers.hasVolatile()) {
+ qualifiers = 2;
+ }
+ // This is a variant of int **x; const int **y = (const int **)x;
+ if (qualifiers == -1)
+ Self.Diag(SrcExpr.get()->getLocStart(), diag::warn_cast_qual2) <<
+ SrcType << DestType;
+ else
+ Self.Diag(SrcExpr.get()->getLocStart(), diag::warn_cast_qual) <<
+ TheOffendingSrcType << TheOffendingDestType << qualifiers;
+ }
}
ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc,
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 66be962fcf33..9fc2bec23b1b 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -111,8 +111,100 @@ static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) {
return false;
}
+static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl,
+ CallExpr *TheCall, unsigned SizeIdx,
+ unsigned DstSizeIdx) {
+ if (TheCall->getNumArgs() <= SizeIdx ||
+ TheCall->getNumArgs() <= DstSizeIdx)
+ return;
+
+ const Expr *SizeArg = TheCall->getArg(SizeIdx);
+ const Expr *DstSizeArg = TheCall->getArg(DstSizeIdx);
+
+ llvm::APSInt Size, DstSize;
+
+ // find out if both sizes are known at compile time
+ if (!SizeArg->EvaluateAsInt(Size, S.Context) ||
+ !DstSizeArg->EvaluateAsInt(DstSize, S.Context))
+ return;
+
+ if (Size.ule(DstSize))
+ return;
+
+ // confirmed overflow so generate the diagnostic.
+ IdentifierInfo *FnName = FDecl->getIdentifier();
+ SourceLocation SL = TheCall->getLocStart();
+ SourceRange SR = TheCall->getSourceRange();
+
+ S.Diag(SL, diag::warn_memcpy_chk_overflow) << SR << FnName;
+}
+
+static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) {
+ if (checkArgCount(S, BuiltinCall, 2))
+ return true;
+
+ SourceLocation BuiltinLoc = BuiltinCall->getLocStart();
+ Expr *Builtin = BuiltinCall->getCallee()->IgnoreImpCasts();
+ Expr *Call = BuiltinCall->getArg(0);
+ Expr *Chain = BuiltinCall->getArg(1);
+
+ if (Call->getStmtClass() != Stmt::CallExprClass) {
+ S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_not_call)
+ << Call->getSourceRange();
+ return true;
+ }
+
+ auto CE = cast<CallExpr>(Call);
+ if (CE->getCallee()->getType()->isBlockPointerType()) {
+ S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_block_call)
+ << Call->getSourceRange();
+ return true;
+ }
+
+ const Decl *TargetDecl = CE->getCalleeDecl();
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl))
+ if (FD->getBuiltinID()) {
+ S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_builtin_call)
+ << Call->getSourceRange();
+ return true;
+ }
+
+ if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens())) {
+ S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_pdtor_call)
+ << Call->getSourceRange();
+ return true;
+ }
+
+ ExprResult ChainResult = S.UsualUnaryConversions(Chain);
+ if (ChainResult.isInvalid())
+ return true;
+ if (!ChainResult.get()->getType()->isPointerType()) {
+ S.Diag(BuiltinLoc, diag::err_second_argument_to_cwsc_not_pointer)
+ << Chain->getSourceRange();
+ return true;
+ }
+
+ QualType ReturnTy = CE->getCallReturnType();
+ QualType ArgTys[2] = { ReturnTy, ChainResult.get()->getType() };
+ QualType BuiltinTy = S.Context.getFunctionType(
+ ReturnTy, ArgTys, FunctionProtoType::ExtProtoInfo());
+ QualType BuiltinPtrTy = S.Context.getPointerType(BuiltinTy);
+
+ Builtin =
+ S.ImpCastExprToType(Builtin, BuiltinPtrTy, CK_BuiltinFnToFnPtr).get();
+
+ BuiltinCall->setType(CE->getType());
+ BuiltinCall->setValueKind(CE->getValueKind());
+ BuiltinCall->setObjectKind(CE->getObjectKind());
+ BuiltinCall->setCallee(Builtin);
+ BuiltinCall->setArg(1, ChainResult.get());
+
+ return false;
+}
+
ExprResult
-Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
+ CallExpr *TheCall) {
ExprResult TheCallResult(TheCall);
// Find out if any arguments are required to be integer constant expressions.
@@ -189,9 +281,14 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return ExprError();
break;
case Builtin::BI__assume:
+ case Builtin::BI__builtin_assume:
if (SemaBuiltinAssume(TheCall))
return ExprError();
break;
+ case Builtin::BI__builtin_assume_aligned:
+ if (SemaBuiltinAssumeAligned(TheCall))
+ return ExprError();
+ break;
case Builtin::BI__builtin_object_size:
if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3))
return ExprError();
@@ -239,6 +336,12 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Builtin::BI__sync_fetch_and_xor_4:
case Builtin::BI__sync_fetch_and_xor_8:
case Builtin::BI__sync_fetch_and_xor_16:
+ case Builtin::BI__sync_fetch_and_nand:
+ case Builtin::BI__sync_fetch_and_nand_1:
+ case Builtin::BI__sync_fetch_and_nand_2:
+ case Builtin::BI__sync_fetch_and_nand_4:
+ case Builtin::BI__sync_fetch_and_nand_8:
+ case Builtin::BI__sync_fetch_and_nand_16:
case Builtin::BI__sync_add_and_fetch:
case Builtin::BI__sync_add_and_fetch_1:
case Builtin::BI__sync_add_and_fetch_2:
@@ -269,6 +372,12 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Builtin::BI__sync_xor_and_fetch_4:
case Builtin::BI__sync_xor_and_fetch_8:
case Builtin::BI__sync_xor_and_fetch_16:
+ case Builtin::BI__sync_nand_and_fetch:
+ case Builtin::BI__sync_nand_and_fetch_1:
+ case Builtin::BI__sync_nand_and_fetch_2:
+ case Builtin::BI__sync_nand_and_fetch_4:
+ case Builtin::BI__sync_nand_and_fetch_8:
+ case Builtin::BI__sync_nand_and_fetch_16:
case Builtin::BI__sync_val_compare_and_swap:
case Builtin::BI__sync_val_compare_and_swap_1:
case Builtin::BI__sync_val_compare_and_swap_2:
@@ -327,6 +436,31 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
// so ensure that they are declared.
DeclareGlobalNewDelete();
break;
+
+ // check secure string manipulation functions where overflows
+ // are detectable at compile time
+ case Builtin::BI__builtin___memcpy_chk:
+ case Builtin::BI__builtin___memmove_chk:
+ case Builtin::BI__builtin___memset_chk:
+ case Builtin::BI__builtin___strlcat_chk:
+ case Builtin::BI__builtin___strlcpy_chk:
+ case Builtin::BI__builtin___strncat_chk:
+ case Builtin::BI__builtin___strncpy_chk:
+ case Builtin::BI__builtin___stpncpy_chk:
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3);
+ break;
+ case Builtin::BI__builtin___memccpy_chk:
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 3, 4);
+ break;
+ case Builtin::BI__builtin___snprintf_chk:
+ case Builtin::BI__builtin___vsnprintf_chk:
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 1, 3);
+ break;
+
+ case Builtin::BI__builtin_call_with_static_chain:
+ if (SemaBuiltinCallWithStaticChain(*this, TheCall))
+ return ExprError();
+ break;
}
// Since the target specific builtins for each arch overlap, only check those
@@ -342,8 +476,6 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
break;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
- case llvm::Triple::arm64:
- case llvm::Triple::arm64_be:
if (CheckAArch64BuiltinFunctionCall(BuiltinID, TheCall))
return ExprError();
break;
@@ -468,8 +600,7 @@ bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
QualType RHSTy = RHS.get()->getType();
llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
- bool IsPolyUnsigned =
- Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::arm64;
+ bool IsPolyUnsigned = Arch == llvm::Triple::aarch64;
bool IsInt64Long =
Context.getTargetInfo().getInt64Type() == TargetInfo::SignedLong;
QualType EltTy =
@@ -627,6 +758,11 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 64);
}
+ if (BuiltinID == ARM::BI__builtin_arm_prefetch) {
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1) ||
+ SemaBuiltinConstantArgRange(TheCall, 2, 0, 1);
+ }
+
if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
return true;
@@ -641,7 +777,8 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break;
case ARM::BI__builtin_arm_dmb:
case ARM::BI__builtin_arm_dsb:
- case ARM::BI__builtin_arm_isb: l = 0; u = 15; break;
+ case ARM::BI__builtin_arm_isb:
+ case ARM::BI__builtin_arm_dbg: l = 0; u = 15; break;
}
// FIXME: VFP Intrinsics should error if VFP not present.
@@ -659,6 +796,13 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 128);
}
+ if (BuiltinID == AArch64::BI__builtin_arm_prefetch) {
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1) ||
+ SemaBuiltinConstantArgRange(TheCall, 2, 0, 2) ||
+ SemaBuiltinConstantArgRange(TheCall, 3, 0, 1) ||
+ SemaBuiltinConstantArgRange(TheCall, 4, 0, 1);
+ }
+
if (CheckNeonBuiltinFunctionCall(BuiltinID, TheCall))
return true;
@@ -672,7 +816,6 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
case AArch64::BI__builtin_arm_isb: l = 0; u = 15; break;
}
- // FIXME: VFP Intrinsics should error if VFP not present.
return SemaBuiltinConstantArgRange(TheCall, i, l, u + l);
}
@@ -693,12 +836,16 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
}
bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+ unsigned i = 0, l = 0, u = 0;
switch (BuiltinID) {
- case X86::BI_mm_prefetch:
- // This is declared to take (const char*, int)
- return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3);
+ default: return false;
+ case X86::BI_mm_prefetch: i = 1; l = 0; u = 3; break;
+ case X86::BI__builtin_ia32_cmpps:
+ case X86::BI__builtin_ia32_cmpss:
+ case X86::BI__builtin_ia32_cmppd:
+ case X86::BI__builtin_ia32_cmpsd: i = 2; l = 0; u = 31; break;
}
- return false;
+ return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}
/// Given a FunctionDecl's FormatAttr, attempts to populate the FomatStringInfo
@@ -753,14 +900,79 @@ static void CheckNonNullArgument(Sema &S,
S.Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
}
+bool Sema::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) {
+ FormatStringInfo FSI;
+ if ((GetFormatStringType(Format) == FST_NSString) &&
+ getFormatStringInfo(Format, false, &FSI)) {
+ Idx = FSI.FormatIdx;
+ return true;
+ }
+ return false;
+}
+/// \brief Diagnose use of %s directive in an NSString which is being passed
+/// as formatting string to formatting method.
+static void
+DiagnoseCStringFormatDirectiveInCFAPI(Sema &S,
+ const NamedDecl *FDecl,
+ Expr **Args,
+ unsigned NumArgs) {
+ unsigned Idx = 0;
+ bool Format = false;
+ ObjCStringFormatFamily SFFamily = FDecl->getObjCFStringFormattingFamily();
+ if (SFFamily == ObjCStringFormatFamily::SFF_CFString) {
+ Idx = 2;
+ Format = true;
+ }
+ else
+ for (const auto *I : FDecl->specific_attrs<FormatAttr>()) {
+ if (S.GetFormatNSStringIdx(I, Idx)) {
+ Format = true;
+ break;
+ }
+ }
+ if (!Format || NumArgs <= Idx)
+ return;
+ const Expr *FormatExpr = Args[Idx];
+ if (const CStyleCastExpr *CSCE = dyn_cast<CStyleCastExpr>(FormatExpr))
+ FormatExpr = CSCE->getSubExpr();
+ const StringLiteral *FormatString;
+ if (const ObjCStringLiteral *OSL =
+ dyn_cast<ObjCStringLiteral>(FormatExpr->IgnoreParenImpCasts()))
+ FormatString = OSL->getString();
+ else
+ FormatString = dyn_cast<StringLiteral>(FormatExpr->IgnoreParenImpCasts());
+ if (!FormatString)
+ return;
+ if (S.FormatStringHasSArg(FormatString)) {
+ S.Diag(FormatExpr->getExprLoc(), diag::warn_objc_cdirective_format_string)
+ << "%s" << 1 << 1;
+ S.Diag(FDecl->getLocation(), diag::note_entity_declared_at)
+ << FDecl->getDeclName();
+ }
+}
+
static void CheckNonNullArguments(Sema &S,
const NamedDecl *FDecl,
- const Expr * const *ExprArgs,
+ ArrayRef<const Expr *> Args,
SourceLocation CallSiteLoc) {
// Check the attributes attached to the method/function itself.
+ llvm::SmallBitVector NonNullArgs;
for (const auto *NonNull : FDecl->specific_attrs<NonNullAttr>()) {
- for (const auto &Val : NonNull->args())
- CheckNonNullArgument(S, ExprArgs[Val], CallSiteLoc);
+ if (!NonNull->args_size()) {
+ // Easy case: all pointer arguments are nonnull.
+ for (const auto *Arg : Args)
+ if (S.isValidPointerAttrType(Arg->getType()))
+ CheckNonNullArgument(S, Arg, CallSiteLoc);
+ return;
+ }
+
+ for (unsigned Val : NonNull->args()) {
+ if (Val >= Args.size())
+ continue;
+ if (NonNullArgs.empty())
+ NonNullArgs.resize(Args.size());
+ NonNullArgs.set(Val);
+ }
}
// Check the attributes on the parameters.
@@ -770,13 +982,19 @@ static void CheckNonNullArguments(Sema &S,
else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(FDecl))
parms = MD->parameters();
- unsigned argIndex = 0;
+ unsigned ArgIndex = 0;
for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
- I != E; ++I, ++argIndex) {
+ I != E; ++I, ++ArgIndex) {
const ParmVarDecl *PVD = *I;
- if (PVD->hasAttr<NonNullAttr>())
- CheckNonNullArgument(S, ExprArgs[argIndex], CallSiteLoc);
+ if (PVD->hasAttr<NonNullAttr>() ||
+ (ArgIndex < NonNullArgs.size() && NonNullArgs[ArgIndex]))
+ CheckNonNullArgument(S, Args[ArgIndex], CallSiteLoc);
}
+
+ // In case this is a variadic call, check any remaining arguments.
+ for (/**/; ArgIndex < NonNullArgs.size(); ++ArgIndex)
+ if (NonNullArgs[ArgIndex])
+ CheckNonNullArgument(S, Args[ArgIndex], CallSiteLoc);
}
/// Handles the checks for format strings, non-POD arguments to vararg
@@ -814,7 +1032,7 @@ void Sema::checkCall(NamedDecl *FDecl, ArrayRef<const Expr *> Args,
}
if (FDecl) {
- CheckNonNullArguments(*this, FDecl, Args.data(), Loc);
+ CheckNonNullArguments(*this, FDecl, Args, Loc);
// Type safety checking.
for (const auto *I : FDecl->specific_attrs<ArgumentWithTypeTagAttr>())
@@ -854,7 +1072,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
++Args;
--NumArgs;
}
- checkCall(FDecl, llvm::makeArrayRef<const Expr *>(Args, NumArgs), NumParams,
+ checkCall(FDecl, llvm::makeArrayRef(Args, NumArgs), NumParams,
IsMemberFunction, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@@ -865,6 +1083,8 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
return false;
CheckAbsoluteValueFunction(TheCall, FDecl, FnInfo);
+ if (getLangOpts().ObjC1)
+ DiagnoseCStringFormatDirectiveInCFAPI(*this, FDecl, Args, NumArgs);
unsigned CMId = FDecl->getMemoryFunctionKind();
if (CMId == 0)
@@ -913,8 +1133,8 @@ bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
}
unsigned NumParams = Proto ? Proto->getNumParams() : 0;
- checkCall(NDecl, llvm::makeArrayRef<const Expr *>(TheCall->getArgs(),
- TheCall->getNumArgs()),
+ checkCall(NDecl, llvm::makeArrayRef(TheCall->getArgs(),
+ TheCall->getNumArgs()),
NumParams, /*IsMemberFunction=*/false, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@@ -929,8 +1149,7 @@ bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) {
unsigned NumParams = Proto ? Proto->getNumParams() : 0;
checkCall(/*FDecl=*/nullptr,
- llvm::makeArrayRef<const Expr *>(TheCall->getArgs(),
- TheCall->getNumArgs()),
+ llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()),
NumParams, /*IsMemberFunction=*/false, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@@ -1383,12 +1602,14 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
BUILTIN_ROW(__sync_fetch_and_or),
BUILTIN_ROW(__sync_fetch_and_and),
BUILTIN_ROW(__sync_fetch_and_xor),
+ BUILTIN_ROW(__sync_fetch_and_nand),
BUILTIN_ROW(__sync_add_and_fetch),
BUILTIN_ROW(__sync_sub_and_fetch),
BUILTIN_ROW(__sync_and_and_fetch),
BUILTIN_ROW(__sync_or_and_fetch),
BUILTIN_ROW(__sync_xor_and_fetch),
+ BUILTIN_ROW(__sync_nand_and_fetch),
BUILTIN_ROW(__sync_val_compare_and_swap),
BUILTIN_ROW(__sync_bool_compare_and_swap),
@@ -1418,6 +1639,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
// as the number of fixed args.
unsigned BuiltinID = FDecl->getBuiltinID();
unsigned BuiltinIndex, NumFixed = 1;
+ bool WarnAboutSemanticsChange = false;
switch (BuiltinID) {
default: llvm_unreachable("Unknown overloaded atomic builtin!");
case Builtin::BI__sync_fetch_and_add:
@@ -1465,13 +1687,23 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
BuiltinIndex = 4;
break;
+ case Builtin::BI__sync_fetch_and_nand:
+ case Builtin::BI__sync_fetch_and_nand_1:
+ case Builtin::BI__sync_fetch_and_nand_2:
+ case Builtin::BI__sync_fetch_and_nand_4:
+ case Builtin::BI__sync_fetch_and_nand_8:
+ case Builtin::BI__sync_fetch_and_nand_16:
+ BuiltinIndex = 5;
+ WarnAboutSemanticsChange = true;
+ break;
+
case Builtin::BI__sync_add_and_fetch:
case Builtin::BI__sync_add_and_fetch_1:
case Builtin::BI__sync_add_and_fetch_2:
case Builtin::BI__sync_add_and_fetch_4:
case Builtin::BI__sync_add_and_fetch_8:
case Builtin::BI__sync_add_and_fetch_16:
- BuiltinIndex = 5;
+ BuiltinIndex = 6;
break;
case Builtin::BI__sync_sub_and_fetch:
@@ -1480,7 +1712,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
case Builtin::BI__sync_sub_and_fetch_4:
case Builtin::BI__sync_sub_and_fetch_8:
case Builtin::BI__sync_sub_and_fetch_16:
- BuiltinIndex = 6;
+ BuiltinIndex = 7;
break;
case Builtin::BI__sync_and_and_fetch:
@@ -1489,7 +1721,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
case Builtin::BI__sync_and_and_fetch_4:
case Builtin::BI__sync_and_and_fetch_8:
case Builtin::BI__sync_and_and_fetch_16:
- BuiltinIndex = 7;
+ BuiltinIndex = 8;
break;
case Builtin::BI__sync_or_and_fetch:
@@ -1498,7 +1730,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
case Builtin::BI__sync_or_and_fetch_4:
case Builtin::BI__sync_or_and_fetch_8:
case Builtin::BI__sync_or_and_fetch_16:
- BuiltinIndex = 8;
+ BuiltinIndex = 9;
break;
case Builtin::BI__sync_xor_and_fetch:
@@ -1507,7 +1739,17 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
case Builtin::BI__sync_xor_and_fetch_4:
case Builtin::BI__sync_xor_and_fetch_8:
case Builtin::BI__sync_xor_and_fetch_16:
- BuiltinIndex = 9;
+ BuiltinIndex = 10;
+ break;
+
+ case Builtin::BI__sync_nand_and_fetch:
+ case Builtin::BI__sync_nand_and_fetch_1:
+ case Builtin::BI__sync_nand_and_fetch_2:
+ case Builtin::BI__sync_nand_and_fetch_4:
+ case Builtin::BI__sync_nand_and_fetch_8:
+ case Builtin::BI__sync_nand_and_fetch_16:
+ BuiltinIndex = 11;
+ WarnAboutSemanticsChange = true;
break;
case Builtin::BI__sync_val_compare_and_swap:
@@ -1516,7 +1758,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
case Builtin::BI__sync_val_compare_and_swap_4:
case Builtin::BI__sync_val_compare_and_swap_8:
case Builtin::BI__sync_val_compare_and_swap_16:
- BuiltinIndex = 10;
+ BuiltinIndex = 12;
NumFixed = 2;
break;
@@ -1526,7 +1768,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
case Builtin::BI__sync_bool_compare_and_swap_4:
case Builtin::BI__sync_bool_compare_and_swap_8:
case Builtin::BI__sync_bool_compare_and_swap_16:
- BuiltinIndex = 11;
+ BuiltinIndex = 13;
NumFixed = 2;
ResultType = Context.BoolTy;
break;
@@ -1537,7 +1779,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
case Builtin::BI__sync_lock_test_and_set_4:
case Builtin::BI__sync_lock_test_and_set_8:
case Builtin::BI__sync_lock_test_and_set_16:
- BuiltinIndex = 12;
+ BuiltinIndex = 14;
break;
case Builtin::BI__sync_lock_release:
@@ -1546,7 +1788,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
case Builtin::BI__sync_lock_release_4:
case Builtin::BI__sync_lock_release_8:
case Builtin::BI__sync_lock_release_16:
- BuiltinIndex = 13;
+ BuiltinIndex = 15;
NumFixed = 0;
ResultType = Context.VoidTy;
break;
@@ -1557,7 +1799,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
case Builtin::BI__sync_swap_4:
case Builtin::BI__sync_swap_8:
case Builtin::BI__sync_swap_16:
- BuiltinIndex = 14;
+ BuiltinIndex = 16;
break;
}
@@ -1570,6 +1812,11 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
return ExprError();
}
+ if (WarnAboutSemanticsChange) {
+ Diag(TheCall->getLocEnd(), diag::warn_sync_fetch_and_nand_semantics_change)
+ << TheCall->getCallee()->getSourceRange();
+ }
+
// Get the decl for the concrete builtin from this, we can tell what the
// concrete integer type we should convert to is.
unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
@@ -2031,7 +2278,46 @@ bool Sema::SemaBuiltinAssume(CallExpr *TheCall) {
if (Arg->HasSideEffects(Context))
return Diag(Arg->getLocStart(), diag::warn_assume_side_effects)
- << Arg->getSourceRange();
+ << Arg->getSourceRange()
+ << cast<FunctionDecl>(TheCall->getCalleeDecl())->getIdentifier();
+
+ return false;
+}
+
+/// Handle __builtin_assume_aligned. This is declared
+/// as (const void*, size_t, ...) and can take one optional constant int arg.
+bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) {
+ unsigned NumArgs = TheCall->getNumArgs();
+
+ if (NumArgs > 3)
+ return Diag(TheCall->getLocEnd(),
+ diag::err_typecheck_call_too_many_args_at_most)
+ << 0 /*function call*/ << 3 << NumArgs
+ << TheCall->getSourceRange();
+
+ // The alignment must be a constant integer.
+ Expr *Arg = TheCall->getArg(1);
+
+ // We can't check the value of a dependent argument.
+ if (!Arg->isTypeDependent() && !Arg->isValueDependent()) {
+ llvm::APSInt Result;
+ if (SemaBuiltinConstantArg(TheCall, 1, Result))
+ return true;
+
+ if (!Result.isPowerOf2())
+ return Diag(TheCall->getLocStart(),
+ diag::err_alignment_not_power_of_two)
+ << Arg->getSourceRange();
+ }
+
+ if (NumArgs > 2) {
+ ExprResult Arg(TheCall->getArg(2));
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
+ Context.getSizeType(), false);
+ Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg);
+ if (Arg.isInvalid()) return true;
+ TheCall->setArg(2, Arg.get());
+ }
return false;
}
@@ -3178,6 +3464,61 @@ static bool requiresParensToAddCast(const Expr *E) {
}
}
+static std::pair<QualType, StringRef>
+shouldNotPrintDirectly(const ASTContext &Context,
+ QualType IntendedTy,
+ const Expr *E) {
+ // Use a 'while' to peel off layers of typedefs.
+ QualType TyTy = IntendedTy;
+ while (const TypedefType *UserTy = TyTy->getAs<TypedefType>()) {
+ StringRef Name = UserTy->getDecl()->getName();
+ QualType CastTy = llvm::StringSwitch<QualType>(Name)
+ .Case("NSInteger", Context.LongTy)
+ .Case("NSUInteger", Context.UnsignedLongTy)
+ .Case("SInt32", Context.IntTy)
+ .Case("UInt32", Context.UnsignedIntTy)
+ .Default(QualType());
+
+ if (!CastTy.isNull())
+ return std::make_pair(CastTy, Name);
+
+ TyTy = UserTy->desugar();
+ }
+
+ // Strip parens if necessary.
+ if (const ParenExpr *PE = dyn_cast<ParenExpr>(E))
+ return shouldNotPrintDirectly(Context,
+ PE->getSubExpr()->getType(),
+ PE->getSubExpr());
+
+ // If this is a conditional expression, then its result type is constructed
+ // via usual arithmetic conversions and thus there might be no necessary
+ // typedef sugar there. Recurse to operands to check for NSInteger &
+ // Co. usage condition.
+ if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
+ QualType TrueTy, FalseTy;
+ StringRef TrueName, FalseName;
+
+ std::tie(TrueTy, TrueName) =
+ shouldNotPrintDirectly(Context,
+ CO->getTrueExpr()->getType(),
+ CO->getTrueExpr());
+ std::tie(FalseTy, FalseName) =
+ shouldNotPrintDirectly(Context,
+ CO->getFalseExpr()->getType(),
+ CO->getFalseExpr());
+
+ if (TrueTy == FalseTy)
+ return std::make_pair(TrueTy, TrueName);
+ else if (TrueTy.isNull())
+ return std::make_pair(FalseTy, FalseName);
+ else if (FalseTy.isNull())
+ return std::make_pair(TrueTy, TrueName);
+ }
+
+ return std::make_pair(QualType(), StringRef());
+}
+
bool
CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
const char *StartSpecifier,
@@ -3269,25 +3610,13 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// Special-case some of Darwin's platform-independence types by suggesting
// casts to primitive types that are known to be large enough.
- bool ShouldNotPrintDirectly = false;
+ bool ShouldNotPrintDirectly = false; StringRef CastTyName;
if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {
- // Use a 'while' to peel off layers of typedefs.
- QualType TyTy = IntendedTy;
- while (const TypedefType *UserTy = TyTy->getAs<TypedefType>()) {
- StringRef Name = UserTy->getDecl()->getName();
- QualType CastTy = llvm::StringSwitch<QualType>(Name)
- .Case("NSInteger", S.Context.LongTy)
- .Case("NSUInteger", S.Context.UnsignedLongTy)
- .Case("SInt32", S.Context.IntTy)
- .Case("UInt32", S.Context.UnsignedIntTy)
- .Default(QualType());
-
- if (!CastTy.isNull()) {
- ShouldNotPrintDirectly = true;
- IntendedTy = CastTy;
- break;
- }
- TyTy = UserTy->desugar();
+ QualType CastTy;
+ std::tie(CastTy, CastTyName) = shouldNotPrintDirectly(S.Context, IntendedTy, E);
+ if (!CastTy.isNull()) {
+ IntendedTy = CastTy;
+ ShouldNotPrintDirectly = true;
}
}
@@ -3304,7 +3633,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen);
- if (IntendedTy == ExprTy) {
+ if (IntendedTy == ExprTy && !ShouldNotPrintDirectly) {
// In this case, the specifier is wrong and should be changed to match
// the argument.
EmitFormatDiagnostic(
@@ -3358,8 +3687,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// The expression has a type that should not be printed directly.
// We extract the name from the typedef because we don't want to show
// the underlying type in the diagnostic.
- StringRef Name = cast<TypedefType>(ExprTy)->getDecl()->getName();
-
+ StringRef Name;
+ if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(ExprTy))
+ Name = TypedefTy->getDecl()->getName();
+ else
+ Name = CastTyName;
EmitFormatDiagnostic(S.PDiag(diag::warn_format_argument_needs_cast)
<< Name << IntendedTy << IsEnum
<< E->getSourceRange(),
@@ -3395,6 +3727,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
break;
case Sema::VAK_Undefined:
+ case Sema::VAK_MSVCUndefined:
EmitFormatDiagnostic(
S.PDiag(diag::warn_non_pod_vararg_with_format_string)
<< S.getLangOpts().CPlusPlus11
@@ -3672,6 +4005,20 @@ void Sema::CheckFormatString(const StringLiteral *FExpr,
} // TODO: handle other formats
}
+bool Sema::FormatStringHasSArg(const StringLiteral *FExpr) {
+ // Str - The format string. NOTE: this is NOT null-terminated!
+ StringRef StrRef = FExpr->getString();
+ const char *Str = StrRef.data();
+ // 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());
+ return analyze_format_string::ParseFormatStringHasSArg(Str, Str + StrLen,
+ getLangOpts(),
+ Context.getTargetInfo());
+}
+
//===--- CHECK: Warn on use of wrong absolute value function. -------------===//
// Returns the related absolute value function that is larger, of 0 if one
@@ -4346,7 +4693,8 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call,
IdentifierInfo *FnName) {
// Don't crash if the user has the wrong number of arguments
- if (Call->getNumArgs() != 3)
+ unsigned NumArgs = Call->getNumArgs();
+ if ((NumArgs != 3) && (NumArgs != 4))
return;
const Expr *SrcArg = ignoreLiteralAdditions(Call->getArg(1), Context);
@@ -4628,7 +4976,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
DeclRefExpr *DR = cast<DeclRefExpr>(E);
// If we leave the immediate function, the lifetime isn't about to end.
- if (DR->refersToEnclosingLocal())
+ if (DR->refersToEnclosingVariableOrCapture())
return nullptr;
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
@@ -4795,7 +5143,7 @@ do {
DeclRefExpr *DR = cast<DeclRefExpr>(E);
// If we leave the immediate function, the lifetime isn't about to end.
- if (DR->refersToEnclosingLocal())
+ if (DR->refersToEnclosingVariableOrCapture())
return nullptr;
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) {
@@ -5660,8 +6008,13 @@ static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) {
static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
// The type the comparison is being performed in.
QualType T = E->getLHS()->getType();
- assert(S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType())
- && "comparison with mismatched types");
+
+ // Only analyze comparison operators where both sides have been converted to
+ // the same type.
+ if (!S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType()))
+ return AnalyzeImpConvsInComparison(S, E);
+
+ // Don't analyze value-dependent comparisons directly.
if (E->isValueDependent())
return AnalyzeImpConvsInComparison(S, E);
@@ -5932,6 +6285,41 @@ void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall,
}
}
+static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T,
+ SourceLocation CC) {
+ if (S.Diags.isIgnored(diag::warn_impcast_null_pointer_to_integer,
+ E->getExprLoc()))
+ return;
+
+ // Check for NULL (GNUNull) or nullptr (CXX11_nullptr).
+ const Expr::NullPointerConstantKind NullKind =
+ E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull);
+ if (NullKind != Expr::NPCK_GNUNull && NullKind != Expr::NPCK_CXX11_nullptr)
+ return;
+
+ // Return if target type is a safe conversion.
+ if (T->isAnyPointerType() || T->isBlockPointerType() ||
+ T->isMemberPointerType() || !T->isScalarType() || T->isNullPtrType())
+ return;
+
+ SourceLocation Loc = E->getSourceRange().getBegin();
+
+ // __null is usually wrapped in a macro. Go up a macro if that is the case.
+ if (NullKind == Expr::NPCK_GNUNull) {
+ if (Loc.isMacroID())
+ Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first;
+ }
+
+ // Only warn if the null and context location are in the same macro expansion.
+ if (S.SourceMgr.getFileID(Loc) != S.SourceMgr.getFileID(CC))
+ return;
+
+ S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer)
+ << (NullKind == Expr::NPCK_CXX11_nullptr) << T << clang::SourceRange(CC)
+ << FixItHint::CreateReplacement(Loc,
+ S.getFixItZeroLiteralForType(T, Loc));
+}
+
void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
SourceLocation CC, bool *ICContext = nullptr) {
if (E->isTypeDependent() || E->isValueDependent()) return;
@@ -6074,19 +6462,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
return;
}
- if ((E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)
- == Expr::NPCK_GNUNull) && !Target->isAnyPointerType()
- && !Target->isBlockPointerType() && !Target->isMemberPointerType()
- && Target->isScalarType() && !Target->isNullPtrType()) {
- SourceLocation Loc = E->getSourceRange().getBegin();
- if (Loc.isMacroID())
- Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first;
- if (!Loc.isMacroID() || CC.isMacroID())
- S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer)
- << T << clang::SourceRange(CC)
- << FixItHint::CreateReplacement(Loc,
- S.getFixItZeroLiteralForType(T, Loc));
- }
+ DiagnoseNullConversion(S, E, T, CC);
if (!Source->isIntegerType() || !Target->isIntegerType())
return;
@@ -6196,7 +6572,7 @@ void CheckConditionalOperand(Sema &S, Expr *E, QualType T,
void CheckConditionalOperator(Sema &S, ConditionalOperator *E,
SourceLocation CC, QualType T) {
- AnalyzeImplicitConversions(S, E->getCond(), CC);
+ AnalyzeImplicitConversions(S, E->getCond(), E->getQuestionLoc());
bool Suspicious = false;
CheckConditionalOperand(S, E->getTrueExpr(), T, CC, Suspicious);
@@ -6222,6 +6598,14 @@ void CheckConditionalOperator(Sema &S, ConditionalOperator *E,
E->getType(), CC, &Suspicious);
}
+/// CheckBoolLikeConversion - Check conversion of given expression to boolean.
+/// Input argument E is a logical expression.
+static void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) {
+ if (S.getLangOpts().Bool)
+ return;
+ CheckImplicitConversion(S, E->IgnoreParenImpCasts(), S.Context.BoolTy, CC);
+}
+
/// AnalyzeImplicitConversions - Find and report any interesting
/// implicit conversions in the given expression. There are a couple
/// of competing diagnostics here, -Wconversion and -Wsign-compare.
@@ -6301,6 +6685,20 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
continue;
AnalyzeImplicitConversions(S, ChildExpr, CC);
}
+
+ if (BO && BO->isLogicalOp()) {
+ Expr *SubExpr = BO->getLHS()->IgnoreParenImpCasts();
+ if (!IsLogicalAndOperator || !isa<StringLiteral>(SubExpr))
+ ::CheckBoolLikeConversion(S, SubExpr, BO->getExprLoc());
+
+ SubExpr = BO->getRHS()->IgnoreParenImpCasts();
+ if (!IsLogicalAndOperator || !isa<StringLiteral>(SubExpr))
+ ::CheckBoolLikeConversion(S, SubExpr, BO->getExprLoc());
+ }
+
+ if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E))
+ if (U->getOpcode() == UO_LNot)
+ ::CheckBoolLikeConversion(S, U->getSubExpr(), CC);
}
} // end anonymous namespace
@@ -6343,6 +6741,22 @@ static bool CheckForReference(Sema &SemaRef, const Expr *E,
return true;
}
+// Returns true if the SourceLocation is expanded from any macro body.
+// Returns false if the SourceLocation is invalid, is from not in a macro
+// expansion, or is from expanded from a top-level macro argument.
+static bool IsInAnyMacroBody(const SourceManager &SM, SourceLocation Loc) {
+ if (Loc.isInvalid())
+ return false;
+
+ while (Loc.isMacroID()) {
+ if (SM.isMacroBodyExpansion(Loc))
+ return true;
+ Loc = SM.getImmediateMacroCallerLoc(Loc);
+ }
+
+ return false;
+}
+
/// \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
@@ -6356,8 +6770,12 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
return;
// Don't warn inside macros.
- if (E->getExprLoc().isMacroID())
+ if (E->getExprLoc().isMacroID()) {
+ const SourceManager &SM = getSourceManager();
+ if (IsInAnyMacroBody(SM, E->getExprLoc()) ||
+ IsInAnyMacroBody(SM, Range.getBegin()))
return;
+ }
E = E->IgnoreImpCasts();
const bool IsCompare = NullKind != Expr::NPCK_NotNull;
@@ -6400,7 +6818,40 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
// Weak Decls can be null.
if (!D || D->isWeak())
return;
-
+
+ // Check for parameter decl with nonnull attribute
+ if (const ParmVarDecl* PV = dyn_cast<ParmVarDecl>(D)) {
+ if (getCurFunction() && !getCurFunction()->ModifiedNonNullParams.count(PV))
+ if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
+ unsigned NumArgs = FD->getNumParams();
+ llvm::SmallBitVector AttrNonNull(NumArgs);
+ for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) {
+ if (!NonNull->args_size()) {
+ AttrNonNull.set(0, NumArgs);
+ break;
+ }
+ for (unsigned Val : NonNull->args()) {
+ if (Val >= NumArgs)
+ continue;
+ AttrNonNull.set(Val);
+ }
+ }
+ if (!AttrNonNull.empty())
+ for (unsigned i = 0; i < NumArgs; ++i)
+ if (FD->getParamDecl(i) == PV &&
+ (AttrNonNull[i] || PV->hasAttr<NonNullAttr>())) {
+ std::string Str;
+ llvm::raw_string_ostream S(Str);
+ E->printPretty(S, nullptr, getPrintingPolicy());
+ unsigned DiagID = IsCompare ? diag::warn_nonnull_parameter_compare
+ : diag::warn_cast_nonnull_to_bool;
+ Diag(E->getExprLoc(), DiagID) << S.str() << E->getSourceRange()
+ << Range << IsEqual;
+ return;
+ }
+ }
+ }
+
QualType T = D->getType();
const bool IsArray = T->isArrayType();
const bool IsFunction = T->isFunctionType();
@@ -6496,11 +6947,17 @@ void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) {
AnalyzeImplicitConversions(*this, E, CC);
}
+/// CheckBoolLikeConversion - Check conversion of given expression to boolean.
+/// Input argument E is a logical expression.
+void Sema::CheckBoolLikeConversion(Expr *E, SourceLocation CC) {
+ ::CheckBoolLikeConversion(*this, E, CC);
+}
+
/// Diagnose when expression is an integer constant expression and its evaluation
/// results in integer overflow
void Sema::CheckForIntOverflow (Expr *E) {
- if (isa<BinaryOperator>(E->IgnoreParens()))
- E->EvaluateForOverflow(Context);
+ if (isa<BinaryOperator>(E->IgnoreParenCasts()))
+ E->IgnoreParenCasts()->EvaluateForOverflow(Context);
}
namespace {
@@ -6630,11 +7087,12 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
Self.ModAsSideEffect = &ModAsSideEffect;
}
~SequencedSubexpression() {
- for (unsigned I = 0, E = ModAsSideEffect.size(); I != E; ++I) {
- UsageInfo &U = Self.UsageMap[ModAsSideEffect[I].first];
- U.Uses[UK_ModAsSideEffect] = ModAsSideEffect[I].second;
- Self.addUsage(U, ModAsSideEffect[I].first,
- ModAsSideEffect[I].second.Use, UK_ModAsValue);
+ for (auto MI = ModAsSideEffect.rbegin(), ME = ModAsSideEffect.rend();
+ MI != ME; ++MI) {
+ UsageInfo &U = Self.UsageMap[MI->first];
+ auto &SideEffectUsage = U.Uses[UK_ModAsSideEffect];
+ Self.addUsage(U, MI->first, SideEffectUsage.Use, UK_ModAsValue);
+ SideEffectUsage = MI->second;
}
Self.ModAsSideEffect = OldModAsSideEffect;
}
@@ -7867,6 +8325,96 @@ void Sema::DiagnoseEmptyLoopBody(const Stmt *S,
}
}
+//===--- CHECK: Warn on self move with std::move. -------------------------===//
+
+/// DiagnoseSelfMove - Emits a warning if a value is moved to itself.
+void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
+ SourceLocation OpLoc) {
+
+ if (Diags.isIgnored(diag::warn_sizeof_pointer_expr_memaccess, OpLoc))
+ return;
+
+ if (!ActiveTemplateInstantiations.empty())
+ return;
+
+ // Strip parens and casts away.
+ LHSExpr = LHSExpr->IgnoreParenImpCasts();
+ RHSExpr = RHSExpr->IgnoreParenImpCasts();
+
+ // Check for a call expression
+ const CallExpr *CE = dyn_cast<CallExpr>(RHSExpr);
+ if (!CE || CE->getNumArgs() != 1)
+ return;
+
+ // Check for a call to std::move
+ const FunctionDecl *FD = CE->getDirectCallee();
+ if (!FD || !FD->isInStdNamespace() || !FD->getIdentifier() ||
+ !FD->getIdentifier()->isStr("move"))
+ return;
+
+ // Get argument from std::move
+ RHSExpr = CE->getArg(0);
+
+ const DeclRefExpr *LHSDeclRef = dyn_cast<DeclRefExpr>(LHSExpr);
+ const DeclRefExpr *RHSDeclRef = dyn_cast<DeclRefExpr>(RHSExpr);
+
+ // Two DeclRefExpr's, check that the decls are the same.
+ if (LHSDeclRef && RHSDeclRef) {
+ if (!LHSDeclRef->getDecl() || !RHSDeclRef->getDecl())
+ return;
+ if (LHSDeclRef->getDecl()->getCanonicalDecl() !=
+ RHSDeclRef->getDecl()->getCanonicalDecl())
+ return;
+
+ Diag(OpLoc, diag::warn_self_move) << LHSExpr->getType()
+ << LHSExpr->getSourceRange()
+ << RHSExpr->getSourceRange();
+ return;
+ }
+
+ // Member variables require a different approach to check for self moves.
+ // MemberExpr's are the same if every nested MemberExpr refers to the same
+ // Decl and that the base Expr's are DeclRefExpr's with the same Decl or
+ // the base Expr's are CXXThisExpr's.
+ const Expr *LHSBase = LHSExpr;
+ const Expr *RHSBase = RHSExpr;
+ const MemberExpr *LHSME = dyn_cast<MemberExpr>(LHSExpr);
+ const MemberExpr *RHSME = dyn_cast<MemberExpr>(RHSExpr);
+ if (!LHSME || !RHSME)
+ return;
+
+ while (LHSME && RHSME) {
+ if (LHSME->getMemberDecl()->getCanonicalDecl() !=
+ RHSME->getMemberDecl()->getCanonicalDecl())
+ return;
+
+ LHSBase = LHSME->getBase();
+ RHSBase = RHSME->getBase();
+ LHSME = dyn_cast<MemberExpr>(LHSBase);
+ RHSME = dyn_cast<MemberExpr>(RHSBase);
+ }
+
+ LHSDeclRef = dyn_cast<DeclRefExpr>(LHSBase);
+ RHSDeclRef = dyn_cast<DeclRefExpr>(RHSBase);
+ if (LHSDeclRef && RHSDeclRef) {
+ if (!LHSDeclRef->getDecl() || !RHSDeclRef->getDecl())
+ return;
+ if (LHSDeclRef->getDecl()->getCanonicalDecl() !=
+ RHSDeclRef->getDecl()->getCanonicalDecl())
+ return;
+
+ Diag(OpLoc, diag::warn_self_move) << LHSExpr->getType()
+ << LHSExpr->getSourceRange()
+ << RHSExpr->getSourceRange();
+ return;
+ }
+
+ if (isa<CXXThisExpr>(LHSBase) && isa<CXXThisExpr>(RHSBase))
+ Diag(OpLoc, diag::warn_self_move) << LHSExpr->getType()
+ << LHSExpr->getSourceRange()
+ << RHSExpr->getSourceRange();
+}
+
//===--- Layout compatibility ----------------------------------------------//
namespace {
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 3d250e3bef11..48bdd2a7d82c 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -292,7 +292,7 @@ namespace {
void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
/// \brief Add a new result to this result set, where we already know
- /// the hiding declation (if any).
+ /// the hiding declaration (if any).
///
/// \param R the result to add (if it is unique).
///
@@ -894,7 +894,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
}
// Make sure that any given declaration only shows up in the result set once.
- if (!AllDeclsFound.insert(CanonDecl))
+ if (!AllDeclsFound.insert(CanonDecl).second)
return;
// If the filter is for nested-name-specifiers, then this result starts a
@@ -957,7 +957,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
return;
// Make sure that any given declaration only shows up in the result set once.
- if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
+ if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
return;
// If the filter is for nested-name-specifiers, then this result starts a
@@ -2575,11 +2575,12 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
const MacroDirective *MD = PP.getMacroDirectiveHistory(Macro);
assert(MD && "Not a macro?");
const MacroInfo *MI = MD->getMacroInfo();
+ assert((!MD->isDefined() || MI) && "missing MacroInfo for define");
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(Macro->getName()));
- if (!MI->isFunctionLike())
+ if (!MI || !MI->isFunctionLike())
return Result.TakeString();
// Format a function-like macro with placeholders for the arguments.
@@ -3466,7 +3467,7 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
// Add properties in this container.
for (const auto *P : Container->properties())
- if (AddedProperties.insert(P->getIdentifier()))
+ if (AddedProperties.insert(P->getIdentifier()).second)
Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
CurContext);
@@ -3477,7 +3478,7 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
for (auto *M : Container->methods()) {
if (M->getSelector().isUnarySelector())
if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
- if (AddedProperties.insert(Name)) {
+ if (AddedProperties.insert(Name).second) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
AddResultTypeChunk(Context, Policy, M, Builder);
@@ -4235,7 +4236,8 @@ void Sema::CodeCompleteConstructorInitializer(
bool SawLastInitializer = Initializers.empty();
CXXRecordDecl *ClassDecl = Constructor->getParent();
for (const auto &Base : ClassDecl->bases()) {
- if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))) {
+ if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
+ .second) {
SawLastInitializer
= !Initializers.empty() &&
Initializers.back()->isBaseInitializer() &&
@@ -4258,7 +4260,8 @@ void Sema::CodeCompleteConstructorInitializer(
// Add completions for virtual base classes.
for (const auto &Base : ClassDecl->vbases()) {
- if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))) {
+ if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
+ .second) {
SawLastInitializer
= !Initializers.empty() &&
Initializers.back()->isBaseInitializer() &&
@@ -4281,7 +4284,8 @@ void Sema::CodeCompleteConstructorInitializer(
// Add completions for members.
for (auto *Field : ClassDecl->fields()) {
- if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
+ if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
+ .second) {
SawLastInitializer
= !Initializers.empty() &&
Initializers.back()->isAnyMemberInitializer() &&
@@ -4348,7 +4352,7 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
Var->hasAttr<BlocksAttr>())
continue;
- if (Known.insert(Var->getIdentifier()))
+ if (Known.insert(Var->getIdentifier()).second)
Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
CurContext, nullptr, false);
}
@@ -4817,7 +4821,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
continue;
- if (!Selectors.insert(M->getSelector()))
+ if (!Selectors.insert(M->getSelector()).second)
continue;
Result R = Result(M, Results.getBasePriority(M), nullptr);
@@ -5400,13 +5404,13 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
MEnd = SemaRef.MethodPool.end();
M != MEnd; ++M) {
for (ObjCMethodList *MethList = &M->second.second;
- MethList && MethList->Method;
+ MethList && MethList->getMethod();
MethList = MethList->getNext()) {
- if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents))
+ if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
- Result R(MethList->Method, Results.getBasePriority(MethList->Method),
- nullptr);
+ Result R(MethList->getMethod(),
+ Results.getBasePriority(MethList->getMethod()), nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, SemaRef.CurContext);
@@ -5573,16 +5577,16 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
MEnd = MethodPool.end();
M != MEnd; ++M) {
for (ObjCMethodList *MethList = &M->second.first;
- MethList && MethList->Method;
+ MethList && MethList->getMethod();
MethList = MethList->getNext()) {
- if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents))
+ if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
- if (!Selectors.insert(MethList->Method->getSelector()))
+ if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
continue;
- Result R(MethList->Method, Results.getBasePriority(MethList->Method),
- nullptr);
+ Result R(MethList->getMethod(),
+ Results.getBasePriority(MethList->getMethod()), nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, CurContext);
@@ -5858,7 +5862,7 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
for (const auto *D : TU->decls())
if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
- if (CategoryNames.insert(Category->getIdentifier()))
+ if (CategoryNames.insert(Category->getIdentifier()).second)
Results.AddResult(Result(Category, Results.getBasePriority(Category),
nullptr),
CurContext, nullptr, false);
@@ -5896,7 +5900,7 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
while (Class) {
for (const auto *Cat : Class->visible_categories()) {
if ((!IgnoreImplemented || !Cat->getImplementation()) &&
- CategoryNames.insert(Cat->getIdentifier()))
+ CategoryNames.insert(Cat->getIdentifier()).second)
Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
CurContext, nullptr, false);
}
@@ -6217,7 +6221,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
// Add the normal accessor -(type)key.
if (IsInstanceMethod &&
- KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
+ KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
if (ReturnType.isNull())
AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
@@ -6238,7 +6242,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
Property->getType()->isBooleanType())))) {
std::string SelectorName = (Twine("is") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
+ .second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("BOOL");
@@ -6257,7 +6262,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
!Property->getSetterMethodDecl()) {
std::string SelectorName = (Twine("set") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
@@ -6309,7 +6314,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
(ReturnType.isNull() || ReturnType->isIntegerType())) {
std::string SelectorName = (Twine("countOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
+ .second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSUInteger");
@@ -6332,7 +6338,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
std::string SelectorName
= (Twine("objectIn") + UpperKey + "AtIndex").str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("id");
@@ -6359,7 +6365,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
std::string SelectorName
= (Twine(Property->getName()) + "AtIndexes").str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSArray *");
@@ -6384,7 +6390,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
&Context.Idents.get("range")
};
- if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
+ if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
@@ -6418,7 +6424,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
&Context.Idents.get(SelectorName)
};
- if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
+ if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
@@ -6450,7 +6456,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
&Context.Idents.get("atIndexes")
};
- if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
+ if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
@@ -6478,7 +6484,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
std::string SelectorName
= (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
@@ -6500,7 +6506,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
std::string SelectorName
= (Twine("remove") + UpperKey + "AtIndexes").str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
@@ -6526,7 +6532,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
&Context.Idents.get("withObject")
};
- if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
+ if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
@@ -6559,7 +6565,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
&Context.Idents.get(SelectorName2)
};
- if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
+ if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
@@ -6592,7 +6598,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
->getName() == "NSEnumerator"))) {
std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
+ .second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSEnumerator *");
@@ -6610,7 +6617,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
(ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
std::string SelectorName = (Twine("memberOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
@@ -6641,7 +6648,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
std::string SelectorName
= (Twine("add") + UpperKey + Twine("Object")).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
@@ -6663,7 +6670,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("add") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
@@ -6685,7 +6692,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
std::string SelectorName
= (Twine("remove") + UpperKey + Twine("Object")).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
@@ -6707,7 +6714,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("remove") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
@@ -6728,7 +6735,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("intersect") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
@@ -6756,7 +6763,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
std::string SelectorName
= (Twine("keyPathsForValuesAffecting") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
+ .second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSSet *");
@@ -6777,7 +6785,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
std::string SelectorName
= (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
- if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
+ if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
+ .second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("BOOL");
@@ -6985,16 +6994,18 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
M != MEnd; ++M) {
for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
&M->second.second;
- MethList && MethList->Method;
+ MethList && MethList->getMethod();
MethList = MethList->getNext()) {
- if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents))
+ if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
if (AtParameterName) {
// Suggest parameter names we've seen before.
unsigned NumSelIdents = SelIdents.size();
- if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
- ParmVarDecl *Param = MethList->Method->parameters()[NumSelIdents-1];
+ if (NumSelIdents &&
+ NumSelIdents <= MethList->getMethod()->param_size()) {
+ ParmVarDecl *Param =
+ MethList->getMethod()->parameters()[NumSelIdents - 1];
if (Param->getIdentifier()) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
@@ -7007,8 +7018,8 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
continue;
}
- Result R(MethList->Method, Results.getBasePriority(MethList->Method),
- nullptr);
+ Result R(MethList->getMethod(),
+ Results.getBasePriority(MethList->getMethod()), nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
R.DeclaringEntity = true;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 87162273bbe6..007470344f19 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -152,7 +152,10 @@ static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
auto *TD = TST->getTemplateName().getAsTemplateDecl();
if (!TD)
continue;
- auto *BasePrimaryTemplate = cast<CXXRecordDecl>(TD->getTemplatedDecl());
+ auto *BasePrimaryTemplate =
+ dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl());
+ if (!BasePrimaryTemplate)
+ continue;
// FIXME: Allow lookup into non-dependent bases of dependent bases, possibly
// by calling or integrating with the main LookupQualifiedName mechanism.
for (NamedDecl *ND : BasePrimaryTemplate->lookup(&II)) {
@@ -283,10 +286,10 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
if (CorrectedII) {
- TypeNameValidatorCCC Validator(true, isClassName);
- TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(),
- Kind, S, SS, Validator,
- CTK_ErrorRecovery);
+ TypoCorrection Correction = CorrectTypo(
+ Result.getLookupNameInfo(), Kind, S, SS,
+ llvm::make_unique<TypeNameValidatorCCC>(true, isClassName),
+ CTK_ErrorRecovery);
IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
TemplateTy Template;
bool MemberOfUnknownSpecialization;
@@ -377,6 +380,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
DiagnoseUseOfDecl(IIDecl, NameLoc);
T = Context.getTypeDeclType(TD);
+ MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
// NOTE: avoid constructing an ElaboratedType(Loc) if this is a
// constructor or destructor name (in such a case, the scope specifier
@@ -494,6 +498,9 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
/// @endcode
bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) {
if (CurContext->isRecord()) {
+ if (SS->getScopeRep()->getKind() == NestedNameSpecifier::Super)
+ return true;
+
const Type *Ty = SS->getScopeRep()->getAsType();
CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext);
@@ -516,10 +523,11 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
// 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, false, AllowClassTemplates);
- if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(II, IILoc),
- LookupOrdinaryName, S, SS,
- Validator, CTK_ErrorRecovery)) {
+ if (TypoCorrection Corrected =
+ CorrectTypo(DeclarationNameInfo(II, IILoc), LookupOrdinaryName, S, SS,
+ llvm::make_unique<TypeNameValidatorCCC>(
+ false, false, AllowClassTemplates),
+ CTK_ErrorRecovery)) {
if (Corrected.isKeyword()) {
// We corrected to a keyword.
diagnoseTypo(Corrected, PDiag(diag::err_unknown_typename_suggest) << II);
@@ -679,13 +687,11 @@ static ParsedType buildNestedType(Sema &S, CXXScopeSpec &SS,
return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
}
-Sema::NameClassification Sema::ClassifyName(Scope *S,
- CXXScopeSpec &SS,
- IdentifierInfo *&Name,
- SourceLocation NameLoc,
- const Token &NextToken,
- bool IsAddressOfOperand,
- CorrectionCandidateCallback *CCC) {
+Sema::NameClassification
+Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name,
+ SourceLocation NameLoc, const Token &NextToken,
+ bool IsAddressOfOperand,
+ std::unique_ptr<CorrectionCandidateCallback> CCC) {
DeclarationNameInfo NameInfo(Name, NameLoc);
ObjCMethodDecl *CurMethod = getCurMethodDecl();
@@ -762,7 +768,7 @@ Corrected:
SecondTry = true;
if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
Result.getLookupKind(), S,
- &SS, *CCC,
+ &SS, std::move(CCC),
CTK_ErrorRecovery)) {
unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
unsigned QualifiedDiag = diag::err_no_member_suggest;
@@ -925,6 +931,7 @@ Corrected:
NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl();
if (TypeDecl *Type = dyn_cast<TypeDecl>(FirstDecl)) {
DiagnoseUseOfDecl(Type, NameLoc);
+ MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false);
QualType T = Context.getTypeDeclType(Type);
if (SS.isNotEmpty())
return buildNestedType(*this, SS, T, NameLoc);
@@ -1392,10 +1399,22 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
if (isa<LabelDecl>(D))
return true;
+
+ // Except for labels, we only care about unused decls that are local to
+ // functions.
+ bool WithinFunction = D->getDeclContext()->isFunctionOrMethod();
+ if (const auto *R = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
+ // For dependent types, the diagnostic is deferred.
+ WithinFunction =
+ WithinFunction || (R->isLocalClass() && !R->isDependentType());
+ if (!WithinFunction)
+ return false;
+
+ if (isa<TypedefNameDecl>(D))
+ return true;
// White-list anything that isn't a local variable.
- if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) ||
- !D->getDeclContext()->isFunctionOrMethod())
+ if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D))
return false;
// Types of valid local variables should be complete, so this should succeed.
@@ -1458,11 +1477,30 @@ static void GenerateFixForUnusedDecl(const NamedDecl *D, ASTContext &Ctx,
return;
}
+void Sema::DiagnoseUnusedNestedTypedefs(const RecordDecl *D) {
+ if (D->getTypeForDecl()->isDependentType())
+ return;
+
+ for (auto *TmpD : D->decls()) {
+ if (const auto *T = dyn_cast<TypedefNameDecl>(TmpD))
+ DiagnoseUnusedDecl(T);
+ else if(const auto *R = dyn_cast<RecordDecl>(TmpD))
+ DiagnoseUnusedNestedTypedefs(R);
+ }
+}
+
/// DiagnoseUnusedDecl - Emit warnings about declarations that are not used
/// unless they are marked attr(unused).
void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {
if (!ShouldDiagnoseUnusedDecl(D))
return;
+
+ if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
+ // typedefs can be referenced later on, so the diagnostics are emitted
+ // at end-of-translation-unit.
+ UnusedLocalTypedefNameCandidates.insert(TD);
+ return;
+ }
FixItHint Hint;
GenerateFixForUnusedDecl(D, Context, Hint);
@@ -1481,8 +1519,14 @@ void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {
static void CheckPoppedLabel(LabelDecl *L, Sema &S) {
// Verify that we have no forward references left. If so, there was a goto
// or address of a label taken, but no definition of it. Label fwd
- // definitions are indicated with a null substmt.
- if (L->getStmt() == nullptr)
+ // definitions are indicated with a null substmt which is also not a resolved
+ // MS inline assembly label name.
+ bool Diagnose = false;
+ if (L->isMSAsmLabel())
+ Diagnose = !L->isResolvedMSAsmLabel();
+ else
+ Diagnose = L->getStmt() == nullptr;
+ if (Diagnose)
S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName();
}
@@ -1502,8 +1546,11 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (!D->getDeclName()) continue;
// Diagnose unused variables in this scope.
- if (!S->hasUnrecoverableErrorOccurred())
+ if (!S->hasUnrecoverableErrorOccurred()) {
DiagnoseUnusedDecl(D);
+ if (const auto *RD = dyn_cast<RecordDecl>(D))
+ DiagnoseUnusedNestedTypedefs(RD);
+ }
// If this was a forward reference to a label, verify it was defined.
if (LabelDecl *LD = dyn_cast<LabelDecl>(D))
@@ -1537,10 +1584,10 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
if (!IDecl && DoTypoCorrection) {
// Perform typo correction at the given location, but only if we
// find an Objective-C class name.
- DeclFilterCCC<ObjCInterfaceDecl> Validator;
- if (TypoCorrection C = CorrectTypo(DeclarationNameInfo(Id, IdLoc),
- LookupOrdinaryName, TUScope, nullptr,
- Validator, CTK_ErrorRecovery)) {
+ if (TypoCorrection C = CorrectTypo(
+ DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName, TUScope, nullptr,
+ llvm::make_unique<DeclFilterCCC<ObjCInterfaceDecl>>(),
+ CTK_ErrorRecovery)) {
diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id);
IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>();
Id = IDecl->getIdentifier();
@@ -1620,32 +1667,30 @@ static StringRef getHeaderName(ASTContext::GetBuiltinTypeError Error) {
/// file scope. lazily create a decl for it. ForRedeclaration is true
/// if we're creating this built-in in anticipation of redeclaring the
/// built-in.
-NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
+NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
Scope *S, bool ForRedeclaration,
SourceLocation Loc) {
LookupPredefedObjCSuperType(*this, S, II);
-
- Builtin::ID BID = (Builtin::ID)bid;
ASTContext::GetBuiltinTypeError Error;
- QualType R = Context.GetBuiltinType(BID, Error);
+ QualType R = Context.GetBuiltinType(ID, Error);
if (Error) {
if (ForRedeclaration)
Diag(Loc, diag::warn_implicit_decl_requires_sysheader)
<< getHeaderName(Error)
- << Context.BuiltinInfo.GetName(BID);
+ << Context.BuiltinInfo.GetName(ID);
return nullptr;
}
- if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
+ if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(ID)) {
Diag(Loc, diag::ext_implicit_lib_function_decl)
- << Context.BuiltinInfo.GetName(BID)
+ << Context.BuiltinInfo.GetName(ID)
<< R;
- if (Context.BuiltinInfo.getHeaderName(BID) &&
+ if (Context.BuiltinInfo.getHeaderName(ID) &&
!Diags.isIgnored(diag::ext_implicit_lib_function_decl, Loc))
Diag(Loc, diag::note_include_header_or_declare)
- << Context.BuiltinInfo.getHeaderName(BID)
- << Context.BuiltinInfo.GetName(BID);
+ << Context.BuiltinInfo.getHeaderName(ID)
+ << Context.BuiltinInfo.GetName(ID);
}
DeclContext *Parent = Context.getTranslationUnitDecl();
@@ -1725,6 +1770,43 @@ static void filterNonConflictingPreviousDecls(ASTContext &context,
filter.done();
}
+/// Typedef declarations don't have linkage, but they still denote the same
+/// entity if their types are the same.
+/// FIXME: This is notionally doing the same thing as ASTReaderDecl's
+/// isSameEntity.
+static void filterNonConflictingPreviousTypedefDecls(ASTContext &Context,
+ TypedefNameDecl *Decl,
+ LookupResult &Previous) {
+ // This is only interesting when modules are enabled.
+ if (!Context.getLangOpts().Modules)
+ return;
+
+ // Empty sets are uninteresting.
+ if (Previous.empty())
+ return;
+
+ LookupResult::Filter Filter = Previous.makeFilter();
+ while (Filter.hasNext()) {
+ NamedDecl *Old = Filter.next();
+
+ // Non-hidden declarations are never ignored.
+ if (!Old->isHidden())
+ continue;
+
+ // Declarations of the same entity are not ignored, even if they have
+ // different linkages.
+ if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old))
+ if (Context.hasSameType(OldTD->getUnderlyingType(),
+ Decl->getUnderlyingType()))
+ continue;
+
+ if (!Old->isExternallyVisible())
+ Filter.erase();
+ }
+
+ Filter.done();
+}
+
bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
QualType OldType;
if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
@@ -2072,6 +2154,14 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), IA->getBestCase(),
AttrSpellingListIndex,
IA->getSemanticSpelling());
+ else if (const auto *AA = dyn_cast<AlwaysInlineAttr>(Attr))
+ NewAttr = S.mergeAlwaysInlineAttr(D, AA->getRange(),
+ &S.Context.Idents.get(AA->getSpelling()),
+ AttrSpellingListIndex);
+ else if (const auto *MA = dyn_cast<MinSizeAttr>(Attr))
+ NewAttr = S.mergeMinSizeAttr(D, MA->getRange(), AttrSpellingListIndex);
+ else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr))
+ NewAttr = S.mergeOptimizeNoneAttr(D, OA->getRange(), AttrSpellingListIndex);
else if (isa<AlignedAttr>(Attr))
// AlignedAttrs are handled separately, because we need to handle all
// such attributes on a declaration at the same time.
@@ -3149,8 +3239,15 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
}
// Merge the types.
- MergeVarDeclTypes(New, Old, mergeTypeWithPrevious(*this, New, Old, Previous));
+ VarDecl *MostRecent = Old->getMostRecentDecl();
+ if (MostRecent != Old) {
+ MergeVarDeclTypes(New, MostRecent,
+ mergeTypeWithPrevious(*this, New, MostRecent, Previous));
+ if (New->isInvalidDecl())
+ return;
+ }
+ MergeVarDeclTypes(New, Old, mergeTypeWithPrevious(*this, New, Old, Previous));
if (New->isInvalidDecl())
return;
@@ -3195,12 +3292,12 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
// Check if extern is followed by non-extern and vice-versa.
if (New->hasExternalStorage() &&
- !Old->hasLinkage() && Old->isLocalVarDecl()) {
+ !Old->hasLinkage() && Old->isLocalVarDeclOrParm()) {
Diag(New->getLocation(), diag::err_extern_non_extern) << New->getDeclName();
Diag(OldLocation, PrevDiag);
return New->setInvalidDecl();
}
- if (Old->hasLinkage() && New->isLocalVarDecl() &&
+ if (Old->hasLinkage() && New->isLocalVarDeclOrParm() &&
!New->hasExternalStorage()) {
Diag(New->getLocation(), diag::err_non_extern_extern) << New->getDeclName();
Diag(OldLocation, PrevDiag);
@@ -3407,21 +3504,39 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
}
}
- // Check for Microsoft C extension: anonymous struct member.
- if (getLangOpts().MicrosoftExt && !getLangOpts().CPlusPlus &&
- CurContext->isRecord() &&
+ // C11 6.7.2.1p2:
+ // A struct-declaration that does not declare an anonymous structure or
+ // anonymous union shall contain a struct-declarator-list.
+ //
+ // This rule also existed in C89 and C99; the grammar for struct-declaration
+ // did not permit a struct-declaration without a struct-declarator-list.
+ if (!getLangOpts().CPlusPlus && CurContext->isRecord() &&
DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) {
- // Handle 2 kinds of anonymous struct:
+ // Check for Microsoft C extension: anonymous struct/union member.
+ // Handle 2 kinds of anonymous struct/union:
// struct STRUCT;
+ // union UNION;
// and
// STRUCT_TYPE; <- where STRUCT_TYPE is a typedef struct.
- RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag);
- if ((Record && Record->getDeclName() && !Record->isCompleteDefinition()) ||
- (DS.getTypeSpecType() == DeclSpec::TST_typename &&
- DS.getRepAsType().get()->isStructureType())) {
- Diag(DS.getLocStart(), diag::ext_ms_anonymous_struct)
- << DS.getSourceRange();
- return BuildMicrosoftCAnonymousStruct(S, DS, Record);
+ // UNION_TYPE; <- where UNION_TYPE is a typedef union.
+ if ((Tag && Tag->getDeclName()) ||
+ DS.getTypeSpecType() == DeclSpec::TST_typename) {
+ RecordDecl *Record = nullptr;
+ if (Tag)
+ Record = dyn_cast<RecordDecl>(Tag);
+ else if (const RecordType *RT =
+ DS.getRepAsType().get()->getAsStructureType())
+ Record = RT->getDecl();
+ else if (const RecordType *UT = DS.getRepAsType().get()->getAsUnionType())
+ Record = UT->getDecl();
+
+ if (Record && getLangOpts().MicrosoftExt) {
+ Diag(DS.getLocStart(), diag::ext_ms_anonymous_record)
+ << Record->isUnion() << DS.getSourceRange();
+ return BuildMicrosoftCAnonymousStruct(S, DS, Record);
+ }
+
+ DeclaresAnything = false;
}
}
@@ -3622,10 +3737,12 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
for (unsigned i = 0; i < Chaining.size(); i++)
NamedChain[i] = Chaining[i];
- IndirectFieldDecl* IndirectField =
- IndirectFieldDecl::Create(SemaRef.Context, Owner, VD->getLocation(),
- VD->getIdentifier(), VD->getType(),
- NamedChain, Chaining.size());
+ IndirectFieldDecl *IndirectField = IndirectFieldDecl::Create(
+ SemaRef.Context, Owner, VD->getLocation(), VD->getIdentifier(),
+ VD->getType(), NamedChain, Chaining.size());
+
+ for (const auto *Attr : VD->attrs())
+ IndirectField->addAttr(Attr->clone(SemaRef.Context));
IndirectField->setAccess(AS);
IndirectField->setImplicit();
@@ -3893,7 +4010,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
FieldCollector->Add(cast<FieldDecl>(Anon));
} else {
DeclSpec::SCS SCSpec = DS.getStorageClassSpec();
- VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(DS);
+ StorageClass SC = StorageClassSpecToVarDeclStorageClass(DS);
if (SCSpec == DeclSpec::SCS_mutable) {
// mutable can only appear on non-static class members, so it's always
// an error here
@@ -3962,28 +4079,28 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
///
/// void foo() {
/// B var;
-/// var.a = 3;
+/// var.a = 3;
/// }
///
Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
RecordDecl *Record) {
-
- // If there is no Record, get the record via the typedef.
- if (!Record)
- Record = DS.getRepAsType().get()->getAsStructureType()->getDecl();
+ assert(Record && "expected a record!");
// Mock up a declarator.
Declarator Dc(DS, Declarator::TypeNameContext);
TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
assert(TInfo && "couldn't build declarator info for anonymous struct");
+ auto *ParentDecl = cast<RecordDecl>(CurContext);
+ QualType RecTy = Context.getTypeDeclType(Record);
+
// Create a declaration for this anonymous struct.
NamedDecl *Anon = FieldDecl::Create(Context,
- cast<RecordDecl>(CurContext),
+ ParentDecl,
DS.getLocStart(),
DS.getLocStart(),
/*IdentifierInfo=*/nullptr,
- Context.getTypeDeclType(Record),
+ RecTy,
TInfo,
/*BitWidth=*/nullptr, /*Mutable=*/false,
/*InitStyle=*/ICIS_NoInit);
@@ -3999,10 +4116,13 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
Chain.push_back(Anon);
RecordDecl *RecordDef = Record->getDefinition();
- if (!RecordDef || InjectAnonymousStructOrUnionMembers(*this, S, CurContext,
- RecordDef, AS_none,
- Chain, true))
+ if (RequireCompleteType(Anon->getLocation(), RecTy,
+ diag::err_field_incomplete) ||
+ InjectAnonymousStructOrUnionMembers(*this, S, CurContext, RecordDef,
+ AS_none, Chain, true)) {
Anon->setInvalidDecl();
+ ParentDecl->setInvalidDecl();
+ }
return Anon;
}
@@ -4835,7 +4955,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
// in an outer scope, it isn't the same thing.
FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/false,
/*AllowInlineNamespace*/false);
- filterNonConflictingPreviousDecls(Context, NewTD, Previous);
+ filterNonConflictingPreviousTypedefDecls(Context, NewTD, Previous);
if (!Previous.empty()) {
Redeclaration = true;
MergeTypedefNameDecl(NewTD, Previous);
@@ -4995,14 +5115,7 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
}
// 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 (const InheritableAttr *Attr = getDLLAttr(&ND)) {
if (!ND.isExternallyVisible()) {
S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern)
<< &ND << Attr;
@@ -5064,17 +5177,22 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
}
// A redeclaration is not allowed to drop a dllimport attribute, the only
- // exception being inline function definitions.
+ // exceptions being inline function definitions, local extern declarations,
+ // and qualified friend declarations.
// NB: MSVC converts such a declaration to dllexport.
- bool IsInline = false, IsStaticDataMember = false;
+ bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;
if (const auto *VD = dyn_cast<VarDecl>(NewDecl))
// Ignore static data because out-of-line definitions are diagnosed
// separately.
IsStaticDataMember = VD->isStaticDataMember();
- else if (const auto *FD = dyn_cast<FunctionDecl>(NewDecl))
+ else if (const auto *FD = dyn_cast<FunctionDecl>(NewDecl)) {
IsInline = FD->isInlined();
+ IsQualifiedFriend = FD->getQualifier() &&
+ FD->getFriendObjectKind() == Decl::FOK_Declared;
+ }
- if (OldImportAttr && !HasNewAttr && !IsInline && !IsStaticDataMember) {
+ if (OldImportAttr && !HasNewAttr && !IsInline && !IsStaticDataMember &&
+ !NewDecl->isLocalExternDecl() && !IsQualifiedFriend) {
S.Diag(NewDecl->getLocation(),
diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
<< NewDecl << OldImportAttr;
@@ -5082,6 +5200,14 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute);
OldDecl->dropAttr<DLLImportAttr>();
NewDecl->dropAttr<DLLImportAttr>();
+ } else if (IsInline && OldImportAttr &&
+ !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ // In MinGW, seeing a function declared inline drops the dllimport attribute.
+ OldDecl->dropAttr<DLLImportAttr>();
+ NewDecl->dropAttr<DLLImportAttr>();
+ S.Diag(NewDecl->getLocation(),
+ diag::warn_dllimport_dropped_from_inline_function)
+ << NewDecl << OldImportAttr;
}
}
@@ -5222,8 +5348,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
DeclarationName Name = GetNameForDeclarator(D).getName();
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
- VarDecl::StorageClass SC =
- StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
+ 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.
@@ -5434,7 +5559,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Only C++1y supports variable templates (N3651).
Diag(D.getIdentifierLoc(),
- getLangOpts().CPlusPlus1y
+ getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_variable_template
: diag::ext_variable_template);
}
@@ -5503,22 +5628,20 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD->setLocalExternDecl();
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) {
- if (NewVD->hasLocalStorage()) {
- // C++11 [dcl.stc]p4:
- // When thread_local is applied to a variable of block scope the
- // storage-class-specifier static is implied if it does not appear
- // explicitly.
- // Core issue: 'static' is not implied if the variable is declared
- // 'extern'.
- if (SCSpec == DeclSpec::SCS_unspecified &&
- TSCS == DeclSpec::TSCS_thread_local &&
- DC->isFunctionOrMethod())
- NewVD->setTSCSpec(TSCS);
- else
- Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
- diag::err_thread_non_global)
- << DeclSpec::getSpecifierName(TSCS);
- } else if (!Context.getTargetInfo().isTLSSupported())
+ // C++11 [dcl.stc]p4:
+ // When thread_local is applied to a variable of block scope the
+ // storage-class-specifier static is implied if it does not appear
+ // explicitly.
+ // Core issue: 'static' is not implied if the variable is declared
+ // 'extern'.
+ if (NewVD->hasLocalStorage() &&
+ (SCSpec != DeclSpec::SCS_unspecified ||
+ TSCS != DeclSpec::TSCS_thread_local ||
+ !DC->isFunctionOrMethod()))
+ Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+ diag::err_thread_non_global)
+ << DeclSpec::getSpecifierName(TSCS);
+ else if (!Context.getTargetInfo().isTLSSupported())
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_unsupported);
else
@@ -6198,7 +6321,7 @@ static void ReportOverrides(Sema& S, unsigned DiagID, const CXXMethodDecl *MD,
/// AddOverriddenMethods - See if a method overrides any in the base classes,
/// and if so, check that it's a valid override and remember it.
bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
- // Look for virtual methods in base classes that this method might override.
+ // Look for methods in base classes that this method might override.
CXXBasePaths Paths;
FindOverriddenMethodData Data;
Data.Method = MD;
@@ -6320,8 +6443,6 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
assert(!Prev.isAmbiguous() &&
"Cannot have an ambiguity in previous-declaration lookup");
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
- DifferentNameValidatorCCC Validator(SemaRef.Context, NewFD,
- MD ? MD->getParent() : nullptr);
if (!Prev.empty()) {
for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
Func != FuncEnd; ++Func) {
@@ -6337,9 +6458,11 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
}
// If the qualified name lookup yielded nothing, try typo correction
} else if ((Correction = SemaRef.CorrectTypo(
- Prev.getLookupNameInfo(), Prev.getLookupKind(), S,
- &ExtraArgs.D.getCXXScopeSpec(), Validator,
- Sema::CTK_ErrorRecovery, IsLocalFriend ? nullptr : NewDC))) {
+ Prev.getLookupNameInfo(), Prev.getLookupKind(), S,
+ &ExtraArgs.D.getCXXScopeSpec(),
+ llvm::make_unique<DifferentNameValidatorCCC>(
+ SemaRef.Context, NewFD, MD ? MD->getParent() : nullptr),
+ Sema::CTK_ErrorRecovery, IsLocalFriend ? nullptr : NewDC))) {
// Set up everything for the call to ActOnFunctionDeclarator
ExtraArgs.D.SetIdentifier(Correction.getCorrectionAsIdentifierInfo(),
ExtraArgs.D.getIdentifierLoc());
@@ -6436,8 +6559,7 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
return nullptr;
}
-static FunctionDecl::StorageClass getFunctionStorageClass(Sema &SemaRef,
- Declarator &D) {
+static StorageClass getFunctionStorageClass(Sema &SemaRef, Declarator &D) {
switch (D.getDeclSpec().getStorageClassSpec()) {
default: llvm_unreachable("Unknown storage class!");
case DeclSpec::SCS_auto:
@@ -6475,7 +6597,7 @@ static FunctionDecl::StorageClass getFunctionStorageClass(Sema &SemaRef,
static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
DeclContext *DC, QualType &R,
TypeSourceInfo *TInfo,
- FunctionDecl::StorageClass SC,
+ StorageClass SC,
bool &IsVirtualOkay) {
DeclarationNameInfo NameInfo = SemaRef.GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
@@ -6500,9 +6622,6 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
if (D.isInvalidType())
NewFD->setInvalidDecl();
- // Set the lexical context.
- NewFD->setLexicalDeclContext(SemaRef.CurContext);
-
return NewFD;
}
@@ -6602,6 +6721,11 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
IsVirtualOkay = !Ret->isStatic();
return Ret;
} else {
+ bool isFriend =
+ SemaRef.getLangOpts().CPlusPlus && D.getDeclSpec().isFriendSpecified();
+ if (!isFriend && SemaRef.CurContext->isRecord())
+ return nullptr;
+
// Determine whether the function was written with a
// prototype. This true when:
// - we're in C++ (where every function has a prototype),
@@ -6655,7 +6779,7 @@ static void checkIsValidOpenCLKernelParameter(
Sema &S,
Declarator &D,
ParmVarDecl *Param,
- llvm::SmallPtrSet<const Type *, 16> &ValidTypes) {
+ llvm::SmallPtrSetImpl<const Type *> &ValidTypes) {
QualType PT = Param->getType();
// Cache the valid types we encounter to avoid rechecking structs that are
@@ -6802,7 +6926,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// TODO: consider using NameInfo for diagnostic.
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
- FunctionDecl::StorageClass SC = getFunctionStorageClass(*this, D);
+ StorageClass SC = getFunctionStorageClass(*this, D);
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec())
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
@@ -6990,12 +7114,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD->setVirtualAsWritten(true);
}
- if (getLangOpts().CPlusPlus1y &&
+ if (getLangOpts().CPlusPlus14 &&
NewFD->getReturnType()->isUndeducedType())
Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual);
}
- if (getLangOpts().CPlusPlus1y &&
+ if (getLangOpts().CPlusPlus14 &&
(NewFD->isDependentContext() ||
(isFriend && CurContext->isDependentContext())) &&
NewFD->getReturnType()->isUndeducedType()) {
@@ -7126,12 +7250,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
const FunctionProtoType *FPT = R->getAs<FunctionProtoType>();
if ((Name.getCXXOverloadedOperator() == OO_Delete ||
Name.getCXXOverloadedOperator() == OO_Array_Delete) &&
- getLangOpts().CPlusPlus11 && FPT && !FPT->hasExceptionSpec()) {
- FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- EPI.ExceptionSpecType = EST_BasicNoexcept;
- NewFD->setType(Context.getFunctionType(FPT->getReturnType(),
- FPT->getParamTypes(), EPI));
- }
+ getLangOpts().CPlusPlus11 && FPT && !FPT->hasExceptionSpec())
+ NewFD->setType(Context.getFunctionType(
+ FPT->getReturnType(), FPT->getParamTypes(),
+ FPT->getExtProtoInfo().withExceptionSpec(EST_BasicNoexcept)));
}
// Filter out previous declarations that don't match the scope.
@@ -7232,7 +7354,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
CodeSegStack.CurrentValue->getString(),
CodeSegStack.CurrentPragmaLocation));
if (UnifySection(CodeSegStack.CurrentValue->getString(),
- PSF_Implicit | PSF_Execute | PSF_Read, NewFD))
+ ASTContext::PSF_Implicit | ASTContext::PSF_Execute |
+ ASTContext::PSF_Read,
+ NewFD))
NewFD->dropAttr<SectionAttr>();
}
@@ -7283,6 +7407,22 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
assert((NewFD->isInvalidDecl() || !D.isRedeclaration() ||
Previous.getResultKind() != LookupResult::FoundOverloaded) &&
"previous declaration set still overloaded");
+
+ // Diagnose no-prototype function declarations with calling conventions that
+ // don't support variadic calls. Only do this in C and do it after merging
+ // possibly prototyped redeclarations.
+ const FunctionType *FT = NewFD->getType()->castAs<FunctionType>();
+ if (isa<FunctionNoProtoType>(FT) && !D.isFunctionDefinition()) {
+ CallingConv CC = FT->getExtInfo().getCC();
+ if (!supportsVariadicCall(CC)) {
+ // Windows system headers sometimes accidentally use stdcall without
+ // (void) parameters, so we relax this to a warning.
+ int DiagID =
+ CC == CC_X86StdCall ? diag::warn_cconv_knr : diag::err_cconv_knr;
+ Diag(NewFD->getLocation(), DiagID)
+ << FunctionType::getNameForCallConv(CC);
+ }
+ }
} else {
// C++11 [replacement.functions]p3:
// The program's definitions shall not be specified as inline.
@@ -7749,12 +7889,12 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// This rule is not present in C++1y, so we produce a backwards
// compatibility warning whenever it happens in C++11.
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
- if (!getLangOpts().CPlusPlus1y && MD && MD->isConstexpr() &&
+ if (!getLangOpts().CPlusPlus14 && MD && MD->isConstexpr() &&
!MD->isStatic() && !isa<CXXConstructorDecl>(MD) &&
(MD->getTypeQualifiers() & Qualifiers::Const) == 0) {
CXXMethodDecl *OldMD = nullptr;
if (OldDecl)
- OldMD = dyn_cast<CXXMethodDecl>(OldDecl->getAsFunction());
+ OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl->getAsFunction());
if (!OldMD || !OldMD->isStatic()) {
const FunctionProtoType *FPT =
MD->getType()->castAs<FunctionProtoType>();
@@ -7771,7 +7911,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
.IgnoreParens().getAs<FunctionTypeLoc>())
AddConstLoc = getLocForEndOfToken(FTL.getRParenLoc());
- Diag(MD->getLocation(), diag::warn_cxx1y_compat_constexpr_not_const)
+ Diag(MD->getLocation(), diag::warn_cxx14_compat_constexpr_not_const)
<< FixItHint::CreateInsertion(AddConstLoc, " const");
}
}
@@ -7838,6 +7978,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}
// Semantic checking for this function declaration (in isolation).
+
if (getLangOpts().CPlusPlus) {
// C++-specific checks.
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
@@ -7918,7 +8059,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// the function returns a UDT (class, struct, or union type) that is not C
// compatible, and if it does, warn the user.
// But, issue any diagnostic on the first declaration only.
- if (NewFD->isExternC() && Previous.empty()) {
+ if (Previous.empty() && NewFD->isExternC()) {
QualType R = NewFD->getReturnType();
if (R->isIncompleteType() && !R->isVoidType())
Diag(NewFD->getLocation(), diag::warn_return_value_udt_incomplete)
@@ -8120,6 +8261,8 @@ namespace {
bool isPODType;
bool isReferenceType;
+ bool isInitList;
+ llvm::SmallVector<unsigned, 4> InitFieldIndex;
public:
typedef EvaluatedExprVisitor<SelfReferenceChecker> Inherited;
@@ -8128,6 +8271,7 @@ namespace {
isPODType = false;
isRecordType = false;
isReferenceType = false;
+ isInitList = false;
if (ValueDecl *VD = dyn_cast<ValueDecl>(OrigDecl)) {
isPODType = VD->getType().isPODType(S.Context);
isRecordType = VD->getType()->isRecordType();
@@ -8135,25 +8279,122 @@ namespace {
}
}
+ // For most expressions, just call the visitor. For initializer lists,
+ // track the index of the field being initialized since fields are
+ // initialized in order allowing use of previously initialized fields.
+ void CheckExpr(Expr *E) {
+ InitListExpr *InitList = dyn_cast<InitListExpr>(E);
+ if (!InitList) {
+ Visit(E);
+ return;
+ }
+
+ // Track and increment the index here.
+ isInitList = true;
+ InitFieldIndex.push_back(0);
+ for (auto Child : InitList->children()) {
+ CheckExpr(cast<Expr>(Child));
+ ++InitFieldIndex.back();
+ }
+ InitFieldIndex.pop_back();
+ }
+
+ // Returns true if MemberExpr is checked and no futher checking is needed.
+ // Returns false if additional checking is required.
+ bool CheckInitListMemberExpr(MemberExpr *E, bool CheckReference) {
+ llvm::SmallVector<FieldDecl*, 4> Fields;
+ Expr *Base = E;
+ bool ReferenceField = false;
+
+ // Get the field memebers used.
+ while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) {
+ FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
+ if (!FD)
+ return false;
+ Fields.push_back(FD);
+ if (FD->getType()->isReferenceType())
+ ReferenceField = true;
+ Base = ME->getBase()->IgnoreParenImpCasts();
+ }
+
+ // Keep checking only if the base Decl is the same.
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base);
+ if (!DRE || DRE->getDecl() != OrigDecl)
+ return false;
+
+ // A reference field can be bound to an unininitialized field.
+ if (CheckReference && !ReferenceField)
+ return true;
+
+ // Convert FieldDecls to their index number.
+ llvm::SmallVector<unsigned, 4> UsedFieldIndex;
+ for (auto I = Fields.rbegin(), E = Fields.rend(); I != E; ++I) {
+ UsedFieldIndex.push_back((*I)->getFieldIndex());
+ }
+
+ // See if a warning is needed by checking the first difference in index
+ // numbers. If field being used has index less than the field being
+ // initialized, then the use is safe.
+ for (auto UsedIter = UsedFieldIndex.begin(),
+ UsedEnd = UsedFieldIndex.end(),
+ OrigIter = InitFieldIndex.begin(),
+ OrigEnd = InitFieldIndex.end();
+ UsedIter != UsedEnd && OrigIter != OrigEnd; ++UsedIter, ++OrigIter) {
+ if (*UsedIter < *OrigIter)
+ return true;
+ if (*UsedIter > *OrigIter)
+ break;
+ }
+
+ // TODO: Add a different warning which will print the field names.
+ HandleDeclRefExpr(DRE);
+ return true;
+ }
+
// For most expressions, the cast is directly above the DeclRefExpr.
// For conditional operators, the cast can be outside the conditional
// operator if both expressions are DeclRefExpr's.
void HandleValue(Expr *E) {
- if (isReferenceType)
- return;
- E = E->IgnoreParenImpCasts();
+ E = E->IgnoreParens();
if (DeclRefExpr* DRE = dyn_cast<DeclRefExpr>(E)) {
HandleDeclRefExpr(DRE);
return;
}
if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
+ Visit(CO->getCond());
HandleValue(CO->getTrueExpr());
HandleValue(CO->getFalseExpr());
return;
}
+ if (BinaryConditionalOperator *BCO =
+ dyn_cast<BinaryConditionalOperator>(E)) {
+ Visit(BCO->getCond());
+ HandleValue(BCO->getFalseExpr());
+ return;
+ }
+
+ if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
+ HandleValue(OVE->getSourceExpr());
+ return;
+ }
+
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+ if (BO->getOpcode() == BO_Comma) {
+ Visit(BO->getLHS());
+ HandleValue(BO->getRHS());
+ return;
+ }
+ }
+
if (isa<MemberExpr>(E)) {
+ if (isInitList) {
+ if (CheckInitListMemberExpr(cast<MemberExpr>(E),
+ false /*CheckReference*/))
+ return;
+ }
+
Expr *Base = E->IgnoreParenImpCasts();
while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) {
// Check for static member variables and don't warn on them.
@@ -8165,24 +8406,32 @@ namespace {
HandleDeclRefExpr(DRE);
return;
}
+
+ Visit(E);
}
- // Reference types are handled here since all uses of references are
- // bad, not just r-value uses.
+ // Reference types not handled in HandleValue are handled here since all
+ // uses of references are bad, not just r-value uses.
void VisitDeclRefExpr(DeclRefExpr *E) {
if (isReferenceType)
HandleDeclRefExpr(E);
}
void VisitImplicitCastExpr(ImplicitCastExpr *E) {
- if (E->getCastKind() == CK_LValueToRValue ||
- (isRecordType && E->getCastKind() == CK_NoOp))
+ if (E->getCastKind() == CK_LValueToRValue) {
HandleValue(E->getSubExpr());
+ return;
+ }
Inherited::VisitImplicitCastExpr(E);
}
void VisitMemberExpr(MemberExpr *E) {
+ if (isInitList) {
+ if (CheckInitListMemberExpr(E, true /*CheckReference*/))
+ return;
+ }
+
// Don't warn on arrays since they can be treated as pointers.
if (E->getType()->canDecayToPointerType()) return;
@@ -8209,11 +8458,14 @@ namespace {
}
void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
- if (E->getNumArgs() > 0)
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->getArg(0)))
- HandleDeclRefExpr(DRE);
+ Expr *Callee = E->getCallee();
- Inherited::VisitCXXOperatorCallExpr(E);
+ if (isa<UnresolvedLookupExpr>(Callee))
+ return Inherited::VisitCXXOperatorCallExpr(E);
+
+ Visit(Callee);
+ for (auto Arg: E->arguments())
+ HandleValue(Arg->IgnoreParenImpCasts());
}
void VisitUnaryOperator(UnaryOperator *E) {
@@ -8224,11 +8476,65 @@ namespace {
HandleValue(E->getSubExpr());
return;
}
+
+ if (E->isIncrementDecrementOp()) {
+ HandleValue(E->getSubExpr());
+ return;
+ }
+
Inherited::VisitUnaryOperator(E);
}
void VisitObjCMessageExpr(ObjCMessageExpr *E) { return; }
+ void VisitCXXConstructExpr(CXXConstructExpr *E) {
+ if (E->getConstructor()->isCopyConstructor()) {
+ Expr *ArgExpr = E->getArg(0);
+ if (InitListExpr *ILE = dyn_cast<InitListExpr>(ArgExpr))
+ if (ILE->getNumInits() == 1)
+ ArgExpr = ILE->getInit(0);
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgExpr))
+ if (ICE->getCastKind() == CK_NoOp)
+ ArgExpr = ICE->getSubExpr();
+ HandleValue(ArgExpr);
+ return;
+ }
+ Inherited::VisitCXXConstructExpr(E);
+ }
+
+ void VisitCallExpr(CallExpr *E) {
+ // Treat std::move as a use.
+ if (E->getNumArgs() == 1) {
+ if (FunctionDecl *FD = E->getDirectCallee()) {
+ if (FD->isInStdNamespace() && FD->getIdentifier() &&
+ FD->getIdentifier()->isStr("move")) {
+ HandleValue(E->getArg(0));
+ return;
+ }
+ }
+ }
+
+ Inherited::VisitCallExpr(E);
+ }
+
+ void VisitBinaryOperator(BinaryOperator *E) {
+ if (E->isCompoundAssignmentOp()) {
+ HandleValue(E->getLHS());
+ Visit(E->getRHS());
+ return;
+ }
+
+ Inherited::VisitBinaryOperator(E);
+ }
+
+ // A custom visitor for BinaryConditionalOperator is needed because the
+ // regular visitor would check the condition and true expression separately
+ // but both point to the same place giving duplicate diagnostics.
+ void VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
+ Visit(E->getCond());
+ Visit(E->getFalseExpr());
+ }
+
void HandleDeclRefExpr(DeclRefExpr *DRE) {
Decl* ReferenceDecl = DRE->getDecl();
if (OrigDecl != ReferenceDecl) return;
@@ -8268,7 +8574,7 @@ namespace {
if (DRE->getDecl() == OrigDecl)
return;
- SelfReferenceChecker(S, OrigDecl).Visit(E);
+ SelfReferenceChecker(S, OrigDecl).CheckExpr(E);
}
}
@@ -8279,8 +8585,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
bool DirectInit, bool TypeMayContainAuto) {
// If there is no declaration, there was an error parsing it. Just ignore
// the initializer.
- if (!RealDecl || RealDecl->isInvalidDecl())
+ if (!RealDecl || RealDecl->isInvalidDecl()) {
+ CorrectDelayedTyposInExpr(Init);
return;
+ }
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
// With declarators parsed the way they are, the parser cannot
@@ -8511,6 +8819,21 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
Args = MultiExprArg(CXXDirectInit->getExprs(),
CXXDirectInit->getNumExprs());
+ // Try to correct any TypoExprs in the initialization arguments.
+ for (size_t Idx = 0; Idx < Args.size(); ++Idx) {
+ ExprResult Res =
+ CorrectDelayedTyposInExpr(Args[Idx], [this, Entity, Kind](Expr *E) {
+ InitializationSequence Init(*this, Entity, Kind, MultiExprArg(E));
+ return Init.Failed() ? ExprError() : E;
+ });
+ if (Res.isInvalid()) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+ if (Res.get() != Args[Idx])
+ Args[Idx] = Res.get();
+ }
+
InitializationSequence InitSeq(*this, Entity, Kind, Args);
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT);
if (Result.isInvalid()) {
@@ -9124,15 +9447,15 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
if (var->isThisDeclarationADefinition() &&
ActiveTemplateInstantiations.empty()) {
PragmaStack<StringLiteral *> *Stack = nullptr;
- int SectionFlags = PSF_Implicit | PSF_Read;
+ int SectionFlags = ASTContext::PSF_Implicit | ASTContext::PSF_Read;
if (var->getType().isConstQualified())
Stack = &ConstSegStack;
else if (!var->getInit()) {
Stack = &BSSSegStack;
- SectionFlags |= PSF_Write;
+ SectionFlags |= ASTContext::PSF_Write;
} else {
Stack = &DataSegStack;
- SectionFlags |= PSF_Write;
+ SectionFlags |= ASTContext::PSF_Write;
}
if (!var->hasAttr<SectionAttr>() && Stack->CurrentValue)
var->addAttr(
@@ -9244,7 +9567,7 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
// Static locals inherit dll attributes from their function.
if (VD->isStaticLocal()) {
if (FunctionDecl *FD =
- dyn_cast<FunctionDecl>(VD->getParentFunctionOrMethod())) {
+ dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod())) {
if (Attr *A = getDLLAttr(FD)) {
auto *NewAttr = cast<InheritableAttr>(A->clone(getASTContext()));
NewAttr->setInherited(true);
@@ -9253,8 +9576,11 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
}
}
+ // Grab the dllimport or dllexport attribute off of the VarDecl.
+ const InheritableAttr *DLLAttr = getDLLAttr(VD);
+
// Imported static data members cannot be defined out-of-line.
- if (const DLLImportAttr *IA = VD->getAttr<DLLImportAttr>()) {
+ if (const auto *IA = dyn_cast_or_null<DLLImportAttr>(DLLAttr)) {
if (VD->isStaticDataMember() && VD->isOutOfLine() &&
VD->isThisDeclarationADefinition()) {
// We allow definitions of dllimport class template static data members
@@ -9275,6 +9601,14 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
}
}
+ // dllimport/dllexport variables cannot be thread local, their TLS index
+ // isn't exported with the variable.
+ if (DLLAttr && VD->getTLSKind()) {
+ Diag(VD->getLocation(), diag::err_attribute_dll_thread_local) << VD
+ << DLLAttr;
+ VD->setInvalidDecl();
+ }
+
if (UsedAttr *Attr = VD->getAttr<UsedAttr>()) {
if (!Attr->isInherited() && !VD->isThisDeclarationADefinition()) {
Diag(Attr->getLocation(), diag::warn_attribute_ignored) << Attr;
@@ -9466,12 +9800,12 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
// C++03 [dcl.stc]p2 also permits 'auto'.
- VarDecl::StorageClass StorageClass = SC_None;
+ StorageClass SC = SC_None;
if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
- StorageClass = SC_Register;
+ SC = SC_Register;
} else if (getLangOpts().CPlusPlus &&
DS.getStorageClassSpec() == DeclSpec::SCS_auto) {
- StorageClass = SC_Auto;
+ SC = SC_Auto;
} else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
Diag(DS.getStorageClassSpecLoc(),
diag::err_invalid_storage_class_in_func_decl);
@@ -9545,7 +9879,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
D.getLocStart(),
D.getIdentifierLoc(), II,
parmDeclType, TInfo,
- StorageClass);
+ SC);
if (D.isInvalidType())
New->setInvalidDecl();
@@ -9637,7 +9971,7 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param,
ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
SourceLocation NameLoc, IdentifierInfo *Name,
QualType T, TypeSourceInfo *TSInfo,
- VarDecl::StorageClass StorageClass) {
+ StorageClass SC) {
// In ARC, infer a lifetime qualifier for appropriate parameter types.
if (getLangOpts().ObjCAutoRefCount &&
T.getObjCLifetime() == Qualifiers::OCL_None &&
@@ -9663,8 +9997,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name,
Context.getAdjustedParameterType(T),
- TSInfo,
- StorageClass, nullptr);
+ TSInfo, SC, nullptr);
// Parameters can not be abstract class types.
// For record types, this is done by the AbstractClassUsageDiagnoser once
@@ -9850,6 +10183,7 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
// Add the captures to the LSI so they can be noted as already
// captured within tryCaptureVar.
+ auto I = LambdaClass->field_begin();
for (const auto &C : LambdaClass->captures()) {
if (C.capturesVariable()) {
VarDecl *VD = C.getCapturedVar();
@@ -9858,7 +10192,7 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
QualType CaptureType = VD->getType();
const bool ByRef = C.getCaptureKind() == LCK_ByRef;
LSI->addCapture(VD, /*IsBlock*/false, ByRef,
- /*RefersToEnclosingLocal*/true, C.getLocation(),
+ /*RefersToEnclosingVariableOrCapture*/true, C.getLocation(),
/*EllipsisLoc*/C.isPackExpansion()
? C.getEllipsisLoc() : SourceLocation(),
CaptureType, /*Expr*/ nullptr);
@@ -9866,7 +10200,10 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
} else if (C.capturesThis()) {
LSI->addThisCapture(/*Nested*/ false, C.getLocation(),
S.getCurrentThisType(), /*Expr*/ nullptr);
+ } else {
+ LSI->addVLATypeCapture(C.getLocation(), I->getType());
}
+ ++I;
}
}
@@ -10107,7 +10444,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (FD) {
FD->setBody(Body);
- if (getLangOpts().CPlusPlus1y && !FD->isInvalidDecl() && Body &&
+ if (getLangOpts().CPlusPlus14 && !FD->isInvalidDecl() && Body &&
!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
@@ -10118,8 +10455,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
FD->setInvalidDecl();
} else {
// Substitute 'void' for the 'auto' in the type.
- TypeLoc ResultType = FD->getTypeSourceInfo()->getTypeLoc().
- IgnoreParens().castAs<FunctionProtoTypeLoc>().getReturnLoc();
+ TypeLoc ResultType = getReturnTypeLoc(FD);
Context.adjustDeducedFunctionResultType(
FD, SubstAutoType(ResultType.getType(), Context.VoidTy));
}
@@ -10154,9 +10490,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(),
FD->getReturnType(), FD);
- // If this is a constructor, we need a vtable.
+ // If this is a structor, we need a vtable.
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD))
MarkVTableUsed(FD->getLocation(), Constructor->getParent());
+ else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(FD))
+ MarkVTableUsed(FD->getLocation(), Destructor->getParent());
// Try to apply the named return value optimization. We have to check
// if we can do this here because lambdas keep return statements around
@@ -10265,7 +10603,19 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
!CheckConstexprFunctionBody(FD, Body)))
FD->setInvalidDecl();
- assert(ExprCleanupObjects.empty() && "Leftover temporaries in function");
+ if (FD && FD->hasAttr<NakedAttr>()) {
+ for (const Stmt *S : Body->children()) {
+ if (!isa<AsmStmt>(S) && !isa<NullStmt>(S)) {
+ Diag(S->getLocStart(), diag::err_non_asm_stmt_in_naked_function);
+ Diag(FD->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
+ FD->setInvalidDecl();
+ break;
+ }
+ }
+ }
+
+ assert(ExprCleanupObjects.size() == ExprEvalContexts.back().NumCleanupObjects
+ && "Leftover temporaries in function");
assert(!ExprNeedsCleanups && "Unaccounted cleanups in function");
assert(MaybeODRUseExprs.empty() &&
"Leftover expressions for odr-use checking");
@@ -10329,10 +10679,10 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
// function declaration is going to be treated as an error.
if (Diags.getDiagnosticLevel(diag_id, Loc) >= DiagnosticsEngine::Error) {
TypoCorrection Corrected;
- DeclFilterCCC<FunctionDecl> Validator;
- if (S && (Corrected = CorrectTypo(DeclarationNameInfo(&II, Loc),
- LookupOrdinaryName, S, nullptr, Validator,
- CTK_NonError)))
+ if (S &&
+ (Corrected = CorrectTypo(
+ DeclarationNameInfo(&II, Loc), LookupOrdinaryName, S, nullptr,
+ llvm::make_unique<DeclFilterCCC<FunctionDecl>>(), CTK_NonError)))
diagnoseTypo(Corrected, PDiag(diag::note_function_suggestion),
/*ErrorRecovery*/false);
}
@@ -10360,6 +10710,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
/*RefQualifierLoc=*/NoLoc,
/*ConstQualifierLoc=*/NoLoc,
/*VolatileQualifierLoc=*/NoLoc,
+ /*RestrictQualifierLoc=*/NoLoc,
/*MutableLoc=*/NoLoc,
EST_None,
/*ESpecLoc=*/NoLoc,
@@ -10367,6 +10718,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
/*NoexceptExpr=*/nullptr,
+ /*ExceptionSpecTokens=*/nullptr,
Loc, Loc, D),
DS.getAttributes(),
SourceLocation());
@@ -11262,9 +11614,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
} else {
// If the type is currently being defined, complain
// about a nested redefinition.
- const TagType *Tag
- = cast<TagType>(Context.getTagDeclType(PrevTagDecl));
- if (Tag->isBeingDefined()) {
+ auto *TD = Context.getTagDeclType(PrevTagDecl)->getAsTagDecl();
+ if (TD->isBeingDefined()) {
Diag(NameLoc, diag::err_nested_redefinition) << Name;
Diag(PrevTagDecl->getLocation(),
diag::note_previous_definition);
@@ -11454,7 +11805,7 @@ CreateNewDecl:
// CheckMemberSpecialization, below.
if (!isExplicitSpecialization &&
(TUK == TUK_Definition || TUK == TUK_Declaration) &&
- diagnoseQualifiedDeclaration(SS, DC, OrigName, NameLoc))
+ diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc))
Invalid = true;
New->setQualifierInfo(SS.getWithLocInContext(Context));
@@ -12430,8 +12781,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
continue;
}
// Okay, we have a legal flexible array member at the end of the struct.
- if (Record)
- Record->setHasFlexibleArrayMember(true);
+ Record->setHasFlexibleArrayMember(true);
} else if (!FDTy->isDependentType() &&
RequireCompleteType(FD->getLocation(), FD->getType(),
diag::err_field_incomplete)) {
@@ -12440,11 +12790,11 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
EnclosingDecl->setInvalidDecl();
continue;
} else if (const RecordType *FDTTy = FDTy->getAs<RecordType>()) {
- if (FDTTy->getDecl()->hasFlexibleArrayMember()) {
- // If this is a member of a union, then entire union becomes "flexible".
- if (Record && Record->isUnion()) {
- Record->setHasFlexibleArrayMember(true);
- } else {
+ if (Record && FDTTy->getDecl()->hasFlexibleArrayMember()) {
+ // A type which contains a flexible array member is considered to be a
+ // flexible array member.
+ Record->setHasFlexibleArrayMember(true);
+ if (!Record->isUnion()) {
// If this is a struct/class and this is not the last element, reject
// it. Note that GCC supports variable sized arrays in the middle of
// structures.
@@ -12456,8 +12806,6 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
// other structs as an extension.
Diag(FD->getLocation(), diag::ext_flexible_array_in_struct)
<< FD->getDeclName();
- if (Record)
- Record->setHasFlexibleArrayMember(true);
}
}
}
@@ -13171,6 +13519,49 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
}
}
+bool
+Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
+ bool AllowMask) const {
+ FlagEnumAttr *FEAttr = ED->getAttr<FlagEnumAttr>();
+ assert(FEAttr && "looking for value in non-flag enum");
+
+ llvm::APInt FlagMask = ~FEAttr->getFlagBits();
+ unsigned Width = FlagMask.getBitWidth();
+
+ // We will try a zero-extended value for the regular check first.
+ llvm::APInt ExtVal = Val.zextOrSelf(Width);
+
+ // A value is in a flag enum if either its bits are a subset of the enum's
+ // flag bits (the first condition) or we are allowing masks and the same is
+ // true of its complement (the second condition). When masks are allowed, we
+ // allow the common idiom of ~(enum1 | enum2) to be a valid enum value.
+ //
+ // While it's true that any value could be used as a mask, the assumption is
+ // that a mask will have all of the insignificant bits set. Anything else is
+ // likely a logic error.
+ if (!(FlagMask & ExtVal))
+ return true;
+
+ if (AllowMask) {
+ // Try a one-extended value instead. This can happen if the enum is wider
+ // than the constant used, in C with extensions to allow for wider enums.
+ // The mask will still have the correct behaviour, so we give the user the
+ // benefit of the doubt.
+ //
+ // FIXME: This heuristic can cause weird results if the enum was extended
+ // to a larger type and is signed, because then bit-masks of smaller types
+ // that get extended will fall out of range (e.g. ~0x1u). We currently don't
+ // detect that case and will get a false positive for it. In most cases,
+ // though, it can be fixed by making it a signed type (e.g. ~0x1), so it may
+ // be fine just to accept this as a warning.
+ ExtVal |= llvm::APInt::getHighBitsSet(Width, Width - Val.getBitWidth());
+ if (!(FlagMask & ~ExtVal))
+ return true;
+ }
+
+ return false;
+}
+
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
SourceLocation RBraceLoc, Decl *EnumDeclX,
ArrayRef<Decl *> Elements,
@@ -13256,10 +13647,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
BestPromotionType = Context.getPromotedIntegerType(BestType);
else
BestPromotionType = BestType;
- // We don't need to set BestWidth, because BestType is going to be the type
- // of the enumerators, but we do anyway because otherwise some compilers
- // warn that it might be used uninitialized.
- BestWidth = CharWidth;
+
+ BestWidth = Context.getIntWidth(BestType);
}
else if (NumNegativeBits) {
// If there is a negative value, figure out the smallest integer type (of
@@ -13324,10 +13713,15 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
}
}
+ FlagEnumAttr *FEAttr = Enum->getAttr<FlagEnumAttr>();
+ if (FEAttr)
+ FEAttr->getFlagBits() = llvm::APInt(BestWidth, 0);
+
// Loop over all of the enumerator constants, changing their types to match
- // the type of the enum if needed.
- for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
- EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]);
+ // the type of the enum if needed. If we have a flag type, we also prepare the
+ // FlagBits cache.
+ for (auto *D : Elements) {
+ auto *ECD = cast_or_null<EnumConstantDecl>(D);
if (!ECD) continue; // Already issued a diagnostic.
// Standard C says the enumerators have int type, but we allow, as an
@@ -13357,7 +13751,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
// enum-specifier, each enumerator has the type of its
// enumeration.
ECD->setType(EnumType);
- continue;
+ goto flagbits;
} else {
NewTy = BestType;
NewWidth = BestWidth;
@@ -13384,8 +13778,32 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
ECD->setType(EnumType);
else
ECD->setType(NewTy);
+
+flagbits:
+ // Check to see if we have a constant with exactly one bit set. Note that x
+ // & (x - 1) will be nonzero if and only if x has more than one bit set.
+ if (FEAttr) {
+ llvm::APInt ExtVal = InitVal.zextOrSelf(BestWidth);
+ if (ExtVal != 0 && !(ExtVal & (ExtVal - 1))) {
+ FEAttr->getFlagBits() |= ExtVal;
+ }
+ }
}
+ if (FEAttr) {
+ for (Decl *D : Elements) {
+ EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(D);
+ if (!ECD) continue; // Already issued a diagnostic.
+
+ llvm::APSInt InitVal = ECD->getInitVal();
+ if (InitVal != 0 && !IsValueInFlagEnum(Enum, InitVal, true))
+ Diag(ECD->getLocation(), diag::warn_flag_enum_constant_out_of_range)
+ << ECD << Enum;
+ }
+ }
+
+
+
Enum->completeDefinition(BestType, BestPromotionType,
NumPositiveBits, NumNegativeBits);
@@ -13455,6 +13873,9 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
if (Mod->getTopLevelModuleName() == getLangOpts().CurrentModule)
Diag(ImportLoc, diag::err_module_self_import)
<< Mod->getFullModuleName() << getLangOpts().CurrentModule;
+ else if (Mod->getTopLevelModuleName() == getLangOpts().ImplementationOfModule)
+ Diag(ImportLoc, diag::err_module_import_in_implementation)
+ << Mod->getFullModuleName() << getLangOpts().ImplementationOfModule;
SmallVector<SourceLocation, 2> IdentifierLocs;
Module *ModCheck = Mod;
@@ -13575,5 +13996,6 @@ AvailabilityResult Sema::getCurContextAvailability() const {
dyn_cast<ObjCImplementationDecl>(D)) {
D = ID->getClassInterface();
}
- return D->getAvailability();
+ // Recover from user error.
+ return D ? D->getAvailability() : AR_Available;
}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 61683cd87579..17a849ea7af0 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -29,6 +29,7 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/MathExtras.h"
using namespace clang;
using namespace sema;
@@ -88,21 +89,39 @@ static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
}
+static SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ return FD->getParamDecl(Idx)->getSourceRange();
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
+ return MD->parameters()[Idx]->getSourceRange();
+ if (const auto *BD = dyn_cast<BlockDecl>(D))
+ return BD->getParamDecl(Idx)->getSourceRange();
+ return SourceRange();
+}
+
static QualType getFunctionOrMethodResultType(const Decl *D) {
if (const FunctionType *FnTy = D->getFunctionType())
return cast<FunctionType>(FnTy)->getReturnType();
return cast<ObjCMethodDecl>(D)->getReturnType();
}
+static SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ return FD->getReturnTypeSourceRange();
+ if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
+ return MD->getReturnTypeSourceRange();
+ return SourceRange();
+}
+
static bool isFunctionOrMethodVariadic(const Decl *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))
- return BD->isVariadic();
- else {
- return cast<ObjCMethodDecl>(D)->isVariadic();
}
+ if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ return BD->isVariadic();
+
+ return cast<ObjCMethodDecl>(D)->isVariadic();
}
static bool isInstanceMethod(const Decl *D) {
@@ -148,30 +167,43 @@ static unsigned getNumAttributeArgs(const AttributeList &Attr) {
return Attr.getNumArgs() + Attr.hasParsedType();
}
-/// \brief Check if the attribute has exactly as many args as Num. May
-/// output an error.
-static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr,
- unsigned Num) {
- if (getNumAttributeArgs(Attr) != Num) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << Num;
+template <typename Compare>
+static bool checkAttributeNumArgsImpl(Sema &S, const AttributeList &Attr,
+ unsigned Num, unsigned Diag,
+ Compare Comp) {
+ if (Comp(getNumAttributeArgs(Attr), Num)) {
+ S.Diag(Attr.getLoc(), Diag) << Attr.getName() << Num;
return false;
}
return true;
}
+/// \brief Check if the attribute has exactly as many args as Num. May
+/// output an error.
+static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr,
+ unsigned Num) {
+ return checkAttributeNumArgsImpl(S, Attr, Num,
+ diag::err_attribute_wrong_number_arguments,
+ std::not_equal_to<unsigned>());
+}
+
/// \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)
- << Attr.getName() << Num;
- return false;
- }
+ return checkAttributeNumArgsImpl(S, Attr, Num,
+ diag::err_attribute_too_few_arguments,
+ std::less<unsigned>());
+}
- return true;
+/// \brief Check if the attribute has at most as many args as Num. May
+/// output an error.
+static bool checkAttributeAtMostNumArgs(Sema &S, const AttributeList &Attr,
+ unsigned Num) {
+ return checkAttributeNumArgsImpl(S, Attr, Num,
+ diag::err_attribute_too_many_arguments,
+ std::greater<unsigned>());
}
/// \brief If Expr is a valid integer constant, get the value of the integer
@@ -192,6 +224,13 @@ static bool checkUInt32Argument(Sema &S, const AttributeList &Attr,
<< Expr->getSourceRange();
return false;
}
+
+ if (!I.isIntN(32)) {
+ S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)
+ << I.toString(10, false) << 32 << /* Unsigned */ 1;
+ return false;
+ }
+
Val = (uint32_t)I.getZExtValue();
return true;
}
@@ -528,10 +567,6 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
// Attribute Implementations
//===----------------------------------------------------------------------===//
-// FIXME: All this manual attribute parsing code is gross. At the
-// least add some helper functions to check most argument patterns (#
-// and types of args).
-
static void handlePtGuardedVarAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!threadSafetyCheckIsPointer(S, D, Attr))
@@ -706,11 +741,9 @@ static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
return;
- D->addAttr(::new (S.Context)
- ExclusiveTrylockFunctionAttr(Attr.getRange(), S.Context,
- Attr.getArgAsExpr(0),
- Args.data(), Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(
+ Attr.getRange(), S.Context, Attr.getArgAsExpr(0), Args.data(),
+ Args.size(), Attr.getAttributeSpellingListIndex()));
}
static void handleLockReturnedAttr(Sema &S, Decl *D,
@@ -828,8 +861,14 @@ static void handleCallableWhenAttr(Sema &S, Decl *D,
StringRef StateString;
SourceLocation Loc;
- if (!S.checkStringLiteralArgumentAttr(Attr, ArgIndex, StateString, &Loc))
- return;
+ if (Attr.isArgIdent(ArgIndex)) {
+ IdentifierLoc *Ident = Attr.getArgAsIdent(ArgIndex);
+ StateString = Ident->Ident->getName();
+ Loc = Ident->Loc;
+ } else {
+ if (!S.checkStringLiteralArgumentAttr(Attr, ArgIndex, StateString, &Loc))
+ return;
+ }
if (!CallableWhenAttr::ConvertStrToConsumedState(StateString,
CallableState)) {
@@ -849,8 +888,6 @@ static void handleCallableWhenAttr(Sema &S, Decl *D,
static void handleParamTypestateAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (!checkAttributeNumArgs(S, Attr, 1)) return;
-
ParamTypestateAttr::ConsumedState ParamState;
if (Attr.isArgIdent(0)) {
@@ -889,8 +926,6 @@ static void handleParamTypestateAttr(Sema &S, Decl *D,
static void handleReturnTypestateAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (!checkAttributeNumArgs(S, Attr, 1)) return;
-
ReturnTypestateAttr::ConsumedState ReturnState;
if (Attr.isArgIdent(0)) {
@@ -939,9 +974,6 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D,
static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkAttributeNumArgs(S, Attr, 1))
- return;
-
if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
return;
@@ -967,9 +999,6 @@ static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr)
static void handleTestTypestateAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (!checkAttributeNumArgs(S, Attr, 1))
- return;
-
if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
return;
@@ -1101,30 +1130,39 @@ static void handleIBOutletCollection(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
-static void possibleTransparentUnionPointerType(QualType &T) {
- if (const RecordType *UT = T->getAsUnionType())
+bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) {
+ if (RefOkay) {
+ if (T->isReferenceType())
+ return true;
+ } else {
+ T = T.getNonReferenceType();
+ }
+
+ // The nonnull attribute, and other similar attributes, can be applied to a
+ // transparent union that contains a pointer type.
+ if (const RecordType *UT = T->getAsUnionType()) {
if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
RecordDecl *UD = UT->getDecl();
for (const auto *I : UD->fields()) {
QualType QT = I->getType();
- if (QT->isAnyPointerType() || QT->isBlockPointerType()) {
- T = QT;
- return;
- }
+ if (QT->isAnyPointerType() || QT->isBlockPointerType())
+ return true;
}
}
+ }
+
+ return T->isAnyPointerType() || T->isBlockPointerType();
}
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;
+ SourceRange AttrParmRange,
+ SourceRange TypeRange,
+ bool isReturnValue = false) {
+ if (!S.isValidPointerAttrType(T)) {
+ S.Diag(Attr.getLoc(), isReturnValue
+ ? diag::warn_attribute_return_pointers_only
+ : diag::warn_attribute_pointers_only)
+ << Attr.getName() << AttrParmRange << TypeRange;
return false;
}
return true;
@@ -1132,46 +1170,45 @@ static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr,
static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
SmallVector<unsigned, 8> NonNullArgs;
- for (unsigned i = 0; i < Attr.getNumArgs(); ++i) {
- Expr *Ex = Attr.getArgAsExpr(i);
+ for (unsigned I = 0; I < Attr.getNumArgs(); ++I) {
+ Expr *Ex = Attr.getArgAsExpr(I);
uint64_t Idx;
- if (!checkFunctionOrMethodParameterIndex(S, D, Attr, i + 1, Ex, Idx))
+ if (!checkFunctionOrMethodParameterIndex(S, D, Attr, I + 1, Ex, Idx))
return;
// Is the function argument a pointer type?
- // FIXME: Should also highlight argument in decl in the diagnostic.
- if (!attrNonNullArgCheck(S, getFunctionOrMethodParamType(D, Idx), Attr,
- Ex->getSourceRange()))
+ if (Idx < getFunctionOrMethodNumParams(D) &&
+ !attrNonNullArgCheck(S, getFunctionOrMethodParamType(D, Idx), Attr,
+ Ex->getSourceRange(),
+ getFunctionOrMethodParamRange(D, Idx)))
continue;
NonNullArgs.push_back(Idx);
}
// If no arguments were specified to __attribute__((nonnull)) then all pointer
- // arguments have a nonnull attribute.
- if (NonNullArgs.empty()) {
- 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);
+ // arguments have a nonnull attribute; warn if there aren't any. Skip this
+ // check if the attribute came from a macro expansion or a template
+ // instantiation.
+ if (NonNullArgs.empty() && Attr.getLoc().isFileID() &&
+ S.ActiveTemplateInstantiations.empty()) {
+ bool AnyPointers = isFunctionOrMethodVariadic(D);
+ for (unsigned I = 0, E = getFunctionOrMethodNumParams(D);
+ I != E && !AnyPointers; ++I) {
+ QualType T = getFunctionOrMethodParamType(D, I);
+ if (T->isDependentType() || S.isValidPointerAttrType(T))
+ AnyPointers = true;
}
- // No pointer arguments?
- if (NonNullArgs.empty()) {
- // Warn the trivial case only if attribute is not coming from a
- // macro instantiation.
- if (Attr.getLoc().isFileID())
- S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
- return;
- }
+ if (!AnyPointers)
+ S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
}
- unsigned *start = &NonNullArgs[0];
- unsigned size = NonNullArgs.size();
- llvm::array_pod_sort(start, start + size);
+ unsigned *Start = NonNullArgs.data();
+ unsigned Size = NonNullArgs.size();
+ llvm::array_pod_sort(Start, Start + Size);
D->addAttr(::new (S.Context)
- NonNullAttr(Attr.getRange(), S.Context, start, size,
+ NonNullAttr(Attr.getRange(), S.Context, Start, Size,
Attr.getAttributeSpellingListIndex()));
}
@@ -1188,7 +1225,8 @@ static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D,
}
// Is the argument a pointer type?
- if (!attrNonNullArgCheck(S, D->getType(), Attr, D->getSourceRange()))
+ if (!attrNonNullArgCheck(S, D->getType(), Attr, SourceRange(),
+ D->getSourceRange()))
return;
D->addAttr(::new (S.Context)
@@ -1199,7 +1237,8 @@ static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D,
static void handleReturnsNonNullAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
QualType ResultType = getFunctionOrMethodResultType(D);
- if (!attrNonNullArgCheck(S, ResultType, Attr, Attr.getRange(),
+ SourceRange SR = getFunctionOrMethodResultSourceRange(D);
+ if (!attrNonNullArgCheck(S, ResultType, Attr, SourceRange(), SR,
/* isReturnValue */ true))
return;
@@ -1208,6 +1247,65 @@ static void handleReturnsNonNullAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+static void handleAssumeAlignedAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ Expr *E = Attr.getArgAsExpr(0),
+ *OE = Attr.getNumArgs() > 1 ? Attr.getArgAsExpr(1) : nullptr;
+ S.AddAssumeAlignedAttr(Attr.getRange(), D, E, OE,
+ Attr.getAttributeSpellingListIndex());
+}
+
+void Sema::AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
+ Expr *OE, unsigned SpellingListIndex) {
+ QualType ResultType = getFunctionOrMethodResultType(D);
+ SourceRange SR = getFunctionOrMethodResultSourceRange(D);
+
+ AssumeAlignedAttr TmpAttr(AttrRange, Context, E, OE, SpellingListIndex);
+ SourceLocation AttrLoc = AttrRange.getBegin();
+
+ if (!isValidPointerAttrType(ResultType, /* RefOkay */ true)) {
+ Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only)
+ << &TmpAttr << AttrRange << SR;
+ return;
+ }
+
+ if (!E->isValueDependent()) {
+ llvm::APSInt I(64);
+ if (!E->isIntegerConstantExpr(I, Context)) {
+ if (OE)
+ Diag(AttrLoc, diag::err_attribute_argument_n_type)
+ << &TmpAttr << 1 << AANT_ArgumentIntegerConstant
+ << E->getSourceRange();
+ else
+ Diag(AttrLoc, diag::err_attribute_argument_type)
+ << &TmpAttr << AANT_ArgumentIntegerConstant
+ << E->getSourceRange();
+ return;
+ }
+
+ if (!I.isPowerOf2()) {
+ Diag(AttrLoc, diag::err_alignment_not_power_of_two)
+ << E->getSourceRange();
+ return;
+ }
+ }
+
+ if (OE) {
+ if (!OE->isValueDependent()) {
+ llvm::APSInt I(64);
+ if (!OE->isIntegerConstantExpr(I, Context)) {
+ Diag(AttrLoc, diag::err_attribute_argument_n_type)
+ << &TmpAttr << 2 << AANT_ArgumentIntegerConstant
+ << OE->getSourceRange();
+ return;
+ }
+ }
+ }
+
+ D->addAttr(::new (Context)
+ AssumeAlignedAttr(AttrRange, Context, E, OE, SpellingListIndex));
+}
+
static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
// This attribute must be applied to a function declaration. The first
// argument to the attribute must be an identifier, the name of the resource,
@@ -1286,13 +1384,26 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
// Check we don't have a conflict with another ownership attribute.
for (const auto *I : D->specific_attrs<OwnershipAttr>()) {
- // FIXME: A returns attribute should conflict with any returns attribute
- // with a different index too.
+ // Cannot have two ownership attributes of different kinds for the same
+ // index.
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() << I;
return;
+ } else if (K == OwnershipAttr::Returns &&
+ I->getOwnKind() == OwnershipAttr::Returns) {
+ // A returns attribute conflicts with any other returns attribute using
+ // a different index. Note, diagnostic reporting is 1-based, but stored
+ // argument indexes are 0-based.
+ if (std::find(I->args_begin(), I->args_end(), Idx) == I->args_end()) {
+ S.Diag(I->getLocation(), diag::err_ownership_returns_index_mismatch)
+ << *(I->args_begin()) + 1;
+ if (I->args_size())
+ S.Diag(AL.getLoc(), diag::note_ownership_returns_index_mismatch)
+ << (unsigned)Idx + 1 << Ex->getSourceRange();
+ return;
+ }
}
}
OwnershipArgs.push_back(Idx);
@@ -1586,15 +1697,8 @@ static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
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)
- << Attr.getName() << 1;
- return;
- }
-
uint32_t priority = ConstructorAttr::DefaultPriority;
- if (Attr.getNumArgs() > 0 &&
+ if (Attr.getNumArgs() &&
!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
return;
@@ -1604,15 +1708,8 @@ static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
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)
- << Attr.getName() << 1;
- return;
- }
-
uint32_t priority = DestructorAttr::DefaultPriority;
- if (Attr.getNumArgs() > 0 &&
+ if (Attr.getNumArgs() &&
!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
return;
@@ -1624,16 +1721,9 @@ static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
template <typename AttrTy>
static void handleAttrWithMessage(Sema &S, Decl *D,
const AttributeList &Attr) {
- unsigned NumArgs = Attr.getNumArgs();
- if (NumArgs > 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
- << Attr.getName() << 1;
- return;
- }
-
// Handle the case where the attribute has a text message.
StringRef Str;
- if (NumArgs == 1 && !S.checkStringLiteralArgumentAttr(Attr, 0, Str))
+ if (Attr.getNumArgs() == 1 && !S.checkStringLiteralArgumentAttr(Attr, 0, Str))
return;
D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str,
@@ -2036,13 +2126,6 @@ static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
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)
- << Attr.getName() << 2;
- return;
- }
-
unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel;
if (Attr.getNumArgs() > 0) {
Expr *E = Attr.getArgAsExpr(0);
@@ -2349,10 +2432,9 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
!isCFStringType(Ty, S.Context) &&
(!Ty->isPointerType() ||
!Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
- // FIXME: Should highlight the actual expression that has the wrong type.
S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
- << (not_nsstring_type ? "a string type" : "an NSString")
- << IdxExpr->getSourceRange();
+ << (not_nsstring_type ? "a string type" : "an NSString")
+ << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0);
return;
}
Ty = getFunctionOrMethodResultType(D);
@@ -2360,10 +2442,9 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
!isCFStringType(Ty, S.Context) &&
(!Ty->isPointerType() ||
!Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
- // FIXME: Should highlight the actual expression that has the wrong type.
S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not)
- << (not_nsstring_type ? "string type" : "NSString")
- << IdxExpr->getSourceRange();
+ << (not_nsstring_type ? "string type" : "NSString")
+ << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0);
return;
}
@@ -2534,23 +2615,24 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (Kind == CFStringFormat) {
if (!isCFStringType(Ty, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
- << "a CFString" << IdxExpr->getSourceRange();
+ << "a CFString" << IdxExpr->getSourceRange()
+ << getFunctionOrMethodParamRange(D, ArgIdx);
return;
}
} else if (Kind == NSStringFormat) {
// FIXME: do we need to check if the type is NSString*? What are the
// semantics?
if (!isNSStringType(Ty, S.Context)) {
- // FIXME: Should highlight the actual expression that has the wrong type.
S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
- << "an NSString" << IdxExpr->getSourceRange();
+ << "an NSString" << IdxExpr->getSourceRange()
+ << getFunctionOrMethodParamRange(D, ArgIdx);
return;
}
} else if (!Ty->isPointerType() ||
!Ty->getAs<PointerType>()->getPointeeType()->isCharType()) {
- // FIXME: Should highlight the actual expression that has the wrong type.
S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
- << "a string type" << IdxExpr->getSourceRange();
+ << "a string type" << IdxExpr->getSourceRange()
+ << getFunctionOrMethodParamRange(D, ArgIdx);
return;
}
@@ -2679,6 +2761,58 @@ static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
+static void handleAlignValueAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ S.AddAlignValueAttr(Attr.getRange(), D, Attr.getArgAsExpr(0),
+ Attr.getAttributeSpellingListIndex());
+}
+
+void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
+ unsigned SpellingListIndex) {
+ AlignValueAttr TmpAttr(AttrRange, Context, E, SpellingListIndex);
+ SourceLocation AttrLoc = AttrRange.getBegin();
+
+ QualType T;
+ if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
+ T = TD->getUnderlyingType();
+ else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
+ T = VD->getType();
+ else
+ llvm_unreachable("Unknown decl type for align_value");
+
+ if (!T->isDependentType() && !T->isAnyPointerType() &&
+ !T->isReferenceType() && !T->isMemberPointerType()) {
+ Diag(AttrLoc, diag::warn_attribute_pointer_or_reference_only)
+ << &TmpAttr /*TmpAttr.getName()*/ << T << D->getSourceRange();
+ return;
+ }
+
+ if (!E->isValueDependent()) {
+ llvm::APSInt Alignment(32);
+ ExprResult ICE
+ = VerifyIntegerConstantExpression(E, &Alignment,
+ diag::err_align_value_attribute_argument_not_int,
+ /*AllowFold*/ false);
+ if (ICE.isInvalid())
+ return;
+
+ if (!Alignment.isPowerOf2()) {
+ Diag(AttrLoc, diag::err_alignment_not_power_of_two)
+ << E->getSourceRange();
+ return;
+ }
+
+ D->addAttr(::new (Context)
+ AlignValueAttr(AttrRange, Context, ICE.get(),
+ SpellingListIndex));
+ return;
+ }
+
+ // Save dependent expressions in the AST to be instantiated.
+ D->addAttr(::new (Context) AlignValueAttr(TmpAttr));
+ return;
+}
+
static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// check the attribute arguments.
if (Attr.getNumArgs() > 1) {
@@ -2773,7 +2907,7 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
// An alignment specification of zero has no effect.
if (!(TmpAttr.isAlignas() && !Alignment) &&
!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
- Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two)
+ Diag(AttrLoc, diag::err_alignment_not_power_of_two)
<< E->getSourceRange();
return;
}
@@ -3006,24 +3140,75 @@ static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
+AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Ident,
+ unsigned AttrSpellingListIndex) {
+ if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
+ Diag(Range.getBegin(), diag::warn_attribute_ignored) << Ident;
+ Diag(Optnone->getLocation(), diag::note_conflicting_attribute);
+ return nullptr;
+ }
+
+ if (D->hasAttr<AlwaysInlineAttr>())
+ return nullptr;
+
+ return ::new (Context) AlwaysInlineAttr(Range, Context,
+ AttrSpellingListIndex);
+}
+
+MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex) {
+ if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
+ Diag(Range.getBegin(), diag::warn_attribute_ignored) << "'minsize'";
+ Diag(Optnone->getLocation(), diag::note_conflicting_attribute);
+ return nullptr;
+ }
+
+ if (D->hasAttr<MinSizeAttr>())
+ return nullptr;
+
+ return ::new (Context) MinSizeAttr(Range, Context, AttrSpellingListIndex);
+}
+
+OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex) {
+ if (AlwaysInlineAttr *Inline = D->getAttr<AlwaysInlineAttr>()) {
+ Diag(Inline->getLocation(), diag::warn_attribute_ignored) << Inline;
+ Diag(Range.getBegin(), diag::note_conflicting_attribute);
+ D->dropAttr<AlwaysInlineAttr>();
+ }
+ if (MinSizeAttr *MinSize = D->getAttr<MinSizeAttr>()) {
+ Diag(MinSize->getLocation(), diag::warn_attribute_ignored) << MinSize;
+ Diag(Range.getBegin(), diag::note_conflicting_attribute);
+ D->dropAttr<MinSizeAttr>();
+ }
+
+ if (D->hasAttr<OptimizeNoneAttr>())
+ return nullptr;
+
+ return ::new (Context) OptimizeNoneAttr(Range, Context,
+ AttrSpellingListIndex);
+}
+
static void handleAlwaysInlineAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (checkAttrMutualExclusion<OptimizeNoneAttr>(S, D, Attr))
- return;
+ if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr(
+ D, Attr.getRange(), Attr.getName(),
+ Attr.getAttributeSpellingListIndex()))
+ D->addAttr(Inline);
+}
- D->addAttr(::new (S.Context)
- AlwaysInlineAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (MinSizeAttr *MinSize = S.mergeMinSizeAttr(
+ D, Attr.getRange(), Attr.getAttributeSpellingListIndex()))
+ D->addAttr(MinSize);
}
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()));
+ if (OptimizeNoneAttr *Optnone = S.mergeOptimizeNoneAttr(
+ D, Attr.getRange(), Attr.getAttributeSpellingListIndex()))
+ D->addAttr(Optnone);
}
static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -3039,7 +3224,7 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
D->addAttr(::new (S.Context)
CUDAGlobalAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ Attr.getAttributeSpellingListIndex()));
}
static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -3096,6 +3281,11 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
PascalAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
return;
+ case AttributeList::AT_VectorCall:
+ D->addAttr(::new (S.Context)
+ VectorCallAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+ return;
case AttributeList::AT_MSABI:
D->addAttr(::new (S.Context)
MSABIAttr(Attr.getRange(), S.Context,
@@ -3158,6 +3348,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
case AttributeList::AT_StdCall: CC = CC_X86StdCall; break;
case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; break;
case AttributeList::AT_Pascal: CC = CC_X86Pascal; break;
+ case AttributeList::AT_VectorCall: CC = CC_X86VectorCall; break;
case AttributeList::AT_MSABI:
CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C :
CC_X86_64Win64;
@@ -3242,14 +3433,6 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
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;
@@ -3440,29 +3623,24 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
default:
llvm_unreachable("invalid ownership attribute");
case AttributeList::AT_NSReturnsAutoreleased:
- D->addAttr(::new (S.Context)
- NSReturnsAutoreleasedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_CFReturnsNotRetained:
- D->addAttr(::new (S.Context)
- CFReturnsNotRetainedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_NSReturnsNotRetained:
- D->addAttr(::new (S.Context)
- NSReturnsNotRetainedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_CFReturnsRetained:
- D->addAttr(::new (S.Context)
- CFReturnsRetainedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) CFReturnsRetainedAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_NSReturnsRetained:
- D->addAttr(::new (S.Context)
- NSReturnsRetainedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) NSReturnsRetainedAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
return;
};
}
@@ -3491,9 +3669,8 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
return;
}
- D->addAttr(::new (S.Context)
- ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context,
- attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) ObjCReturnsInnerPointerAttr(
+ attr.getRange(), S.Context, attr.getAttributeSpellingListIndex()));
}
static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
@@ -3587,7 +3764,8 @@ static void handleObjCBridgeRelatedAttr(Sema &S, Scope *Sc, Decl *D,
static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
const AttributeList &Attr) {
ObjCInterfaceDecl *IFace;
- if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
+ if (ObjCCategoryDecl *CatDecl =
+ dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
IFace = CatDecl->getClassInterface();
else
IFace = cast<ObjCInterfaceDecl>(D->getDeclContext());
@@ -3812,6 +3990,32 @@ static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
handleARMInterruptAttr(S, D, Attr);
}
+static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ uint32_t NumRegs;
+ Expr *NumRegsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
+ if (!checkUInt32Argument(S, Attr, NumRegsExpr, NumRegs))
+ return;
+
+ D->addAttr(::new (S.Context)
+ AMDGPUNumVGPRAttr(Attr.getLoc(), S.Context,
+ NumRegs,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ uint32_t NumRegs;
+ Expr *NumRegsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
+ if (!checkUInt32Argument(S, Attr, NumRegsExpr, NumRegs))
+ return;
+
+ D->addAttr(::new (S.Context)
+ AMDGPUNumSGPRAttr(Attr.getLoc(), S.Context,
+ NumRegs,
+ Attr.getAttributeSpellingListIndex()));
+}
+
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
@@ -3871,6 +4075,16 @@ static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
return;
}
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->isInlined() && A.getKind() == AttributeList::AT_DLLImport &&
+ !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ // MinGW doesn't allow dllimport on inline functions.
+ S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline)
+ << A.getName();
+ return;
+ }
+ }
+
unsigned Index = A.getAttributeSpellingListIndex();
Attr *NewAttr = A.getKind() == AttributeList::AT_DLLExport
? (Attr *)S.mergeDLLExportAttr(D, A.getRange(), Index)
@@ -4001,6 +4215,19 @@ static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
D->addAttr(RCA);
}
+static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (auto *NSD = dyn_cast<NamespaceDecl>(D)) {
+ if (NSD->isAnonymousNamespace()) {
+ S.Diag(Attr.getLoc(), diag::warn_deprecated_anonymous_namespace);
+ // Do not want to attach the attribute to the namespace because that will
+ // cause confusing diagnostic reports for uses of declarations within the
+ // namespace.
+ return;
+ }
+ }
+ handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);
+}
+
/// Handles semantic checking for features that are common to all attributes,
/// such as checking whether a parameter was properly specified, or the correct
/// number of arguments were passed, etc.
@@ -4020,11 +4247,20 @@ static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D,
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;
+ if (Attr.getMinArgs() == Attr.getMaxArgs()) {
+ // If there are no optional arguments, then checking for the argument count
+ // is trivial.
+ if (!checkAttributeNumArgs(S, Attr, Attr.getMinArgs()))
+ return true;
+ } else {
+ // There are optional arguments, so checking is slightly more involved.
+ if (Attr.getMinArgs() &&
+ !checkAttributeAtLeastNumArgs(S, Attr, Attr.getMinArgs()))
+ return true;
+ else if (!Attr.hasVariadicArg() && Attr.getMaxArgs() &&
+ !checkAttributeAtMostNumArgs(S, Attr, Attr.getMaxArgs()))
+ return true;
+ }
// Check whether the attribute appertains to the given subject.
if (!Attr.diagnoseAppertainsTo(S, D))
@@ -4087,6 +4323,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_NoMips16:
handleSimpleAttribute<NoMips16Attr>(S, D, Attr);
break;
+ case AttributeList::AT_AMDGPUNumVGPR:
+ handleAMDGPUNumVGPRAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_AMDGPUNumSGPR:
+ handleAMDGPUNumSGPRAttr(S, D, Attr);
+ break;
case AttributeList::AT_IBAction:
handleSimpleAttribute<IBActionAttr>(S, D, Attr);
break;
@@ -4102,6 +4344,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_Aligned:
handleAlignedAttr(S, D, Attr);
break;
+ case AttributeList::AT_AlignValue:
+ handleAlignValueAttr(S, D, Attr);
+ break;
case AttributeList::AT_AlwaysInline:
handleAlwaysInlineAttr(S, D, Attr);
break;
@@ -4133,7 +4378,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleSimpleAttribute<CXX11NoReturnAttr>(S, D, Attr);
break;
case AttributeList::AT_Deprecated:
- handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);
+ handleDeprecatedAttr(S, D, Attr);
break;
case AttributeList::AT_Destructor:
handleDestructorAttr(S, D, Attr);
@@ -4145,11 +4390,14 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleExtVectorTypeAttr(S, scope, D, Attr);
break;
case AttributeList::AT_MinSize:
- handleSimpleAttribute<MinSizeAttr>(S, D, Attr);
+ handleMinSizeAttr(S, D, Attr);
break;
case AttributeList::AT_OptimizeNone:
handleOptimizeNoneAttr(S, D, Attr);
break;
+ case AttributeList::AT_FlagEnum:
+ handleSimpleAttribute<FlagEnumAttr>(S, D, Attr);
+ break;
case AttributeList::AT_Flatten:
handleSimpleAttribute<FlattenAttr>(S, D, Attr);
break;
@@ -4198,6 +4446,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ReturnsNonNull:
handleReturnsNonNullAttr(S, D, Attr);
break;
+ case AttributeList::AT_AssumeAligned:
+ handleAssumeAlignedAttr(S, D, Attr);
+ break;
case AttributeList::AT_Overloadable:
handleSimpleAttribute<OverloadableAttr>(S, D, Attr);
break;
@@ -4392,6 +4643,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_FastCall:
case AttributeList::AT_ThisCall:
case AttributeList::AT_Pascal:
+ case AttributeList::AT_VectorCall:
case AttributeList::AT_MSABI:
case AttributeList::AT_SysVABI:
case AttributeList::AT_Pcs:
@@ -4553,19 +4805,31 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
return;
}
+ // FIXME: We should be able to handle this in TableGen as well. It would be
+ // good to have a way to specify "these attributes must appear as a group",
+ // for these. Additionally, it would be good to have a way to specify "these
+ // attribute must never appear as a group" for attributes like cold and hot.
if (!D->hasAttr<OpenCLKernelAttr>()) {
// These attributes cannot be applied to a non-kernel function.
if (Attr *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
+ // FIXME: This emits a different error message than
+ // diag::err_attribute_wrong_decl_type + ExpectedKernelFunction.
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
- }
- if (Attr *A = D->getAttr<WorkGroupSizeHintAttr>()) {
+ } else if (Attr *A = D->getAttr<WorkGroupSizeHintAttr>()) {
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
- }
- if (Attr *A = D->getAttr<VecTypeHintAttr>()) {
+ } else if (Attr *A = D->getAttr<VecTypeHintAttr>()) {
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
+ } else if (Attr *A = D->getAttr<AMDGPUNumVGPRAttr>()) {
+ Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
+ << A << ExpectedKernelFunction;
+ D->setInvalidDecl();
+ } else if (Attr *A = D->getAttr<AMDGPUNumSGPRAttr>()) {
+ Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
+ << A << ExpectedKernelFunction;
+ D->setInvalidDecl();
}
}
}
@@ -4576,7 +4840,7 @@ bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
const AttributeList *AttrList) {
for (const AttributeList* l = AttrList; l; l = l->getNext()) {
if (l->getKind() == AttributeList::AT_Annotate) {
- handleAnnotateAttr(*this, ASDecl, *l);
+ ProcessDeclAttribute(*this, nullptr, ASDecl, *l, l->isCXX11Attribute());
} else {
Diag(l->getLoc(), diag::err_only_annotate_after_access_spec);
return true;
@@ -4774,61 +5038,6 @@ static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag,
diag.Triggered = true;
}
-void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
- assert(DelayedDiagnostics.getCurrentPool());
- DelayedDiagnosticPool &poppedPool = *DelayedDiagnostics.getCurrentPool();
- DelayedDiagnostics.popWithoutEmitting(state);
-
- // When delaying diagnostics to run in the context of a parsed
- // declaration, we only want to actually emit anything if parsing
- // succeeds.
- if (!decl) return;
-
- // We emit all the active diagnostics in this pool or any of its
- // parents. In general, we'll get one pool for the decl spec
- // and a child pool for each declarator; in a decl group like:
- // deprecated_typedef foo, *bar, baz();
- // only the declarator pops will be passed decls. This is correct;
- // we really do need to consider delayed diagnostics from the decl spec
- // for each of the different declarations.
- const DelayedDiagnosticPool *pool = &poppedPool;
- do {
- for (DelayedDiagnosticPool::pool_iterator
- i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) {
- // This const_cast is a bit lame. Really, Triggered should be mutable.
- DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i);
- if (diag.Triggered)
- continue;
-
- switch (diag.Kind) {
- case DelayedDiagnostic::Deprecation:
- case DelayedDiagnostic::Unavailable:
- // Don't bother giving deprecation/unavailable diagnostics if
- // the decl is invalid.
- if (!decl->isInvalidDecl())
- HandleDelayedAvailabilityCheck(diag, decl);
- break;
-
- case DelayedDiagnostic::Access:
- HandleDelayedAccessCheck(diag, decl);
- break;
-
- case DelayedDiagnostic::ForbiddenType:
- handleDelayedForbiddenType(*this, diag, decl);
- break;
- }
- }
- } while ((pool = pool->getParent()));
-}
-
-/// Given a set of delayed diagnostics, re-emit them as if they had
-/// been delayed in the current context instead of in the given pool.
-/// Essentially, this just moves them to the current pool.
-void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) {
- DelayedDiagnosticPool *curPool = DelayedDiagnostics.getCurrentPool();
- assert(curPool && "re-emitting in undelayed context not supported");
- curPool->steal(pool);
-}
static bool isDeclDeprecated(Decl *D) {
do {
@@ -4852,17 +5061,12 @@ static bool isDeclUnavailable(Decl *D) {
return false;
}
-static void
-DoEmitAvailabilityWarning(Sema &S,
- DelayedDiagnostic::DDKind K,
- Decl *Ctx,
- const NamedDecl *D,
- StringRef Message,
- SourceLocation Loc,
- const ObjCInterfaceDecl *UnknownObjCClass,
- const ObjCPropertyDecl *ObjCProperty,
- bool ObjCPropertyAccess) {
-
+static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K,
+ Decl *Ctx, const NamedDecl *D,
+ StringRef Message, SourceLocation Loc,
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ const ObjCPropertyDecl *ObjCProperty,
+ bool ObjCPropertyAccess) {
// Diagnostics for deprecated or unavailable.
unsigned diag, diag_message, diag_fwdclass_message;
@@ -4874,65 +5078,116 @@ DoEmitAvailabilityWarning(Sema &S,
// Don't warn if our current context is deprecated or unavailable.
switch (K) {
- case DelayedDiagnostic::Deprecation:
- if (isDeclDeprecated(Ctx))
- return;
- diag = !ObjCPropertyAccess ? diag::warn_deprecated
- : diag::warn_property_method_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::Deprecation:
+ if (isDeclDeprecated(Ctx))
+ return;
+ diag = !ObjCPropertyAccess ? diag::warn_deprecated
+ : diag::warn_property_method_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 = !ObjCPropertyAccess ? diag::err_unavailable
- : diag::err_property_method_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;
+ case DelayedDiagnostic::Unavailable:
+ if (isDeclUnavailable(Ctx))
+ return;
+ diag = !ObjCPropertyAccess ? diag::err_unavailable
+ : diag::err_property_method_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");
+ default:
+ llvm_unreachable("Neither a deprecation or unavailable kind");
}
- DeclarationName Name = D->getDeclName();
if (!Message.empty()) {
- S.Diag(Loc, diag_message) << Name << Message;
+ S.Diag(Loc, diag_message) << D << Message;
if (ObjCProperty)
S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
- << ObjCProperty->getDeclName() << property_note_select;
+ << ObjCProperty->getDeclName() << property_note_select;
} else if (!UnknownObjCClass) {
- S.Diag(Loc, diag) << Name;
+ S.Diag(Loc, diag) << D;
if (ObjCProperty)
S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
- << ObjCProperty->getDeclName() << property_note_select;
+ << ObjCProperty->getDeclName() << property_note_select;
} else {
- S.Diag(Loc, diag_fwdclass_message) << Name;
+ S.Diag(Loc, diag_fwdclass_message) << D;
S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
}
S.Diag(D->getLocation(), diag::note_availability_specified_here)
- << D << available_here_select_kind;
+ << D << available_here_select_kind;
}
-void Sema::HandleDelayedAvailabilityCheck(DelayedDiagnostic &DD,
- Decl *Ctx) {
+static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
+ Decl *Ctx) {
DD.Triggered = true;
- DoEmitAvailabilityWarning(*this,
- (DelayedDiagnostic::DDKind) DD.Kind,
- Ctx,
- DD.getDeprecationDecl(),
- DD.getDeprecationMessage(),
- DD.Loc,
- DD.getUnknownObjCClass(),
+ DoEmitAvailabilityWarning(S, (DelayedDiagnostic::DDKind)DD.Kind, Ctx,
+ DD.getDeprecationDecl(), DD.getDeprecationMessage(),
+ DD.Loc, DD.getUnknownObjCClass(),
DD.getObjCProperty(), false);
}
+void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
+ assert(DelayedDiagnostics.getCurrentPool());
+ DelayedDiagnosticPool &poppedPool = *DelayedDiagnostics.getCurrentPool();
+ DelayedDiagnostics.popWithoutEmitting(state);
+
+ // When delaying diagnostics to run in the context of a parsed
+ // declaration, we only want to actually emit anything if parsing
+ // succeeds.
+ if (!decl) return;
+
+ // We emit all the active diagnostics in this pool or any of its
+ // parents. In general, we'll get one pool for the decl spec
+ // and a child pool for each declarator; in a decl group like:
+ // deprecated_typedef foo, *bar, baz();
+ // only the declarator pops will be passed decls. This is correct;
+ // we really do need to consider delayed diagnostics from the decl spec
+ // for each of the different declarations.
+ const DelayedDiagnosticPool *pool = &poppedPool;
+ do {
+ for (DelayedDiagnosticPool::pool_iterator
+ i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) {
+ // This const_cast is a bit lame. Really, Triggered should be mutable.
+ DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i);
+ if (diag.Triggered)
+ continue;
+
+ switch (diag.Kind) {
+ case DelayedDiagnostic::Deprecation:
+ case DelayedDiagnostic::Unavailable:
+ // Don't bother giving deprecation/unavailable diagnostics if
+ // the decl is invalid.
+ if (!decl->isInvalidDecl())
+ handleDelayedAvailabilityCheck(*this, diag, decl);
+ break;
+
+ case DelayedDiagnostic::Access:
+ HandleDelayedAccessCheck(diag, decl);
+ break;
+
+ case DelayedDiagnostic::ForbiddenType:
+ handleDelayedForbiddenType(*this, diag, decl);
+ break;
+ }
+ }
+ } while ((pool = pool->getParent()));
+}
+
+/// Given a set of delayed diagnostics, re-emit them as if they had
+/// been delayed in the current context instead of in the given pool.
+/// Essentially, this just moves them to the current pool.
+void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) {
+ DelayedDiagnosticPool *curPool = DelayedDiagnostics.getCurrentPool();
+ assert(curPool && "re-emitting in undelayed context not supported");
+ curPool->steal(pool);
+}
+
void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD,
NamedDecl *D, StringRef Message,
SourceLocation Loc,
@@ -4941,11 +5196,9 @@ void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD,
bool ObjCPropertyAccess) {
// Delay if we're currently parsing a declaration.
if (DelayedDiagnostics.shouldDelayDiagnostics()) {
- DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(AD, Loc, D,
- UnknownObjCClass,
- ObjCProperty,
- Message,
- ObjCPropertyAccess));
+ DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(
+ AD, Loc, D, UnknownObjCClass, ObjCProperty, Message,
+ ObjCPropertyAccess));
return;
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index c5cd83da59d6..510738ea8168 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -36,6 +36,7 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Template.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include <map>
@@ -212,7 +213,7 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
ComputedEST = EST_Dynamic;
// Record the exceptions in this function's exception specification.
for (const auto &E : Proto->exceptions())
- if (ExceptionsSeen.insert(Self->Context.getCanonicalType(E)))
+ if (ExceptionsSeen.insert(Self->Context.getCanonicalType(E)).second)
Exceptions.push_back(E);
}
@@ -353,7 +354,9 @@ void Sema::ActOnParamDefaultArgumentError(Decl *param,
Param->setInvalidDecl();
UnparsedDefaultArgLocs.erase(Param);
Param->setDefaultArg(new(Context)
- OpaqueValueExpr(EqualLoc, Param->getType(), VK_RValue));
+ OpaqueValueExpr(EqualLoc,
+ Param->getType().getNonReferenceType(),
+ VK_RValue));
}
/// CheckExtraCXXDefaultArguments - Check for any extra default
@@ -385,9 +388,14 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
ParmVarDecl *Param = cast<ParmVarDecl>(chunk.Fun.Params[argIdx].Param);
if (Param->hasUnparsedDefaultArg()) {
CachedTokens *Toks = chunk.Fun.Params[argIdx].DefaultArgTokens;
+ SourceRange SR;
+ if (Toks->size() > 1)
+ SR = SourceRange((*Toks)[1].getLocation(),
+ Toks->back().getLocation());
+ else
+ SR = UnparsedDefaultArgLocs[Param];
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
- << SourceRange((*Toks)[1].getLocation(),
- Toks->back().getLocation());
+ << SR;
delete Toks;
chunk.Fun.Params[argIdx].DefaultArgTokens = nullptr;
} else if (Param->getDefaultArg()) {
@@ -446,20 +454,24 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
bool OldParamHasDfl = OldParam->hasDefaultArg();
bool NewParamHasDfl = NewParam->hasDefaultArg();
- NamedDecl *ND = Old;
-
// The declaration context corresponding to the scope is the semantic
// parent, unless this is a local function declaration, in which case
// it is that surrounding function.
- DeclContext *ScopeDC = New->getLexicalDeclContext();
- if (!ScopeDC->isFunctionOrMethod())
- ScopeDC = New->getDeclContext();
- if (S && !isDeclInScope(ND, ScopeDC, S) &&
+ DeclContext *ScopeDC = New->isLocalExternDecl()
+ ? New->getLexicalDeclContext()
+ : New->getDeclContext();
+ if (S && !isDeclInScope(Old, ScopeDC, S) &&
!New->getDeclContext()->isRecord())
// Ignore default parameters of old decl if they are not in
// the same scope and this is not an out-of-line definition of
// a member function.
OldParamHasDfl = false;
+ if (New->isLocalExternDecl() != Old->isLocalExternDecl())
+ // If only one of these is a local function declaration, then they are
+ // declared in different scopes, even though isDeclInScope may think
+ // they're in the same scope. (If both are local, the scope check is
+ // sufficent, and if neither is local, then they are in the same scope.)
+ OldParamHasDfl = false;
if (OldParamHasDfl && NewParamHasDfl) {
@@ -855,7 +867,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
// C++1y allows types to be defined, not just declared.
if (cast<TagDecl>(DclIt)->isThisDeclarationADefinition())
SemaRef.Diag(DS->getLocStart(),
- SemaRef.getLangOpts().CPlusPlus1y
+ SemaRef.getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_constexpr_type_definition
: diag::ext_constexpr_type_definition)
<< isa<CXXConstructorDecl>(Dcl);
@@ -896,7 +908,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
}
}
SemaRef.Diag(VD->getLocation(),
- SemaRef.getLangOpts().CPlusPlus1y
+ SemaRef.getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_constexpr_local_var
: diag::ext_constexpr_local_var)
<< isa<CXXConstructorDecl>(Dcl);
@@ -1041,7 +1053,7 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
case Stmt::ContinueStmtClass:
// C++1y allows all of these. We don't allow them as extensions in C++11,
// because they don't make sense without variable mutation.
- if (!SemaRef.getLangOpts().CPlusPlus1y)
+ if (!SemaRef.getLangOpts().CPlusPlus14)
break;
if (!Cxx1yLoc.isValid())
Cxx1yLoc = S->getLocStart();
@@ -1115,7 +1127,7 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
if (Cxx1yLoc.isValid())
Diag(Cxx1yLoc,
- getLangOpts().CPlusPlus1y
+ getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_constexpr_body_invalid_stmt
: diag::ext_constexpr_body_invalid_stmt)
<< isa<CXXConstructorDecl>(Dcl);
@@ -1180,7 +1192,7 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
// statement. We still do, unless the return type might be void, because
// otherwise if there's no return statement, the function cannot
// be used in a core constant expression.
- bool OK = getLangOpts().CPlusPlus1y &&
+ bool OK = getLangOpts().CPlusPlus14 &&
(Dcl->getReturnType()->isVoidType() ||
Dcl->getReturnType()->isDependentType());
Diag(Dcl->getLocation(),
@@ -1190,7 +1202,7 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
}
if (ReturnStmts.size() > 1) {
Diag(ReturnStmts.back(),
- getLangOpts().CPlusPlus1y
+ getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_constexpr_body_multiple_return
: diag::ext_constexpr_body_multiple_return);
for (unsigned I = 0; I < ReturnStmts.size() - 1; ++I)
@@ -1881,7 +1893,7 @@ void Sema::CheckOverrideControl(NamedDecl *D) {
}
// C++11 [class.virtual]p5:
- // If a virtual function is marked with the virt-specifier override and
+ // If a function is marked with the virt-specifier override and
// does not override a member function of a base class, the program is
// ill-formed.
bool HasOverriddenMethods =
@@ -1891,6 +1903,30 @@ void Sema::CheckOverrideControl(NamedDecl *D) {
<< MD->getDeclName();
}
+void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) {
+ if (D->isInvalidDecl() || D->hasAttr<OverrideAttr>())
+ return;
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D);
+ if (!MD || MD->isImplicit() || MD->hasAttr<FinalAttr>() ||
+ isa<CXXDestructorDecl>(MD))
+ return;
+
+ SourceLocation Loc = MD->getLocation();
+ SourceLocation SpellingLoc = Loc;
+ if (getSourceManager().isMacroArgExpansion(Loc))
+ SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).first;
+ SpellingLoc = getSourceManager().getSpellingLoc(SpellingLoc);
+ if (SpellingLoc.isValid() && getSourceManager().isInSystemHeader(SpellingLoc))
+ return;
+
+ if (MD->size_overridden_methods() > 0) {
+ Diag(MD->getLocation(), diag::warn_function_marked_not_override_overriding)
+ << MD->getDeclName();
+ const CXXMethodDecl *OMD = *MD->begin_overridden_methods();
+ Diag(OMD->getLocation(), diag::note_overridden_virtual_function);
+ }
+}
+
/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member
/// function overrides a virtual member function marked 'final', according to
/// C++11 [class.virtual]p4.
@@ -2133,7 +2169,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
if (BitWidth) {
if (Member->isInvalidDecl()) {
// don't emit another diagnostic.
- } else if (isa<VarDecl>(Member)) {
+ } else if (isa<VarDecl>(Member) || isa<VarTemplateDecl>(Member)) {
// C++ 9.6p3: A bit-field shall not be a static member.
// "static member 'A' cannot be a bit-field"
Diag(Loc, diag::err_static_not_bitfield)
@@ -2205,18 +2241,73 @@ namespace {
Sema &S;
// List of Decls to generate a warning on. Also remove Decls that become
// initialized.
- llvm::SmallPtrSet<ValueDecl*, 4> &Decls;
+ llvm::SmallPtrSetImpl<ValueDecl*> &Decls;
+ // List of base classes of the record. Classes are removed after their
+ // initializers.
+ llvm::SmallPtrSetImpl<QualType> &BaseClasses;
+ // Vector of decls to be removed from the Decl set prior to visiting the
+ // nodes. These Decls may have been initialized in the prior initializer.
+ llvm::SmallVector<ValueDecl*, 4> DeclsToRemove;
// If non-null, add a note to the warning pointing back to the constructor.
const CXXConstructorDecl *Constructor;
+ // Variables to hold state when processing an initializer list. When
+ // InitList is true, special case initialization of FieldDecls matching
+ // InitListFieldDecl.
+ bool InitList;
+ FieldDecl *InitListFieldDecl;
+ llvm::SmallVector<unsigned, 4> InitFieldIndex;
+
public:
typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited;
UninitializedFieldVisitor(Sema &S,
- llvm::SmallPtrSet<ValueDecl*, 4> &Decls,
- const CXXConstructorDecl *Constructor)
- : Inherited(S.Context), S(S), Decls(Decls),
- Constructor(Constructor) { }
+ llvm::SmallPtrSetImpl<ValueDecl*> &Decls,
+ llvm::SmallPtrSetImpl<QualType> &BaseClasses)
+ : Inherited(S.Context), S(S), Decls(Decls), BaseClasses(BaseClasses),
+ Constructor(nullptr), InitList(false), InitListFieldDecl(nullptr) {}
+
+ // Returns true if the use of ME is not an uninitialized use.
+ bool IsInitListMemberExprInitialized(MemberExpr *ME,
+ bool CheckReferenceOnly) {
+ llvm::SmallVector<FieldDecl*, 4> Fields;
+ bool ReferenceField = false;
+ while (ME) {
+ FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
+ if (!FD)
+ return false;
+ Fields.push_back(FD);
+ if (FD->getType()->isReferenceType())
+ ReferenceField = true;
+ ME = dyn_cast<MemberExpr>(ME->getBase()->IgnoreParenImpCasts());
+ }
+
+ // Binding a reference to an unintialized field is not an
+ // uninitialized use.
+ if (CheckReferenceOnly && !ReferenceField)
+ return true;
- void HandleMemberExpr(MemberExpr *ME, bool CheckReferenceOnly) {
+ llvm::SmallVector<unsigned, 4> UsedFieldIndex;
+ // Discard the first field since it is the field decl that is being
+ // initialized.
+ for (auto I = Fields.rbegin() + 1, E = Fields.rend(); I != E; ++I) {
+ UsedFieldIndex.push_back((*I)->getFieldIndex());
+ }
+
+ for (auto UsedIter = UsedFieldIndex.begin(),
+ UsedEnd = UsedFieldIndex.end(),
+ OrigIter = InitFieldIndex.begin(),
+ OrigEnd = InitFieldIndex.end();
+ UsedIter != UsedEnd && OrigIter != OrigEnd; ++UsedIter, ++OrigIter) {
+ if (*UsedIter < *OrigIter)
+ return true;
+ if (*UsedIter > *OrigIter)
+ break;
+ }
+
+ return false;
+ }
+
+ void HandleMemberExpr(MemberExpr *ME, bool CheckReferenceOnly,
+ bool AddressOf) {
if (isa<EnumConstantDecl>(ME->getMemberDecl()))
return;
@@ -2224,33 +2315,63 @@ namespace {
// or union.
MemberExpr *FieldME = ME;
+ bool AllPODFields = FieldME->getType().isPODType(S.Context);
+
Expr *Base = ME;
- while (isa<MemberExpr>(Base)) {
- ME = cast<MemberExpr>(Base);
+ while (MemberExpr *SubME =
+ dyn_cast<MemberExpr>(Base->IgnoreParenImpCasts())) {
- if (isa<VarDecl>(ME->getMemberDecl()))
+ if (isa<VarDecl>(SubME->getMemberDecl()))
return;
- if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(SubME->getMemberDecl()))
if (!FD->isAnonymousStructOrUnion())
- FieldME = ME;
+ FieldME = SubME;
+
+ if (!FieldME->getType().isPODType(S.Context))
+ AllPODFields = false;
- Base = ME->getBase();
+ Base = SubME->getBase();
}
- if (!isa<CXXThisExpr>(Base))
+ if (!isa<CXXThisExpr>(Base->IgnoreParenImpCasts()))
+ return;
+
+ if (AddressOf && AllPODFields)
return;
ValueDecl* FoundVD = FieldME->getMemberDecl();
+ if (ImplicitCastExpr *BaseCast = dyn_cast<ImplicitCastExpr>(Base)) {
+ while (isa<ImplicitCastExpr>(BaseCast->getSubExpr())) {
+ BaseCast = cast<ImplicitCastExpr>(BaseCast->getSubExpr());
+ }
+
+ if (BaseCast->getCastKind() == CK_UncheckedDerivedToBase) {
+ QualType T = BaseCast->getType();
+ if (T->isPointerType() &&
+ BaseClasses.count(T->getPointeeType())) {
+ S.Diag(FieldME->getExprLoc(), diag::warn_base_class_is_uninit)
+ << T->getPointeeType() << FoundVD;
+ }
+ }
+ }
+
if (!Decls.count(FoundVD))
return;
const bool IsReference = FoundVD->getType()->isReferenceType();
- // Prevent double warnings on use of unbounded references.
- if (IsReference != CheckReferenceOnly)
- return;
+ if (InitList && !AddressOf && FoundVD == InitListFieldDecl) {
+ // Special checking for initializer lists.
+ if (IsInitListMemberExprInitialized(ME, CheckReferenceOnly)) {
+ return;
+ }
+ } else {
+ // Prevent double warnings on use of unbounded references.
+ if (CheckReferenceOnly && !IsReference)
+ return;
+ }
unsigned diag = IsReference
? diag::warn_reference_field_is_uninit
@@ -2263,74 +2384,160 @@ namespace {
}
- void HandleValue(Expr *E) {
+ void HandleValue(Expr *E, bool AddressOf) {
E = E->IgnoreParens();
if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
- HandleMemberExpr(ME, false /*CheckReferenceOnly*/);
+ HandleMemberExpr(ME, false /*CheckReferenceOnly*/,
+ AddressOf /*AddressOf*/);
return;
}
if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
- HandleValue(CO->getTrueExpr());
- HandleValue(CO->getFalseExpr());
+ Visit(CO->getCond());
+ HandleValue(CO->getTrueExpr(), AddressOf);
+ HandleValue(CO->getFalseExpr(), AddressOf);
return;
}
if (BinaryConditionalOperator *BCO =
dyn_cast<BinaryConditionalOperator>(E)) {
- HandleValue(BCO->getCommon());
- HandleValue(BCO->getFalseExpr());
+ Visit(BCO->getCond());
+ HandleValue(BCO->getFalseExpr(), AddressOf);
+ return;
+ }
+
+ if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
+ HandleValue(OVE->getSourceExpr(), AddressOf);
return;
}
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
switch (BO->getOpcode()) {
default:
- return;
+ break;
case(BO_PtrMemD):
case(BO_PtrMemI):
- HandleValue(BO->getLHS());
+ HandleValue(BO->getLHS(), AddressOf);
+ Visit(BO->getRHS());
return;
case(BO_Comma):
- HandleValue(BO->getRHS());
+ Visit(BO->getLHS());
+ HandleValue(BO->getRHS(), AddressOf);
return;
}
}
+
+ Visit(E);
+ }
+
+ void CheckInitListExpr(InitListExpr *ILE) {
+ InitFieldIndex.push_back(0);
+ for (auto Child : ILE->children()) {
+ if (InitListExpr *SubList = dyn_cast<InitListExpr>(Child)) {
+ CheckInitListExpr(SubList);
+ } else {
+ Visit(Child);
+ }
+ ++InitFieldIndex.back();
+ }
+ InitFieldIndex.pop_back();
+ }
+
+ void CheckInitializer(Expr *E, const CXXConstructorDecl *FieldConstructor,
+ FieldDecl *Field, const Type *BaseClass) {
+ // Remove Decls that may have been initialized in the previous
+ // initializer.
+ for (ValueDecl* VD : DeclsToRemove)
+ Decls.erase(VD);
+ DeclsToRemove.clear();
+
+ Constructor = FieldConstructor;
+ InitListExpr *ILE = dyn_cast<InitListExpr>(E);
+
+ if (ILE && Field) {
+ InitList = true;
+ InitListFieldDecl = Field;
+ InitFieldIndex.clear();
+ CheckInitListExpr(ILE);
+ } else {
+ InitList = false;
+ Visit(E);
+ }
+
+ if (Field)
+ Decls.erase(Field);
+ if (BaseClass)
+ BaseClasses.erase(BaseClass->getCanonicalTypeInternal());
}
void VisitMemberExpr(MemberExpr *ME) {
// All uses of unbounded reference fields will warn.
- HandleMemberExpr(ME, true /*CheckReferenceOnly*/);
-
- Inherited::VisitMemberExpr(ME);
+ HandleMemberExpr(ME, true /*CheckReferenceOnly*/, false /*AddressOf*/);
}
void VisitImplicitCastExpr(ImplicitCastExpr *E) {
- if (E->getCastKind() == CK_LValueToRValue)
- HandleValue(E->getSubExpr());
+ if (E->getCastKind() == CK_LValueToRValue) {
+ HandleValue(E->getSubExpr(), false /*AddressOf*/);
+ return;
+ }
Inherited::VisitImplicitCastExpr(E);
}
void VisitCXXConstructExpr(CXXConstructExpr *E) {
- if (E->getConstructor()->isCopyConstructor())
- if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(E->getArg(0)))
+ if (E->getConstructor()->isCopyConstructor()) {
+ Expr *ArgExpr = E->getArg(0);
+ if (InitListExpr *ILE = dyn_cast<InitListExpr>(ArgExpr))
+ if (ILE->getNumInits() == 1)
+ ArgExpr = ILE->getInit(0);
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgExpr))
if (ICE->getCastKind() == CK_NoOp)
- if (MemberExpr *ME = dyn_cast<MemberExpr>(ICE->getSubExpr()))
- HandleMemberExpr(ME, false /*CheckReferenceOnly*/);
-
+ ArgExpr = ICE->getSubExpr();
+ HandleValue(ArgExpr, false /*AddressOf*/);
+ return;
+ }
Inherited::VisitCXXConstructExpr(E);
}
void VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
Expr *Callee = E->getCallee();
- if (isa<MemberExpr>(Callee))
- HandleValue(Callee);
+ if (isa<MemberExpr>(Callee)) {
+ HandleValue(Callee, false /*AddressOf*/);
+ for (auto Arg : E->arguments())
+ Visit(Arg);
+ return;
+ }
Inherited::VisitCXXMemberCallExpr(E);
}
+ void VisitCallExpr(CallExpr *E) {
+ // Treat std::move as a use.
+ if (E->getNumArgs() == 1) {
+ if (FunctionDecl *FD = E->getDirectCallee()) {
+ if (FD->isInStdNamespace() && FD->getIdentifier() &&
+ FD->getIdentifier()->isStr("move")) {
+ HandleValue(E->getArg(0), false /*AddressOf*/);
+ return;
+ }
+ }
+ }
+
+ Inherited::VisitCallExpr(E);
+ }
+
+ void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+ Expr *Callee = E->getCallee();
+
+ if (isa<UnresolvedLookupExpr>(Callee))
+ return Inherited::VisitCXXOperatorCallExpr(E);
+
+ Visit(Callee);
+ for (auto Arg : E->arguments())
+ HandleValue(Arg->IgnoreParenImpCasts(), false /*AddressOf*/);
+ }
+
void VisitBinaryOperator(BinaryOperator *E) {
// If a field assignment is detected, remove the field from the
// uninitiailized field set.
@@ -2338,30 +2545,32 @@ namespace {
if (MemberExpr *ME = dyn_cast<MemberExpr>(E->getLHS()))
if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
if (!FD->getType()->isReferenceType())
- Decls.erase(FD);
+ DeclsToRemove.push_back(FD);
+
+ if (E->isCompoundAssignmentOp()) {
+ HandleValue(E->getLHS(), false /*AddressOf*/);
+ Visit(E->getRHS());
+ return;
+ }
Inherited::VisitBinaryOperator(E);
}
- };
- static void CheckInitExprContainsUninitializedFields(
- Sema &S, Expr *E, llvm::SmallPtrSet<ValueDecl*, 4> &Decls,
- const CXXConstructorDecl *Constructor) {
- if (Decls.size() == 0)
- return;
-
- if (!E)
- return;
- if (CXXDefaultInitExpr *Default = dyn_cast<CXXDefaultInitExpr>(E)) {
- E = Default->getExpr();
- if (!E)
+ void VisitUnaryOperator(UnaryOperator *E) {
+ if (E->isIncrementDecrementOp()) {
+ HandleValue(E->getSubExpr(), false /*AddressOf*/);
return;
- // In class initializers will point to the constructor.
- UninitializedFieldVisitor(S, Decls, Constructor).Visit(E);
- } else {
- UninitializedFieldVisitor(S, Decls, nullptr).Visit(E);
+ }
+ if (E->getOpcode() == UO_AddrOf) {
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(E->getSubExpr())) {
+ HandleValue(ME->getBase(), true /*AddressOf*/);
+ return;
+ }
+ }
+
+ Inherited::VisitUnaryOperator(E);
}
- }
+ };
// Diagnose value-uses of fields to initialize themselves, e.g.
// foo(foo)
@@ -2382,6 +2591,9 @@ namespace {
const CXXRecordDecl *RD = Constructor->getParent();
+ if (RD->getDescribedClassTemplate())
+ return;
+
// Holds fields that are uninitialized.
llvm::SmallPtrSet<ValueDecl*, 4> UninitializedFields;
@@ -2394,14 +2606,39 @@ namespace {
}
}
+ llvm::SmallPtrSet<QualType, 4> UninitializedBaseClasses;
+ for (auto I : RD->bases())
+ UninitializedBaseClasses.insert(I.getType().getCanonicalType());
+
+ if (UninitializedFields.empty() && UninitializedBaseClasses.empty())
+ return;
+
+ UninitializedFieldVisitor UninitializedChecker(SemaRef,
+ UninitializedFields,
+ UninitializedBaseClasses);
+
for (const auto *FieldInit : Constructor->inits()) {
- Expr *InitExpr = FieldInit->getInit();
+ if (UninitializedFields.empty() && UninitializedBaseClasses.empty())
+ break;
- CheckInitExprContainsUninitializedFields(
- SemaRef, InitExpr, UninitializedFields, Constructor);
+ Expr *InitExpr = FieldInit->getInit();
+ if (!InitExpr)
+ continue;
- if (FieldDecl *Field = FieldInit->getAnyMember())
- UninitializedFields.erase(Field);
+ if (CXXDefaultInitExpr *Default =
+ dyn_cast<CXXDefaultInitExpr>(InitExpr)) {
+ InitExpr = Default->getExpr();
+ if (!InitExpr)
+ continue;
+ // In class initializers will point to the constructor.
+ UninitializedChecker.CheckInitializer(InitExpr, Constructor,
+ FieldInit->getAnyMember(),
+ FieldInit->getBaseClass());
+ } else {
+ UninitializedChecker.CheckInitializer(InitExpr, nullptr,
+ FieldInit->getAnyMember(),
+ FieldInit->getBaseClass());
+ }
}
}
} // namespace
@@ -2424,13 +2661,14 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
// Pop the notional constructor scope we created earlier.
PopFunctionScopeInfo(nullptr, D);
- FieldDecl *FD = cast<FieldDecl>(D);
- assert(FD->getInClassInitStyle() != ICIS_NoInit &&
+ FieldDecl *FD = dyn_cast<FieldDecl>(D);
+ assert((isa<MSPropertyDecl>(D) || FD->getInClassInitStyle() != ICIS_NoInit) &&
"must set init style when field is created");
if (!InitExpr) {
- FD->setInvalidDecl();
- FD->removeInClassInitializer();
+ D->setInvalidDecl();
+ if (FD)
+ FD->removeInClassInitializer();
return;
}
@@ -2581,6 +2819,11 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
SourceLocation IdLoc,
Expr *Init,
SourceLocation EllipsisLoc) {
+ ExprResult Res = CorrectDelayedTyposInExpr(Init);
+ if (!Res.isUsable())
+ return true;
+ Init = Res.get();
+
if (!ConstructorD)
return true;
@@ -2610,8 +2853,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
// using a qualified name. ]
if (!SS.getScopeRep() && !TemplateTypeTy) {
// Look for a member, first.
- DeclContext::lookup_result Result
- = ClassDecl->lookup(MemberOrBase);
+ DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase);
if (!Result.empty()) {
ValueDecl *Member;
if ((Member = dyn_cast<FieldDecl>(Result.front())) ||
@@ -2666,10 +2908,11 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
// If no results were found, try to correct typos.
TypoCorrection Corr;
- MemInitializerValidatorCCC Validator(ClassDecl);
if (R.empty() && BaseType.isNull() &&
- (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
- Validator, CTK_ErrorRecovery, ClassDecl))) {
+ (Corr = CorrectTypo(
+ R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
+ llvm::make_unique<MemInitializerValidatorCCC>(ClassDecl),
+ CTK_ErrorRecovery, ClassDecl))) {
if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {
// We have found a non-static data member with a similar
// name to what was typed; complain and initialize that
@@ -2713,6 +2956,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
if (BaseType.isNull()) {
BaseType = Context.getTypeDeclType(TyD);
+ MarkAnyDeclReferenced(TyD->getLocation(), TyD, /*OdrUse=*/false);
if (SS.isSet())
// FIXME: preserve source range information
BaseType = Context.getElaboratedType(ETK_None, SS.getScopeRep(),
@@ -3528,19 +3772,19 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
return false;
if (Field->hasInClassInitializer() && !Info.isImplicitCopyOrMove()) {
- Expr *DIE = CXXDefaultInitExpr::Create(SemaRef.Context,
- Info.Ctor->getLocation(), Field);
+ ExprResult DIE =
+ SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field);
+ if (DIE.isInvalid())
+ return true;
CXXCtorInitializer *Init;
if (Indirect)
- Init = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect,
- SourceLocation(),
- SourceLocation(), DIE,
- SourceLocation());
+ Init = new (SemaRef.Context)
+ CXXCtorInitializer(SemaRef.Context, Indirect, SourceLocation(),
+ SourceLocation(), DIE.get(), SourceLocation());
else
- Init = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field,
- SourceLocation(),
- SourceLocation(), DIE,
- SourceLocation());
+ Init = new (SemaRef.Context)
+ CXXCtorInitializer(SemaRef.Context, Field, SourceLocation(),
+ SourceLocation(), DIE.get(), SourceLocation());
return Info.addFieldInitializer(Init);
}
@@ -3582,6 +3826,8 @@ Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor,
DelegatingCtorDecls.push_back(Constructor);
+ DiagnoseUninitializedFields(*this, Constructor);
+
return false;
}
@@ -4234,7 +4480,7 @@ void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) {
if (!SO->second.front().Method->isPure())
continue;
- if (!SeenPureMethods.insert(SO->second.front().Method))
+ if (!SeenPureMethods.insert(SO->second.front().Method).second)
continue;
Diag(SO->second.front().Method->getLocation(),
@@ -4415,10 +4661,53 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
/// \brief Check class-level dllimport/dllexport attribute.
static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
+
+ // MSVC inherits DLL attributes to partial class template specializations.
+ if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) {
+ if (auto *Spec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Class)) {
+ if (Attr *TemplateAttr =
+ getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) {
+ auto *A = cast<InheritableAttr>(TemplateAttr->clone(S.getASTContext()));
+ A->setInherited(true);
+ ClassAttr = A;
+ }
+ }
+ }
+
if (!ClassAttr)
return;
- bool ClassExported = ClassAttr->getKind() == attr::DLLExport;
+ if (!Class->isExternallyVisible()) {
+ S.Diag(Class->getLocation(), diag::err_attribute_dll_not_extern)
+ << Class << ClassAttr;
+ return;
+ }
+
+ if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ !ClassAttr->isInherited()) {
+ // Diagnose dll attributes on members of class with dll attribute.
+ for (Decl *Member : Class->decls()) {
+ if (!isa<VarDecl>(Member) && !isa<CXXMethodDecl>(Member))
+ continue;
+ InheritableAttr *MemberAttr = getDLLAttr(Member);
+ if (!MemberAttr || MemberAttr->isInherited() || Member->isInvalidDecl())
+ continue;
+
+ S.Diag(MemberAttr->getLocation(),
+ diag::err_attribute_dll_member_of_dll_class)
+ << MemberAttr << ClassAttr;
+ S.Diag(ClassAttr->getLocation(), diag::note_previous_attribute);
+ Member->setInvalidDecl();
+ }
+ }
+
+ if (Class->getDescribedClassTemplate())
+ // Don't inherit dll attribute until the template is instantiated.
+ return;
+
+ // The class is either imported or exported.
+ const bool ClassExported = ClassAttr->getKind() == attr::DLLExport;
+ const bool ClassImported = !ClassExported;
// Force declaration of implicit members so they can inherit the attribute.
S.ForceDeclarationOfImplicitMembers(Class);
@@ -4426,6 +4715,9 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
// FIXME: MSVC's docs say all bases must be exportable, but this doesn't
// seem to be true in practice?
+ TemplateSpecializationKind TSK =
+ Class->getTemplateSpecializationKind();
+
for (Decl *Member : Class->decls()) {
VarDecl *VD = dyn_cast<VarDecl>(Member);
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member);
@@ -4434,50 +4726,57 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
if (!VD && !MD)
continue;
- // Don't process deleted methods.
- if (MD && MD->isDeleted())
- continue;
+ if (MD) {
+ // Don't process deleted methods.
+ if (MD->isDeleted())
+ continue;
- if (MD && MD->isMoveAssignmentOperator() && !ClassExported &&
- MD->isInlined()) {
- // Current MSVC versions don't export the move assignment operators, so
- // don't attempt to import them if we have a definition.
- continue;
- }
+ if (MD->isMoveAssignmentOperator() && ClassImported && MD->isInlined()) {
+ // Current MSVC versions don't export the move assignment operators, so
+ // don't attempt to import them if we have a definition.
+ continue;
+ }
- if (InheritableAttr *MemberAttr = getDLLAttr(Member)) {
- if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
- !MemberAttr->isInherited() && !ClassAttr->isInherited()) {
- S.Diag(MemberAttr->getLocation(),
- diag::err_attribute_dll_member_of_dll_class)
- << MemberAttr << ClassAttr;
- S.Diag(ClassAttr->getLocation(), diag::note_previous_attribute);
- Member->setInvalidDecl();
+ if (MD->isInlined() && ClassImported &&
+ !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ // MinGW does not import inline functions.
continue;
}
- } else {
+ }
+
+ if (!getDLLAttr(Member)) {
auto *NewAttr =
cast<InheritableAttr>(ClassAttr->clone(S.getASTContext()));
NewAttr->setInherited(true);
Member->addAttr(NewAttr);
}
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member)) {
- if (ClassExported) {
- if (MD->isUserProvided()) {
- // Instantiate non-default methods.
- S.MarkFunctionReferenced(Class->getLocation(), MD);
- } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() ||
- MD->isCopyAssignmentOperator() ||
- MD->isMoveAssignmentOperator()) {
- // Instantiate non-trivial or explicitly defaulted methods, and the
- // copy assignment / move assignment operators.
- S.MarkFunctionReferenced(Class->getLocation(), MD);
- // Resolve its exception specification; CodeGen needs it.
- auto *FPT = MD->getType()->getAs<FunctionProtoType>();
- S.ResolveExceptionSpec(Class->getLocation(), FPT);
- S.ActOnFinishInlineMethodDef(MD);
- }
+ if (MD && ClassExported) {
+ if (MD->isUserProvided()) {
+ // Instantiate non-default class member functions ...
+
+ // .. except for certain kinds of template specializations.
+ if (TSK == TSK_ExplicitInstantiationDeclaration)
+ continue;
+ if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited())
+ continue;
+
+ S.MarkFunctionReferenced(Class->getLocation(), MD);
+
+ // The function will be passed to the consumer when its definition is
+ // encountered.
+ } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() ||
+ MD->isCopyAssignmentOperator() ||
+ MD->isMoveAssignmentOperator()) {
+ // Synthesize and instantiate non-trivial implicit methods, explicitly
+ // defaulted methods, and the copy and move assignment operators. The
+ // latter are exported even if they are trivial, because the address of
+ // an operator can be taken and should compare equal accross libraries.
+ S.MarkFunctionReferenced(Class->getLocation(), MD);
+
+ // There is no later point when we will see the definition of this
+ // function, so pass it to the consumer now.
+ S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
}
}
}
@@ -4563,13 +4862,18 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
+ bool HasMethodWithOverrideControl = false,
+ HasOverridingMethodWithoutOverrideControl = false;
if (!Record->isDependentType()) {
for (auto *M : Record->methods()) {
// See if a method overloads virtual methods in a base
// class without overriding any.
if (!M->isStatic())
DiagnoseHiddenVirtualMethods(M);
-
+ if (M->hasAttr<OverrideAttr>())
+ HasMethodWithOverrideControl = true;
+ else if (M->size_overridden_methods() > 0)
+ HasOverridingMethodWithoutOverrideControl = true;
// Check whether the explicitly-defaulted special members are valid.
if (!M->isInvalidDecl() && M->isExplicitlyDefaulted())
CheckExplicitlyDefaultedSpecialMember(M);
@@ -4588,41 +4892,12 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
- // C++11 [dcl.constexpr]p8: A constexpr specifier for a non-static member
- // function that is not a constructor declares that member function to be
- // const. [...] The class of which that function is a member shall be
- // a literal type.
- //
- // If the class has virtual bases, any constexpr members will already have
- // been diagnosed by the checks performed on the member declaration, so
- // suppress this (less useful) diagnostic.
- //
- // We delay this until we know whether an explicitly-defaulted (or deleted)
- // destructor for the class is trivial.
- if (LangOpts.CPlusPlus11 && !Record->isDependentType() &&
- !Record->isLiteral() && !Record->getNumVBases()) {
- for (const auto *M : Record->methods()) {
- if (M->isConstexpr() && M->isInstance() && !isa<CXXConstructorDecl>(M)) {
- switch (Record->getTemplateSpecializationKind()) {
- case TSK_ImplicitInstantiation:
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- // If a template instantiates to a non-literal type, but its members
- // instantiate to constexpr functions, the template is technically
- // ill-formed, but we allow it for sanity.
- continue;
-
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- RequireLiteralType(M->getLocation(), Context.getRecordType(Record),
- diag::err_constexpr_method_non_literal);
- break;
- }
-
- // Only produce one error per class.
- break;
- }
- }
+ if (HasMethodWithOverrideControl &&
+ HasOverridingMethodWithoutOverrideControl) {
+ // At least one method has the 'override' control declared.
+ // Diagnose all other overridden methods which do not have 'override' specified on them.
+ for (auto *M : Record->methods())
+ DiagnoseAbsenceOfOverrideControl(M);
}
// ms_struct is a request to use the same ABI rules as MSVC. Check
@@ -4723,7 +4998,7 @@ static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
case Sema::CXXCopyAssignment:
case Sema::CXXMoveAssignment:
- if (!S.getLangOpts().CPlusPlus1y)
+ if (!S.getLangOpts().CPlusPlus14)
return false;
// In C++1y, we need to perform overload resolution.
Ctor = false;
@@ -4818,8 +5093,8 @@ static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S,
FunctionProtoType::ExtProtoInfo EPI;
// Build an exception specification pointing back at this member.
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = MD;
+ EPI.ExceptionSpec.Type = EST_Unevaluated;
+ EPI.ExceptionSpec.SourceDecl = MD;
// Set the calling convention to the default for C++ instance methods.
EPI.ExtInfo = EPI.ExtInfo.withCallingConv(
@@ -4834,14 +5109,10 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD)
return;
// Evaluate the exception specification.
- ImplicitExceptionSpecification ExceptSpec =
- computeImplicitExceptionSpec(*this, Loc, MD);
-
- FunctionProtoType::ExtProtoInfo EPI;
- ExceptSpec.getEPI(EPI);
+ auto ESI = computeImplicitExceptionSpec(*this, Loc, MD).getExceptionSpec();
// Update the type of the special member to use it.
- UpdateExceptionSpec(MD, EPI);
+ UpdateExceptionSpec(MD, ESI);
// A user-provided destructor can be defined outside the class. When that
// happens, be sure to update the exception specification on both
@@ -4849,7 +5120,7 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD)
const FunctionProtoType *CanonicalFPT =
MD->getCanonicalDecl()->getType()->castAs<FunctionProtoType>();
if (CanonicalFPT->getExceptionSpecType() == EST_Unevaluated)
- UpdateExceptionSpec(MD->getCanonicalDecl(), EPI);
+ UpdateExceptionSpec(MD->getCanonicalDecl(), ESI);
}
void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
@@ -4911,7 +5182,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
// A defaulted special member cannot have cv-qualifiers.
if (Type->getTypeQuals()) {
Diag(MD->getLocation(), diag::err_defaulted_special_member_quals)
- << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus1y;
+ << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus14;
HadError = true;
}
}
@@ -4960,7 +5231,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
// destructors in C++1y), this is checked elsewhere.
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, RD, CSM,
HasConstParam);
- if ((getLangOpts().CPlusPlus1y ? !isa<CXXDestructorDecl>(MD)
+ if ((getLangOpts().CPlusPlus14 ? !isa<CXXDestructorDecl>(MD)
: isa<CXXConstructorDecl>(MD)) &&
MD->isConstexpr() && !Constexpr &&
MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
@@ -4995,10 +5266,10 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
// -- it is implicitly considered to have the same exception-specification
// as if it had been implicitly declared,
FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo();
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = MD;
+ EPI.ExceptionSpec.Type = EST_Unevaluated;
+ EPI.ExceptionSpec.SourceDecl = MD;
MD->setType(Context.getFunctionType(ReturnType,
- ArrayRef<QualType>(&ArgType,
+ llvm::makeArrayRef(&ArgType,
ExpectedParams),
EPI));
}
@@ -5026,11 +5297,18 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
/// C++11 [dcl.fct.def.default]p2.
void Sema::CheckExplicitlyDefaultedMemberExceptionSpec(
CXXMethodDecl *MD, const FunctionProtoType *SpecifiedType) {
+ // If the exception specification was explicitly specified but hadn't been
+ // parsed when the method was defaulted, grab it now.
+ if (SpecifiedType->getExceptionSpecType() == EST_Unparsed)
+ SpecifiedType =
+ MD->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>();
+
// Compute the implicit exception specification.
CallingConv CC = Context.getDefaultCallingConvention(/*IsVariadic=*/false,
/*IsCXXMethod=*/true);
FunctionProtoType::ExtProtoInfo EPI(CC);
- computeImplicitExceptionSpec(*this, MD->getLocation(), MD).getEPI(EPI);
+ EPI.ExceptionSpec = computeImplicitExceptionSpec(*this, MD->getLocation(), MD)
+ .getExceptionSpec();
const FunctionProtoType *ImplicitType = cast<FunctionProtoType>(
Context.getFunctionType(Context.VoidTy, None, EPI));
@@ -5043,27 +5321,21 @@ void Sema::CheckExplicitlyDefaultedMemberExceptionSpec(
}
void Sema::CheckDelayedMemberExceptionSpecs() {
- SmallVector<std::pair<const CXXDestructorDecl *, const CXXDestructorDecl *>,
- 2> Checks;
- SmallVector<std::pair<CXXMethodDecl *, const FunctionProtoType *>, 2> Specs;
+ decltype(DelayedExceptionSpecChecks) Checks;
+ decltype(DelayedDefaultedMemberExceptionSpecs) Specs;
- std::swap(Checks, DelayedDestructorExceptionSpecChecks);
+ std::swap(Checks, DelayedExceptionSpecChecks);
std::swap(Specs, DelayedDefaultedMemberExceptionSpecs);
// Perform any deferred checking of exception specifications for virtual
// destructors.
- for (unsigned i = 0, e = Checks.size(); i != e; ++i) {
- const CXXDestructorDecl *Dtor = Checks[i].first;
- assert(!Dtor->getParent()->isDependentType() &&
- "Should not ever add destructors of templates into the list.");
- CheckOverridingFunctionExceptionSpec(Dtor, Checks[i].second);
- }
+ for (auto &Check : Checks)
+ CheckOverridingFunctionExceptionSpec(Check.first, Check.second);
// Check that any explicitly-defaulted methods have exception specifications
// compatible with their implicit exception specifications.
- for (unsigned I = 0, N = Specs.size(); I != N; ++I)
- CheckExplicitlyDefaultedMemberExceptionSpec(Specs[I].first,
- Specs[I].second);
+ for (auto &Spec : Specs)
+ CheckExplicitlyDefaultedMemberExceptionSpec(Spec.first, Spec.second);
}
namespace {
@@ -5491,6 +5763,13 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
if (SMI.shouldDeleteForAllConstMembers())
return true;
+ if (getLangOpts().CUDA) {
+ // We should delete the special member in CUDA mode if target inference
+ // failed.
+ return inferCUDATargetForImplicitSpecialMember(RD, CSM, MD, SMI.ConstArg,
+ Diagnose);
+ }
+
return false;
}
@@ -5907,7 +6186,7 @@ namespace {
/// \brief Check whether any most overriden method from MD in Methods
static bool CheckMostOverridenMethods(const CXXMethodDecl *MD,
- const llvm::SmallPtrSet<const CXXMethodDecl *, 8>& Methods) {
+ const llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) {
if (MD->size_overridden_methods() == 0)
return Methods.count(MD->getCanonicalDecl());
for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
@@ -5945,7 +6224,14 @@ static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier,
if (!MD->isVirtual())
continue;
// If the method we are checking overrides a method from its base
- // don't warn about the other overloaded methods.
+ // don't warn about the other overloaded methods. Clang deviates from GCC
+ // by only diagnosing overloads of inherited virtual functions that do not
+ // override any other virtual functions in the base. GCC's
+ // -Woverloaded-virtual diagnoses any derived function hiding a virtual
+ // function from a base class. These cases may be better served by a
+ // warning (not specific to virtual functions) on call sites when the call
+ // would select a different function from the base class, were it visible.
+ // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example.
if (!Data.S->IsOverload(Data.Method, MD, false))
return true;
// Collect the overload only if its hidden.
@@ -5962,7 +6248,7 @@ static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier,
/// \brief Add the most overriden methods from MD to Methods
static void AddMostOverridenMethods(const CXXMethodDecl *MD,
- llvm::SmallPtrSet<const CXXMethodDecl *, 8>& Methods) {
+ llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) {
if (MD->size_overridden_methods() == 0)
Methods.insert(MD->getCanonicalDecl());
for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
@@ -6515,6 +6801,22 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
return Context.getFunctionType(Context.VoidTy, None, EPI);
}
+static void extendLeft(SourceRange &R, const SourceRange &Before) {
+ if (Before.isInvalid())
+ return;
+ R.setBegin(Before.getBegin());
+ if (R.getEnd().isInvalid())
+ R.setEnd(Before.getEnd());
+}
+
+static void extendRight(SourceRange &R, const SourceRange &After) {
+ if (After.isInvalid())
+ return;
+ if (R.getBegin().isInvalid())
+ R.setBegin(After.getBegin());
+ R.setEnd(After.getEnd());
+}
+
/// CheckConversionDeclarator - Called by ActOnDeclarator to check the
/// well-formednes of the conversion function declarator @p D with
/// type @p R. If there are any errors in the declarator, this routine
@@ -6536,7 +6838,9 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
SC = SC_None;
}
- QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId);
+ TypeSourceInfo *ConvTSI = nullptr;
+ QualType ConvType =
+ GetTypeFromParser(D.getName().ConversionFunctionId, &ConvTSI);
if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
// Conversion functions don't have return types, but the parser will
@@ -6570,9 +6874,75 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
// Diagnose "&operator bool()" and other such nonsense. This
// is actually a gcc extension which we don't support.
if (Proto->getReturnType() != ConvType) {
- Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl)
- << Proto->getReturnType();
- D.setInvalidType();
+ bool NeedsTypedef = false;
+ SourceRange Before, After;
+
+ // Walk the chunks and extract information on them for our diagnostic.
+ bool PastFunctionChunk = false;
+ for (auto &Chunk : D.type_objects()) {
+ switch (Chunk.Kind) {
+ case DeclaratorChunk::Function:
+ if (!PastFunctionChunk) {
+ if (Chunk.Fun.HasTrailingReturnType) {
+ TypeSourceInfo *TRT = nullptr;
+ GetTypeFromParser(Chunk.Fun.getTrailingReturnType(), &TRT);
+ if (TRT) extendRight(After, TRT->getTypeLoc().getSourceRange());
+ }
+ PastFunctionChunk = true;
+ break;
+ }
+ // Fall through.
+ case DeclaratorChunk::Array:
+ NeedsTypedef = true;
+ extendRight(After, Chunk.getSourceRange());
+ break;
+
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::MemberPointer:
+ extendLeft(Before, Chunk.getSourceRange());
+ break;
+
+ case DeclaratorChunk::Paren:
+ extendLeft(Before, Chunk.Loc);
+ extendRight(After, Chunk.EndLoc);
+ break;
+ }
+ }
+
+ SourceLocation Loc = Before.isValid() ? Before.getBegin() :
+ After.isValid() ? After.getBegin() :
+ D.getIdentifierLoc();
+ auto &&DB = Diag(Loc, diag::err_conv_function_with_complex_decl);
+ DB << Before << After;
+
+ if (!NeedsTypedef) {
+ DB << /*don't need a typedef*/0;
+
+ // If we can provide a correct fix-it hint, do so.
+ if (After.isInvalid() && ConvTSI) {
+ SourceLocation InsertLoc =
+ PP.getLocForEndOfToken(ConvTSI->getTypeLoc().getLocEnd());
+ DB << FixItHint::CreateInsertion(InsertLoc, " ")
+ << FixItHint::CreateInsertionFromRange(
+ InsertLoc, CharSourceRange::getTokenRange(Before))
+ << FixItHint::CreateRemoval(Before);
+ }
+ } else if (!Proto->getReturnType()->isDependentType()) {
+ DB << /*typedef*/1 << Proto->getReturnType();
+ } else if (getLangOpts().CPlusPlus11) {
+ DB << /*alias template*/2 << Proto->getReturnType();
+ } else {
+ DB << /*might not be fixable*/3;
+ }
+
+ // Recover by incorporating the other type chunks into the result type.
+ // Note, this does *not* change the name of the function. This is compatible
+ // with the GCC extension:
+ // struct S { &operator int(); } s;
+ // int &r = s.operator int(); // ok in GCC
+ // S::operator int&() {} // error in GCC, function name is 'operator int'.
ConvType = Proto->getReturnType();
}
@@ -6893,7 +7263,7 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() {
/*PrevDecl=*/nullptr);
getStdNamespace()->setImplicit(true);
}
-
+
return getStdNamespace();
}
@@ -7054,12 +7424,11 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *Ident) {
- NamespaceValidatorCCC Validator;
R.clear();
- if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(),
- R.getLookupKind(), Sc, &SS,
- Validator,
- Sema::CTK_ErrorRecovery)) {
+ if (TypoCorrection Corrected =
+ S.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), Sc, &SS,
+ llvm::make_unique<NamespaceValidatorCCC>(),
+ Sema::CTK_ErrorRecovery)) {
if (DeclContext *DC = S.computeDeclContext(SS, false)) {
std::string CorrectedStr(Corrected.getAsString(S.getLangOpts()));
bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
@@ -7124,6 +7493,10 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
NamedDecl *Named = R.getFoundDecl();
assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named))
&& "expected namespace decl");
+
+ // The use of a nested name specifier may trigger deprecation warnings.
+ DiagnoseUseOfDecl(Named, IdentLoc);
+
// C++ [namespace.udir]p1:
// A using-directive specifies that the names in the nominated
// namespace can be used in the scope in which the
@@ -7685,11 +8058,12 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
// Try to correct typos if possible.
if (R.empty()) {
- UsingValidatorCCC CCC(HasTypenameKeyword, IsInstantiation, SS.getScopeRep(),
- dyn_cast<CXXRecordDecl>(CurContext));
- if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
- R.getLookupKind(), S, &SS, CCC,
- CTK_ErrorRecovery)){
+ if (TypoCorrection Corrected = CorrectTypo(
+ R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
+ llvm::make_unique<UsingValidatorCCC>(
+ HasTypenameKeyword, IsInstantiation, SS.getScopeRep(),
+ dyn_cast<CXXRecordDecl>(CurContext)),
+ CTK_ErrorRecovery)) {
// We reject any correction for which ND would be NULL.
NamedDecl *ND = Corrected.getCorrectionDecl();
@@ -7874,7 +8248,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
// 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);
+ auto *RD = dyn_cast_or_null<CXXRecordDecl>(NamedContext);
if (RD && RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), RD))
RD = nullptr;
@@ -8164,6 +8538,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
TypeAliasTemplateDecl::Create(Context, CurContext, UsingLoc,
Name.Identifier, TemplateParams,
NewTD);
+ NewTD->setDescribedAliasTemplate(NewDecl);
NewDecl->setAccess(AS);
@@ -8185,57 +8560,65 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
return NewND;
}
-Decl *Sema::ActOnNamespaceAliasDef(Scope *S,
- SourceLocation NamespaceLoc,
- SourceLocation AliasLoc,
- IdentifierInfo *Alias,
- CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *Ident) {
+Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias, CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *Ident) {
// Lookup the namespace name.
LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName);
LookupParsedName(R, S, &SS);
+ if (R.isAmbiguous())
+ return nullptr;
+
+ if (R.empty()) {
+ if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) {
+ Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
+ return nullptr;
+ }
+ }
+ assert(!R.isAmbiguous() && !R.empty());
+
// Check if we have a previous declaration with the same name.
- NamedDecl *PrevDecl
- = LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName,
- ForRedeclaration);
+ NamedDecl *PrevDecl = LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName,
+ ForRedeclaration);
if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S))
PrevDecl = nullptr;
+ NamedDecl *ND = R.getFoundDecl();
+
if (PrevDecl) {
if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
// We already have an alias with the same name that points to the same
- // namespace, so don't create a new one.
- // FIXME: At some point, we'll want to create the (redundant)
- // declaration to maintain better source information.
- if (!R.isAmbiguous() && !R.empty() &&
- AD->getNamespace()->Equals(getNamespaceDecl(R.getFoundDecl())))
+ // namespace; check that it matches.
+ if (!AD->getNamespace()->Equals(getNamespaceDecl(ND))) {
+ Diag(AliasLoc, diag::err_redefinition_different_namespace_alias)
+ << Alias;
+ Diag(PrevDecl->getLocation(), diag::note_previous_namespace_alias)
+ << AD->getNamespace();
return nullptr;
- }
-
- unsigned DiagID = isa<NamespaceDecl>(PrevDecl) ? diag::err_redefinition :
- diag::err_redefinition_different_kind;
- Diag(AliasLoc, DiagID) << Alias;
- Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- return nullptr;
- }
-
- if (R.isAmbiguous())
- return nullptr;
-
- if (R.empty()) {
- if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) {
- Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
+ }
+ } else {
+ unsigned DiagID = isa<NamespaceDecl>(PrevDecl)
+ ? diag::err_redefinition
+ : diag::err_redefinition_different_kind;
+ Diag(AliasLoc, DiagID) << Alias;
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
return nullptr;
}
}
+ // The use of a nested name specifier may trigger deprecation warnings.
+ DiagnoseUseOfDecl(ND, IdentLoc);
+
NamespaceAliasDecl *AliasDecl =
NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
Alias, SS.getWithLocInContext(Context),
- IdentLoc, R.getFoundDecl());
+ IdentLoc, ND);
+ if (PrevDecl)
+ AliasDecl->setPreviousDecl(cast<NamespaceAliasDecl>(PrevDecl));
PushOnScopeChains(AliasDecl, S);
return AliasDecl;
@@ -8285,22 +8668,6 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc,
if (F->hasInClassInitializer()) {
if (Expr *E = F->getInClassInitializer())
ExceptSpec.CalledExpr(E);
- else if (!F->isInvalidDecl())
- // DR1351:
- // If the brace-or-equal-initializer of a non-static data member
- // invokes a defaulted default constructor of its class or of an
- // enclosing class in a potentially evaluated subexpression, the
- // program is ill-formed.
- //
- // This resolution is unworkable: the exception specification of the
- // default constructor can be needed in an unevaluated context, in
- // particular, in the operand of a noexcept-expression, and we can be
- // unable to compute an exception specification for an enclosed class.
- //
- // We do not allow an in-class initializer to require the evaluation
- // of the exception specification for any in-class initializer whose
- // definition is not lexically complete.
- Diag(Loc, diag::err_in_class_initializer_references_def_ctor) << MD;
} else if (const RecordType *RecordTy
= Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
@@ -8368,9 +8735,6 @@ Sema::ComputeInheritingCtorExceptionSpec(CXXConstructorDecl *CD) {
if (F->hasInClassInitializer()) {
if (Expr *E = F->getInClassInitializer())
ExceptSpec.CalledExpr(E);
- else if (!F->isInvalidDecl())
- Diag(CD->getLocation(),
- diag::err_in_class_initializer_references_def_ctor) << CD;
} else if (const RecordType *RecordTy
= Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
@@ -8392,7 +8756,7 @@ struct DeclaringSpecialMember {
DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM)
: S(S), D(RD, CSM) {
- WasAlreadyBeingDeclared = !S.SpecialMembersBeingDeclared.insert(D);
+ WasAlreadyBeingDeclared = !S.SpecialMembersBeingDeclared.insert(D).second;
if (WasAlreadyBeingDeclared)
// This almost never happens, but if it does, ensure that our cache
// doesn't contain a stale result.
@@ -8421,7 +8785,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
// user-declared constructor for class X, a default constructor is
// implicitly declared. An implicitly-declared default constructor
// is an inline public member of its class.
- assert(ClassDecl->needsImplicitDefaultConstructor() &&
+ assert(ClassDecl->needsImplicitDefaultConstructor() &&
"Should not build implicit default constructor!");
DeclaringSpecialMember DSM(*this, ClassDecl, CXXDefaultConstructor);
@@ -8445,7 +8809,13 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
/*isImplicitlyDeclared=*/true, Constexpr);
DefaultCon->setAccess(AS_public);
DefaultCon->setDefaulted();
- DefaultCon->setImplicit();
+
+ if (getLangOpts().CUDA) {
+ inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDefaultConstructor,
+ DefaultCon,
+ /* ConstRHS */ false,
+ /* Diagnose */ false);
+ }
// Build an exception specification pointing back at this constructor.
FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, DefaultCon);
@@ -8488,6 +8858,11 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
return;
}
+ // The exception specification is needed because we are defining the
+ // function.
+ ResolveExceptionSpec(CurrentLocation,
+ Constructor->getType()->castAs<FunctionProtoType>());
+
SourceLocation Loc = Constructor->getLocEnd().isValid()
? Constructor->getLocEnd()
: Constructor->getLocation();
@@ -8597,7 +8972,7 @@ private:
void inherit(const CXXConstructorDecl *Ctor) {
const FunctionProtoType *CtorType =
Ctor->getType()->castAs<FunctionProtoType>();
- ArrayRef<QualType> ArgTypes(CtorType->getParamTypes());
+ ArrayRef<QualType> ArgTypes = CtorType->getParamTypes();
FunctionProtoType::ExtProtoInfo EPI = CtorType->getExtProtoInfo();
SourceLocation UsingLoc = getUsingLoc(Ctor->getParent());
@@ -8737,8 +9112,8 @@ private:
// Build an unevaluated exception specification for this constructor.
const FunctionProtoType *FPT = DerivedType->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = DerivedCtor;
+ EPI.ExceptionSpec.Type = EST_Unevaluated;
+ EPI.ExceptionSpec.SourceDecl = DerivedCtor;
DerivedCtor->setType(Context.getFunctionType(FPT->getReturnType(),
FPT->getParamTypes(), EPI));
@@ -8900,7 +9275,13 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
/*isImplicitlyDeclared=*/true);
Destructor->setAccess(AS_public);
Destructor->setDefaulted();
- Destructor->setImplicit();
+
+ if (getLangOpts().CUDA) {
+ inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDestructor,
+ Destructor,
+ /* ConstRHS */ false,
+ /* Diagnose */ false);
+ }
// Build an exception specification pointing back at this destructor.
FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, Destructor);
@@ -8952,6 +9333,11 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
return;
}
+ // The exception specification is needed because we are defining the
+ // function.
+ ResolveExceptionSpec(CurrentLocation,
+ Destructor->getType()->castAs<FunctionProtoType>());
+
SourceLocation Loc = Destructor->getLocEnd().isValid()
? Destructor->getLocEnd()
: Destructor->getLocation();
@@ -8971,7 +9357,7 @@ void Sema::ActOnFinishCXXMemberDecls() {
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) {
if (Record->isInvalidDecl()) {
DelayedDefaultedMemberExceptionSpecs.clear();
- DelayedDestructorExceptionSpecChecks.clear();
+ DelayedExceptionSpecChecks.clear();
return;
}
}
@@ -8995,8 +9381,8 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
// the only thing of interest in the destructor type is its extended info.
// The return and arguments are fixed.
FunctionProtoType::ExtProtoInfo EPI = DtorType->getExtProtoInfo();
- EPI.ExceptionSpecType = EST_Unevaluated;
- EPI.ExceptionSpecDecl = Destructor;
+ EPI.ExceptionSpec.Type = EST_Unevaluated;
+ EPI.ExceptionSpec.SourceDecl = Destructor;
Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI));
// FIXME: If the destructor has a body that could throw, and the newly created
@@ -9032,7 +9418,7 @@ class RefBuilder: public ExprBuilder {
QualType VarType;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const override {
+ Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.BuildDeclRefExpr(Var, VarType, VK_LValue, Loc).get());
}
@@ -9042,7 +9428,7 @@ public:
class ThisBuilder: public ExprBuilder {
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const override {
+ Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.ActOnCXXThis(Loc).getAs<Expr>());
}
};
@@ -9054,7 +9440,7 @@ class CastBuilder: public ExprBuilder {
const CXXCastPath &Path;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const override {
+ Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.ImpCastExprToType(Builder.build(S, Loc), Type,
CK_UncheckedDerivedToBase, Kind,
&Path).get());
@@ -9069,7 +9455,7 @@ class DerefBuilder: public ExprBuilder {
const ExprBuilder &Builder;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const override {
+ Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(
S.CreateBuiltinUnaryOp(Loc, UO_Deref, Builder.build(S, Loc)).get());
}
@@ -9085,7 +9471,7 @@ class MemberBuilder: public ExprBuilder {
LookupResult &MemberLookup;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const override {
+ Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.BuildMemberReferenceExpr(
Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(),
nullptr, MemberLookup, nullptr).get());
@@ -9101,7 +9487,7 @@ class MoveCastBuilder: public ExprBuilder {
const ExprBuilder &Builder;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const override {
+ Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(CastForMoving(S, Builder.build(S, Loc)));
}
@@ -9112,7 +9498,7 @@ class LvalueConvBuilder: public ExprBuilder {
const ExprBuilder &Builder;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const override {
+ Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(
S.DefaultLvalueConversion(Builder.build(S, Loc)).get());
}
@@ -9125,7 +9511,7 @@ class SubscriptBuilder: public ExprBuilder {
const ExprBuilder &Index;
public:
- virtual Expr *build(Sema &S, SourceLocation Loc) const override {
+ Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.CreateBuiltinArraySubscriptExpr(
Base.build(S, Loc), Loc, Index.build(S, Loc), Loc).get());
}
@@ -9521,6 +9907,13 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
CopyAssignment->setDefaulted();
CopyAssignment->setImplicit();
+ if (getLangOpts().CUDA) {
+ inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyAssignment,
+ CopyAssignment,
+ /* ConstRHS */ Const,
+ /* Diagnose */ false);
+ }
+
// Build an exception specification pointing back at this member.
FunctionProtoType::ExtProtoInfo EPI =
getImplicitMethodEPI(*this, CopyAssignment);
@@ -9795,6 +10188,11 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
}
}
+ // The exception specification is needed because we are defining the
+ // function.
+ ResolveExceptionSpec(CurrentLocation,
+ CopyAssignOperator->getType()->castAs<FunctionProtoType>());
+
if (Invalid) {
CopyAssignOperator->setInvalidDecl();
return;
@@ -9898,6 +10296,13 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
MoveAssignment->setDefaulted();
MoveAssignment->setImplicit();
+ if (getLangOpts().CUDA) {
+ inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveAssignment,
+ MoveAssignment,
+ /* ConstRHS */ false,
+ /* Diagnose */ false);
+ }
+
// Build an exception specification pointing back at this member.
FunctionProtoType::ExtProtoInfo EPI =
getImplicitMethodEPI(*this, MoveAssignment);
@@ -10217,6 +10622,11 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
}
}
+ // The exception specification is needed because we are defining the
+ // function.
+ ResolveExceptionSpec(CurrentLocation,
+ MoveAssignOperator->getType()->castAs<FunctionProtoType>());
+
if (Invalid) {
MoveAssignOperator->setInvalidDecl();
return;
@@ -10319,6 +10729,13 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
CopyConstructor->setAccess(AS_public);
CopyConstructor->setDefaulted();
+ if (getLangOpts().CUDA) {
+ inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyConstructor,
+ CopyConstructor,
+ /* ConstRHS */ Const,
+ /* Diagnose */ false);
+ }
+
// Build an exception specification pointing back at this member.
FunctionProtoType::ExtProtoInfo EPI =
getImplicitMethodEPI(*this, CopyConstructor);
@@ -10386,6 +10803,11 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
ActOnCompoundStmt(Loc, Loc, None, /*isStmtExpr=*/false).getAs<Stmt>());
}
+ // The exception specification is needed because we are defining the
+ // function.
+ ResolveExceptionSpec(CurrentLocation,
+ CopyConstructor->getType()->castAs<FunctionProtoType>());
+
CopyConstructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
@@ -10484,6 +10906,13 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
MoveConstructor->setAccess(AS_public);
MoveConstructor->setDefaulted();
+ if (getLangOpts().CUDA) {
+ inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveConstructor,
+ MoveConstructor,
+ /* ConstRHS */ false,
+ /* Diagnose */ false);
+ }
+
// Build an exception specification pointing back at this member.
FunctionProtoType::ExtProtoInfo EPI =
getImplicitMethodEPI(*this, MoveConstructor);
@@ -10546,6 +10975,11 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
Loc, Loc, None, /*isStmtExpr=*/ false).getAs<Stmt>());
}
+ // The exception specification is needed because we are defining the
+ // function.
+ ResolveExceptionSpec(CurrentLocation,
+ MoveConstructor->getType()->castAs<FunctionProtoType>());
+
MoveConstructor->markUsed(Context);
MarkVTableUsed(CurrentLocation, ClassDecl);
@@ -10765,6 +11199,56 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
ParenRange);
}
+ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
+ assert(Field->hasInClassInitializer());
+
+ // If we already have the in-class initializer nothing needs to be done.
+ if (Field->getInClassInitializer())
+ return CXXDefaultInitExpr::Create(Context, Loc, Field);
+
+ // Maybe we haven't instantiated the in-class initializer. Go check the
+ // pattern FieldDecl to see if it has one.
+ CXXRecordDecl *ParentRD = cast<CXXRecordDecl>(Field->getParent());
+
+ if (isTemplateInstantiation(ParentRD->getTemplateSpecializationKind())) {
+ CXXRecordDecl *ClassPattern = ParentRD->getTemplateInstantiationPattern();
+ DeclContext::lookup_result Lookup =
+ ClassPattern->lookup(Field->getDeclName());
+ assert(Lookup.size() == 1);
+ FieldDecl *Pattern = cast<FieldDecl>(Lookup[0]);
+ if (InstantiateInClassInitializer(Loc, Field, Pattern,
+ getTemplateInstantiationArgs(Field)))
+ return ExprError();
+ return CXXDefaultInitExpr::Create(Context, Loc, Field);
+ }
+
+ // DR1351:
+ // If the brace-or-equal-initializer of a non-static data member
+ // invokes a defaulted default constructor of its class or of an
+ // enclosing class in a potentially evaluated subexpression, the
+ // program is ill-formed.
+ //
+ // This resolution is unworkable: the exception specification of the
+ // default constructor can be needed in an unevaluated context, in
+ // particular, in the operand of a noexcept-expression, and we can be
+ // unable to compute an exception specification for an enclosed class.
+ //
+ // Any attempt to resolve the exception specification of a defaulted default
+ // constructor before the initializer is lexically complete will ultimately
+ // come here at which point we can diagnose it.
+ RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext();
+ if (OutermostClass == ParentRD) {
+ Diag(Field->getLocEnd(), diag::err_in_class_initializer_not_yet_parsed)
+ << ParentRD << Field;
+ } else {
+ Diag(Field->getLocEnd(),
+ diag::err_in_class_initializer_not_yet_parsed_outer_class)
+ << ParentRD << OutermostClass << Field;
+ }
+
+ return ExprError();
+}
+
void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
if (VD->isInvalidDecl()) return;
@@ -10834,8 +11318,7 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
DiagnoseSentinelCalls(Constructor, Loc, AllArgs);
CheckConstructorCall(Constructor,
- llvm::makeArrayRef<const Expr *>(AllArgs.data(),
- AllArgs.size()),
+ llvm::makeArrayRef(AllArgs.data(), AllArgs.size()),
Proto, Loc);
return Invalid;
@@ -12118,8 +12601,12 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
}
// Mark templated-scope function declarations as unsupported.
- if (FD->getNumTemplateParameterLists())
+ if (FD->getNumTemplateParameterLists() && SS.isValid()) {
+ Diag(FD->getLocation(), diag::warn_template_qualified_friend_unsupported)
+ << SS.getScopeRep() << SS.getRange()
+ << cast<CXXRecordDecl>(CurContext);
FrD->setUnsupportedFriend(true);
+ }
}
return ND;
@@ -12220,11 +12707,6 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
CheckExplicitlyDefaultedSpecialMember(MD);
- // The exception specification is needed because we are defining the
- // function.
- ResolveExceptionSpec(DefaultLoc,
- MD->getType()->castAs<FunctionProtoType>());
-
if (MD->isInvalidDecl())
return;
@@ -12538,7 +13020,7 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired));
if (!Pos.second) {
// If we already had an entry, check to see if we are promoting this vtable
- // to required a definition. If so, we need to reappend to the VTableUses
+ // to require a definition. If so, we need to reappend to the VTableUses
// list, since we may have already processed the first entry.
if (DefinitionRequired && !Pos.first->second) {
Pos.first->second = true;
@@ -12739,10 +13221,10 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
AllToInit.push_back(Member);
// Be sure that the destructor is accessible and is marked as referenced.
- if (const RecordType *RecordTy
- = Context.getBaseElementType(Field->getType())
- ->getAs<RecordType>()) {
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (const RecordType *RecordTy =
+ Context.getBaseElementType(Field->getType())
+ ->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) {
MarkFunctionReferenced(Field->getLocation(), Destructor);
CheckDestructorAccess(Field->getLocation(), Destructor,
@@ -12780,7 +13262,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
// Avoid dereferencing a null pointer here.
*TCanonical = Target? Target->getCanonicalDecl() : nullptr;
- if (!Current.insert(Canonical))
+ if (!Current.insert(Canonical).second)
return;
// We know that beyond here, we aren't chaining into a cycle.
@@ -12898,6 +13380,7 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) {
FindCXXThisExpr Finder(*this);
switch (Proto->getExceptionSpecType()) {
+ case EST_Unparsed:
case EST_Uninstantiated:
case EST_Unevaluated:
case EST_BasicNoexcept:
@@ -12934,27 +13417,27 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
else if (const auto *G = dyn_cast<PtGuardedByAttr>(A))
Arg = G->getArg();
else if (const auto *AA = dyn_cast<AcquiredAfterAttr>(A))
- Args = ArrayRef<Expr *>(AA->args_begin(), AA->args_size());
+ Args = llvm::makeArrayRef(AA->args_begin(), AA->args_size());
else if (const auto *AB = dyn_cast<AcquiredBeforeAttr>(A))
- Args = ArrayRef<Expr *>(AB->args_begin(), AB->args_size());
+ Args = llvm::makeArrayRef(AB->args_begin(), AB->args_size());
else if (const auto *ETLF = dyn_cast<ExclusiveTrylockFunctionAttr>(A)) {
Arg = ETLF->getSuccessValue();
- Args = ArrayRef<Expr *>(ETLF->args_begin(), ETLF->args_size());
+ Args = llvm::makeArrayRef(ETLF->args_begin(), ETLF->args_size());
} else if (const auto *STLF = dyn_cast<SharedTrylockFunctionAttr>(A)) {
Arg = STLF->getSuccessValue();
- Args = ArrayRef<Expr *>(STLF->args_begin(), STLF->args_size());
+ Args = llvm::makeArrayRef(STLF->args_begin(), STLF->args_size());
} else if (const auto *LR = dyn_cast<LockReturnedAttr>(A))
Arg = LR->getArg();
else if (const auto *LE = dyn_cast<LocksExcludedAttr>(A))
- Args = ArrayRef<Expr *>(LE->args_begin(), LE->args_size());
+ Args = llvm::makeArrayRef(LE->args_begin(), LE->args_size());
else if (const auto *RC = dyn_cast<RequiresCapabilityAttr>(A))
- Args = ArrayRef<Expr *>(RC->args_begin(), RC->args_size());
+ Args = llvm::makeArrayRef(RC->args_begin(), RC->args_size());
else if (const auto *AC = dyn_cast<AcquireCapabilityAttr>(A))
- Args = ArrayRef<Expr *>(AC->args_begin(), AC->args_size());
+ Args = llvm::makeArrayRef(AC->args_begin(), AC->args_size());
else if (const auto *AC = dyn_cast<TryAcquireCapabilityAttr>(A))
- Args = ArrayRef<Expr *>(AC->args_begin(), AC->args_size());
+ Args = llvm::makeArrayRef(AC->args_begin(), AC->args_size());
else if (const auto *RC = dyn_cast<ReleaseCapabilityAttr>(A))
- Args = ArrayRef<Expr *>(RC->args_begin(), RC->args_size());
+ Args = llvm::makeArrayRef(RC->args_begin(), RC->args_size());
if (Arg && !Finder.TraverseStmt(Arg))
return true;
@@ -12968,28 +13451,29 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
return false;
}
-void
-Sema::checkExceptionSpecification(ExceptionSpecificationType EST,
- ArrayRef<ParsedType> DynamicExceptions,
- ArrayRef<SourceRange> DynamicExceptionRanges,
- Expr *NoexceptExpr,
- SmallVectorImpl<QualType> &Exceptions,
- FunctionProtoType::ExtProtoInfo &EPI) {
+void Sema::checkExceptionSpecification(
+ bool IsTopLevel, ExceptionSpecificationType EST,
+ ArrayRef<ParsedType> DynamicExceptions,
+ ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr,
+ SmallVectorImpl<QualType> &Exceptions,
+ FunctionProtoType::ExceptionSpecInfo &ESI) {
Exceptions.clear();
- EPI.ExceptionSpecType = EST;
+ ESI.Type = EST;
if (EST == EST_Dynamic) {
Exceptions.reserve(DynamicExceptions.size());
for (unsigned ei = 0, ee = DynamicExceptions.size(); ei != ee; ++ei) {
// FIXME: Preserve type source info.
QualType ET = GetTypeFromParser(DynamicExceptions[ei]);
- SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- collectUnexpandedParameterPacks(ET, Unexpanded);
- if (!Unexpanded.empty()) {
- DiagnoseUnexpandedParameterPacks(DynamicExceptionRanges[ei].getBegin(),
- UPPC_ExceptionType,
- Unexpanded);
- continue;
+ if (IsTopLevel) {
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ collectUnexpandedParameterPacks(ET, Unexpanded);
+ if (!Unexpanded.empty()) {
+ DiagnoseUnexpandedParameterPacks(
+ DynamicExceptionRanges[ei].getBegin(), UPPC_ExceptionType,
+ Unexpanded);
+ continue;
+ }
}
// Check that the type is valid for an exception spec, and
@@ -12997,11 +13481,10 @@ Sema::checkExceptionSpecification(ExceptionSpecificationType EST,
if (!CheckSpecifiedExceptionType(ET, DynamicExceptionRanges[ei]))
Exceptions.push_back(ET);
}
- EPI.NumExceptions = Exceptions.size();
- EPI.Exceptions = Exceptions.data();
+ ESI.Exceptions = Exceptions;
return;
}
-
+
if (EST == EST_ComputedNoexcept) {
// If an error occurred, there's no expression here.
if (NoexceptExpr) {
@@ -13009,59 +13492,59 @@ Sema::checkExceptionSpecification(ExceptionSpecificationType EST,
NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
Context.BoolTy) &&
"Parser should have made sure that the expression is boolean");
- if (NoexceptExpr && DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
- EPI.ExceptionSpecType = EST_BasicNoexcept;
+ if (IsTopLevel && NoexceptExpr &&
+ DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
+ ESI.Type = EST_BasicNoexcept;
return;
}
-
+
if (!NoexceptExpr->isValueDependent())
NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, nullptr,
diag::err_noexcept_needs_constant_expression,
/*AllowFold*/ false).get();
- EPI.NoexceptExpr = NoexceptExpr;
+ ESI.NoexceptExpr = NoexceptExpr;
}
return;
}
}
-/// IdentifyCUDATarget - Determine the CUDA compilation target for this function
-Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
- // Implicitly declared functions (e.g. copy constructors) are
- // __host__ __device__
- if (D->isImplicit())
- return CFT_HostDevice;
-
- if (D->hasAttr<CUDAGlobalAttr>())
- return CFT_Global;
+void Sema::actOnDelayedExceptionSpecification(Decl *MethodD,
+ ExceptionSpecificationType EST,
+ SourceRange SpecificationRange,
+ ArrayRef<ParsedType> DynamicExceptions,
+ ArrayRef<SourceRange> DynamicExceptionRanges,
+ Expr *NoexceptExpr) {
+ if (!MethodD)
+ return;
- if (D->hasAttr<CUDADeviceAttr>()) {
- if (D->hasAttr<CUDAHostAttr>())
- return CFT_HostDevice;
- return CFT_Device;
- }
+ // Dig out the method we're referring to.
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(MethodD))
+ MethodD = FunTmpl->getTemplatedDecl();
- return CFT_Host;
-}
+ CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(MethodD);
+ if (!Method)
+ return;
-bool Sema::CheckCUDATarget(CUDAFunctionTarget CallerTarget,
- CUDAFunctionTarget CalleeTarget) {
- // CUDA B.1.1 "The __device__ qualifier declares a function that is...
- // Callable from the device only."
- if (CallerTarget == CFT_Host && CalleeTarget == CFT_Device)
- return true;
+ // Check the exception specification.
+ llvm::SmallVector<QualType, 4> Exceptions;
+ FunctionProtoType::ExceptionSpecInfo ESI;
+ checkExceptionSpecification(/*IsTopLevel*/true, EST, DynamicExceptions,
+ DynamicExceptionRanges, NoexceptExpr, Exceptions,
+ ESI);
- // CUDA B.1.2 "The __global__ qualifier declares a function that is...
- // Callable from the host only."
- // CUDA B.1.3 "The __host__ qualifier declares a function that is...
- // Callable from the host only."
- if ((CallerTarget == CFT_Device || CallerTarget == CFT_Global) &&
- (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global))
- return true;
+ // Update the exception specification on the function type.
+ Context.adjustExceptionSpec(Method, ESI, /*AsWritten*/true);
- if (CallerTarget == CFT_HostDevice && CalleeTarget != CFT_HostDevice)
- return true;
+ if (Method->isStatic())
+ checkThisInStaticMemberFunctionExceptionSpec(Method);
- return false;
+ if (Method->isVirtual()) {
+ // Check overrides, which we previously had to delay.
+ for (CXXMethodDecl::method_iterator O = Method->begin_overridden_methods(),
+ OEnd = Method->end_overridden_methods();
+ O != OEnd; ++O)
+ CheckOverridingFunctionExceptionSpec(Method, *O);
+ }
}
/// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class.
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index b5205b3e6238..7e3da941b339 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -118,10 +118,7 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
// a suitable return type, but the new (overriding) method does not have
// a suitable return type.
QualType ResultType = NewMethod->getReturnType();
- SourceRange ResultTypeRange;
- if (const TypeSourceInfo *ResultTypeInfo =
- NewMethod->getReturnTypeSourceInfo())
- ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange();
+ SourceRange ResultTypeRange = NewMethod->getReturnTypeSourceRange();
// Figure out which class this method is part of, if any.
ObjCInterfaceDecl *CurrentClass
@@ -204,15 +201,13 @@ bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) {
case OMF_autorelease:
case OMF_retainCount:
case OMF_self:
+ case OMF_initialize:
case OMF_performSelector:
return false;
case OMF_dealloc:
if (!Context.hasSameType(method->getReturnType(), Context.VoidTy)) {
- SourceRange ResultTypeRange;
- if (const TypeSourceInfo *ResultTypeInfo =
- method->getReturnTypeSourceInfo())
- ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange();
+ SourceRange ResultTypeRange = method->getReturnTypeSourceRange();
if (ResultTypeRange.isInvalid())
Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
<< method->getReturnType()
@@ -359,6 +354,7 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
case OMF_copy:
case OMF_new:
case OMF_self:
+ case OMF_initialize:
case OMF_performSelector:
break;
}
@@ -520,10 +516,11 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
if (!PrevDecl) {
// Try to correct for a typo in the superclass name without correcting
// to the class we're defining.
- ObjCInterfaceValidatorCCC Validator(IDecl);
- if (TypoCorrection Corrected = CorrectTypo(
- DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope,
- nullptr, Validator, CTK_ErrorRecovery)) {
+ if (TypoCorrection Corrected =
+ CorrectTypo(DeclarationNameInfo(SuperName, SuperLoc),
+ LookupOrdinaryName, TUScope, nullptr,
+ llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl),
+ CTK_ErrorRecovery)) {
diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
<< SuperName << ClassName);
PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
@@ -790,10 +787,10 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first,
ProtocolId[i].second);
if (!PDecl) {
- DeclFilterCCC<ObjCProtocolDecl> Validator;
TypoCorrection Corrected = CorrectTypo(
DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second),
- LookupObjCProtocolName, TUScope, nullptr, Validator,
+ LookupObjCProtocolName, TUScope, nullptr,
+ llvm::make_unique<DeclFilterCCC<ObjCProtocolDecl>>(),
CTK_ErrorRecovery);
if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>()))
diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest)
@@ -1031,11 +1028,9 @@ Decl *Sema::ActOnStartClassImplementation(
} else {
// We did not find anything with the name ClassName; try to correct for
// typos in the class name.
- ObjCInterfaceValidatorCCC Validator;
- TypoCorrection Corrected =
- CorrectTypo(DeclarationNameInfo(ClassName, ClassLoc),
- LookupOrdinaryName, TUScope, nullptr, Validator,
- CTK_NonError);
+ TypoCorrection Corrected = CorrectTypo(
+ DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope,
+ nullptr, llvm::make_unique<ObjCInterfaceValidatorCCC>(), CTK_NonError);
if (Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
// Suggest the (potentially) correct interface name. Don't provide a
// code-modification hint or use the typo name for recovery, because
@@ -1362,9 +1357,9 @@ static bool CheckMethodOverrideReturn(Sema &S,
? diag::warn_conflicting_overriding_ret_type_modifiers
: diag::warn_conflicting_ret_type_modifiers))
<< MethodImpl->getDeclName()
- << getTypeRange(MethodImpl->getReturnTypeSourceInfo());
+ << MethodImpl->getReturnTypeSourceRange();
S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)
- << getTypeRange(MethodDecl->getReturnTypeSourceInfo());
+ << MethodDecl->getReturnTypeSourceRange();
}
else
return false;
@@ -1402,11 +1397,11 @@ static bool CheckMethodOverrideReturn(Sema &S,
S.Diag(MethodImpl->getLocation(), DiagID)
<< MethodImpl->getDeclName() << MethodDecl->getReturnType()
<< MethodImpl->getReturnType()
- << getTypeRange(MethodImpl->getReturnTypeSourceInfo());
+ << MethodImpl->getReturnTypeSourceRange();
S.Diag(MethodDecl->getLocation(), IsOverridingMode
? diag::note_previous_declaration
: diag::note_previous_definition)
- << getTypeRange(MethodDecl->getReturnTypeSourceInfo());
+ << MethodDecl->getReturnTypeSourceRange();
return false;
}
@@ -1521,6 +1516,7 @@ static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl,
case OMF_finalize:
case OMF_retainCount:
case OMF_self:
+ case OMF_initialize:
case OMF_performSelector:
// Mismatches for these methods don't change ownership
// conventions, so we don't care.
@@ -1819,7 +1815,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
// Check and see if instance methods in class interface have been
// implemented in the implementation class. If so, their types match.
for (auto *I : CDecl->instance_methods()) {
- if (!InsMapSeen.insert(I->getSelector()))
+ if (!InsMapSeen.insert(I->getSelector()).second)
continue;
if (!I->isPropertyAccessor() &&
!InsMap.count(I->getSelector())) {
@@ -1846,7 +1842,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
// Check and see if class methods in class interface have been
// implemented in the implementation class. If so, their types match.
for (auto *I : CDecl->class_methods()) {
- if (!ClsMapSeen.insert(I->getSelector()))
+ if (!ClsMapSeen.insert(I->getSelector()).second)
continue;
if (!ClsMap.count(I->getSelector())) {
if (ImmediateClass)
@@ -2008,13 +2004,12 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
IncompleteImpl, InsMap, ClsMap, CDecl,
ExplicitImplProtocols);
DiagnoseUnimplementedProperties(S, IMPDecl, CDecl,
- /* SynthesizeProperties */ false);
+ /*SynthesizeProperties=*/false);
}
} else
llvm_unreachable("invalid ObjCContainerDecl type.");
}
-/// ActOnForwardClassDeclaration -
Sema::DeclGroupPtrTy
Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
@@ -2041,10 +2036,11 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
} else {
// a forward class declaration matching a typedef name of a class refers
// to the underlying class. Just ignore the forward class with a warning
- // as this will force the intended behavior which is to lookup the typedef
- // name.
+ // as this will force the intended behavior which is to lookup the
+ // typedef name.
if (isa<ObjCObjectType>(TDD->getUnderlyingType())) {
- Diag(AtClassLoc, diag::warn_forward_class_redefinition) << IdentList[i];
+ Diag(AtClassLoc, diag::warn_forward_class_redefinition)
+ << IdentList[i];
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
continue;
}
@@ -2107,7 +2103,12 @@ static bool matchTypes(ASTContext &Context, Sema::MethodMatchStrategy strategy,
// validate the basic, low-level compatibility of the two types.
// As a minimum, require the sizes and alignments to match.
- if (Context.getTypeInfo(left) != Context.getTypeInfo(right))
+ TypeInfo LeftTI = Context.getTypeInfo(left);
+ TypeInfo RightTI = Context.getTypeInfo(right);
+ if (LeftTI.Width != RightTI.Width)
+ return false;
+
+ if (LeftTI.Align != RightTI.Align)
return false;
// Consider all the kinds of non-dependent canonical types:
@@ -2159,7 +2160,13 @@ static bool tryMatchRecordTypes(ASTContext &Context,
return false;
// Require size and alignment to match.
- if (Context.getTypeInfo(lt) != Context.getTypeInfo(rt)) return false;
+ TypeInfo LeftTI = Context.getTypeInfo(lt);
+ TypeInfo RightTI = Context.getTypeInfo(rt);
+ if (LeftTI.Width != RightTI.Width)
+ return false;
+
+ if (LeftTI.Align != RightTI.Align)
+ return false;
// Require fields to match.
RecordDecl::field_iterator li = left->field_begin(), le = left->field_end();
@@ -2210,21 +2217,22 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left,
return true;
}
-void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) {
+void Sema::addMethodToGlobalList(ObjCMethodList *List,
+ ObjCMethodDecl *Method) {
// Record at the head of the list whether there were 0, 1, or >= 2 methods
// inside categories.
- if (ObjCCategoryDecl *
- CD = dyn_cast<ObjCCategoryDecl>(Method->getDeclContext()))
+ if (ObjCCategoryDecl *CD =
+ dyn_cast<ObjCCategoryDecl>(Method->getDeclContext()))
if (!CD->IsClassExtension() && List->getBits() < 2)
- List->setBits(List->getBits()+1);
+ List->setBits(List->getBits() + 1);
// If the list is empty, make it a singleton list.
- if (List->Method == nullptr) {
- List->Method = Method;
+ if (List->getMethod() == nullptr) {
+ List->setMethod(Method);
List->setNext(nullptr);
return;
}
-
+
// We've seen a method with this name, see if we have already seen this type
// signature.
ObjCMethodList *Previous = List;
@@ -2233,35 +2241,42 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) {
if (getLangOpts().Modules && !getLangOpts().CurrentModule.empty())
continue;
- if (!MatchTwoMethodDeclarations(Method, List->Method))
+ if (!MatchTwoMethodDeclarations(Method, List->getMethod()))
continue;
-
- ObjCMethodDecl *PrevObjCMethod = List->Method;
+
+ ObjCMethodDecl *PrevObjCMethod = List->getMethod();
// Propagate the 'defined' bit.
if (Method->isDefined())
PrevObjCMethod->setDefined(true);
-
+ else {
+ // Objective-C doesn't allow an @interface for a class after its
+ // @implementation. So if Method is not defined and there already is
+ // an entry for this type signature, Method has to be for a different
+ // class than PrevObjCMethod.
+ List->setHasMoreThanOneDecl(true);
+ }
+
// If a method is deprecated, push it in the global pool.
// This is used for better diagnostics.
if (Method->isDeprecated()) {
if (!PrevObjCMethod->isDeprecated())
- List->Method = Method;
+ List->setMethod(Method);
}
- // If new method is unavailable, push it into global pool
+ // If the new method is unavailable, push it into global pool
// unless previous one is deprecated.
if (Method->isUnavailable()) {
if (PrevObjCMethod->getAvailability() < AR_Deprecated)
- List->Method = Method;
+ List->setMethod(Method);
}
-
+
return;
}
-
+
// We have a new signature for an existing method - add it.
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
- Previous->setNext(new (Mem) ObjCMethodList(Method, nullptr));
+ Previous->setNext(new (Mem) ObjCMethodList(Method));
}
/// \brief Read the contents of the method pool for a given selector from
@@ -2284,7 +2299,7 @@ void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,
if (Pos == MethodPool.end())
Pos = MethodPool.insert(std::make_pair(Method->getSelector(),
GlobalMethods())).first;
-
+
Method->setDefined(impl);
ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second;
@@ -2310,6 +2325,32 @@ static bool isAcceptableMethodMismatch(ObjCMethodDecl *chosen,
return (chosen->getReturnType()->isIntegerType());
}
+bool Sema::CollectMultipleMethodsInGlobalPool(
+ Selector Sel, SmallVectorImpl<ObjCMethodDecl *> &Methods, bool instance) {
+ if (ExternalSource)
+ ReadMethodPool(Sel);
+
+ GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
+ if (Pos == MethodPool.end())
+ return false;
+ // Gather the non-hidden methods.
+ ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
+ for (ObjCMethodList *M = &MethList; M; M = M->getNext())
+ if (M->getMethod() && !M->getMethod()->isHidden())
+ Methods.push_back(M->getMethod());
+ return Methods.size() > 1;
+}
+
+bool Sema::AreMultipleMethodsInGlobalPool(Selector Sel, bool instance) {
+ GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
+ // Test for no method in the pool which should not trigger any warning by
+ // caller.
+ if (Pos == MethodPool.end())
+ return true;
+ ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
+ return MethList.hasMoreThanOneDecl();
+}
+
ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
bool receiverIdOrClass,
bool warn, bool instance) {
@@ -2324,12 +2365,12 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
SmallVector<ObjCMethodDecl *, 4> Methods;
for (ObjCMethodList *M = &MethList; M; M = M->getNext()) {
- if (M->Method && !M->Method->isHidden()) {
+ if (M->getMethod() && !M->getMethod()->isHidden()) {
// If we're not supposed to warn about mismatches, we're done.
if (!warn)
- return M->Method;
+ return M->getMethod();
- Methods.push_back(M->Method);
+ Methods.push_back(M->getMethod());
}
}
@@ -2401,13 +2442,13 @@ ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
GlobalMethods &Methods = Pos->second;
for (const ObjCMethodList *Method = &Methods.first; Method;
Method = Method->getNext())
- if (Method->Method && Method->Method->isDefined())
- return Method->Method;
+ if (Method->getMethod() && Method->getMethod()->isDefined())
+ return Method->getMethod();
for (const ObjCMethodList *Method = &Methods.second; Method;
Method = Method->getNext())
- if (Method->Method && Method->Method->isDefined())
- return Method->Method;
+ if (Method->getMethod() && Method->getMethod()->isDefined())
+ return Method->getMethod();
return nullptr;
}
@@ -2470,25 +2511,27 @@ Sema::SelectorsForTypoCorrection(Selector Sel,
e = MethodPool.end(); b != e; b++) {
// instance methods
for (ObjCMethodList *M = &b->second.first; M; M=M->getNext())
- if (M->Method &&
- (M->Method->getSelector().getNumArgs() == NumArgs) &&
- (M->Method->getSelector() != Sel)) {
+ if (M->getMethod() &&
+ (M->getMethod()->getSelector().getNumArgs() == NumArgs) &&
+ (M->getMethod()->getSelector() != Sel)) {
if (ObjectIsId)
- Methods.push_back(M->Method);
+ Methods.push_back(M->getMethod());
else if (!ObjectIsClass &&
- HelperIsMethodInObjCType(*this, M->Method->getSelector(), ObjectType))
- Methods.push_back(M->Method);
+ HelperIsMethodInObjCType(*this, M->getMethod()->getSelector(),
+ ObjectType))
+ Methods.push_back(M->getMethod());
}
// class methods
for (ObjCMethodList *M = &b->second.second; M; M=M->getNext())
- if (M->Method &&
- (M->Method->getSelector().getNumArgs() == NumArgs) &&
- (M->Method->getSelector() != Sel)) {
+ if (M->getMethod() &&
+ (M->getMethod()->getSelector().getNumArgs() == NumArgs) &&
+ (M->getMethod()->getSelector() != Sel)) {
if (ObjectIsClass)
- Methods.push_back(M->Method);
+ Methods.push_back(M->getMethod());
else if (!ObjectIsId &&
- HelperIsMethodInObjCType(*this, M->Method->getSelector(), ObjectType))
- Methods.push_back(M->Method);
+ HelperIsMethodInObjCType(*this, M->getMethod()->getSelector(),
+ ObjectType))
+ Methods.push_back(M->getMethod());
}
}
@@ -2818,7 +2861,7 @@ public:
}
ObjCMethodList &list =
method->isInstanceMethod() ? it->second.first : it->second.second;
- if (!list.Method) return;
+ if (!list.getMethod()) return;
ObjCContainerDecl *container
= cast<ObjCContainerDecl>(method->getDeclContext());
@@ -3237,6 +3280,7 @@ Decl *Sema::ActOnMethodDeclaration(
case OMF_mutableCopy:
case OMF_release:
case OMF_retainCount:
+ case OMF_initialize:
case OMF_performSelector:
break;
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index b92fcbd2a0d9..2387325be435 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -35,6 +35,33 @@ static const FunctionProtoType *GetUnderlyingFunction(QualType T)
return T->getAs<FunctionProtoType>();
}
+/// HACK: libstdc++ has a bug where it shadows std::swap with a member
+/// swap function then tries to call std::swap unqualified from the exception
+/// specification of that function. This function detects whether we're in
+/// such a case and turns off delay-parsing of exception specifications.
+bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
+ auto *RD = dyn_cast<CXXRecordDecl>(CurContext);
+
+ // All the problem cases are member functions named "swap" within class
+ // templates declared directly within namespace std.
+ if (!RD || RD->getEnclosingNamespaceContext() != getStdNamespace() ||
+ !RD->getIdentifier() || !RD->getDescribedClassTemplate() ||
+ !D.getIdentifier() || !D.getIdentifier()->isStr("swap"))
+ return false;
+
+ // Only apply this hack within a system header.
+ if (!Context.getSourceManager().isInSystemHeader(D.getLocStart()))
+ return false;
+
+ return llvm::StringSwitch<bool>(RD->getIdentifier()->getName())
+ .Case("array", true)
+ .Case("pair", true)
+ .Case("priority_queue", true)
+ .Case("stack", true)
+ .Case("queue", true)
+ .Default(false);
+}
+
/// CheckSpecifiedExceptionType - Check if the given type is valid in an
/// exception specification. Incomplete types, or pointers to incomplete types
/// other than void are not allowed.
@@ -112,6 +139,11 @@ bool Sema::CheckDistantExceptionSpec(QualType T) {
const FunctionProtoType *
Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
+ if (FPT->getExceptionSpecType() == EST_Unparsed) {
+ Diag(Loc, diag::err_exception_spec_not_parsed);
+ return nullptr;
+ }
+
if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
return FPT;
@@ -132,21 +164,14 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
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));
+void
+Sema::UpdateExceptionSpec(FunctionDecl *FD,
+ const FunctionProtoType::ExceptionSpecInfo &ESI) {
+ for (auto *Redecl : FD->redecls())
+ Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
// If we've fully resolved the exception specification, notify listeners.
- if (!isUnresolvedExceptionSpec(EPI.ExceptionSpecType))
+ if (!isUnresolvedExceptionSpec(ESI.Type))
if (auto *Listener = getASTMutationListener())
Listener->ResolvedExceptionSpec(FD);
}
@@ -227,32 +252,28 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
(Old->getLocation().isInvalid() ||
Context.getSourceManager().isInSystemHeader(Old->getLocation())) &&
Old->isExternC()) {
- FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
- EPI.ExceptionSpecType = EST_DynamicNone;
- QualType NewType = Context.getFunctionType(NewProto->getReturnType(),
- NewProto->getParamTypes(), EPI);
- New->setType(NewType);
+ New->setType(Context.getFunctionType(
+ NewProto->getReturnType(), NewProto->getParamTypes(),
+ NewProto->getExtProtoInfo().withExceptionSpec(EST_DynamicNone)));
return false;
}
const FunctionProtoType *OldProto =
Old->getType()->castAs<FunctionProtoType>();
- FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
- EPI.ExceptionSpecType = OldProto->getExceptionSpecType();
- if (EPI.ExceptionSpecType == EST_Dynamic) {
- EPI.NumExceptions = OldProto->getNumExceptions();
- EPI.Exceptions = OldProto->exception_begin();
- } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
+ FunctionProtoType::ExceptionSpecInfo ESI = OldProto->getExceptionSpecType();
+ if (ESI.Type == EST_Dynamic) {
+ ESI.Exceptions = OldProto->exceptions();
+ } else if (ESI.Type == EST_ComputedNoexcept) {
// FIXME: We can't just take the expression from the old prototype. It
// likely contains references to the old prototype's parameters.
}
// Update the type of the function with the appropriate exception
// specification.
- QualType NewType = Context.getFunctionType(NewProto->getReturnType(),
- NewProto->getParamTypes(), EPI);
- New->setType(NewType);
+ New->setType(Context.getFunctionType(
+ NewProto->getReturnType(), NewProto->getParamTypes(),
+ NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
// Warn about the lack of exception specification.
SmallString<128> ExceptionSpecString;
@@ -723,10 +744,11 @@ static bool CheckSpecForTypesEquivalent(Sema &S,
/// assignment and override compatibility check. We do not check the parameters
/// of parameter function pointers recursively, as no sane programmer would
/// even be able to write such a function type.
-bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
- const FunctionProtoType *Target, SourceLocation TargetLoc,
- const FunctionProtoType *Source, SourceLocation SourceLoc)
-{
+bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &NoteID,
+ const FunctionProtoType *Target,
+ SourceLocation TargetLoc,
+ const FunctionProtoType *Source,
+ SourceLocation SourceLoc) {
if (CheckSpecForTypesEquivalent(
*this, PDiag(diag::err_deep_exception_specs_differ) << 0, PDiag(),
Target->getReturnType(), TargetLoc, Source->getReturnType(),
@@ -747,23 +769,30 @@ bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
return false;
}
-bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)
-{
+bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) {
// First we check for applicability.
// Target type must be a function, function pointer or function reference.
const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType);
- if (!ToFunc)
+ if (!ToFunc || ToFunc->hasDependentExceptionSpec())
return false;
// SourceType must be a function or function pointer.
const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType());
- if (!FromFunc)
+ if (!FromFunc || FromFunc->hasDependentExceptionSpec())
return false;
// Now we've got the correct types on both sides, check their compatibility.
// This means that the source of the conversion can only throw a subset of
// the exceptions of the target, and any exception specs on arguments or
// return types must be equivalent.
+ //
+ // FIXME: If there is a nested dependent exception specification, we should
+ // not be checking it here. This is fine:
+ // template<typename T> void f() {
+ // void (*p)(void (*) throw(T));
+ // void (*q)(void (*) throw(int)) = p;
+ // }
+ // ... because it might be instantiated with T=int.
return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs),
PDiag(), ToFunc,
From->getSourceRange().getBegin(),
@@ -772,6 +801,11 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)
bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
const CXXMethodDecl *Old) {
+ // If the new exception specification hasn't been parsed yet, skip the check.
+ // We'll get called again once it's been parsed.
+ if (New->getType()->castAs<FunctionProtoType>()->getExceptionSpecType() ==
+ EST_Unparsed)
+ return false;
if (getLangOpts().CPlusPlus11 && isa<CXXDestructorDecl>(New)) {
// Don't check uninstantiated template destructors at all. We can only
// synthesize correct specs after the template is instantiated.
@@ -780,11 +814,18 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
if (New->getParent()->isBeingDefined()) {
// The destructor might be updated once the definition is finished. So
// remember it and check later.
- DelayedDestructorExceptionSpecChecks.push_back(std::make_pair(
- cast<CXXDestructorDecl>(New), cast<CXXDestructorDecl>(Old)));
+ DelayedExceptionSpecChecks.push_back(std::make_pair(New, Old));
return false;
}
}
+ // If the old exception specification hasn't been parsed yet, remember that
+ // we need to perform this check when we get to the end of the outermost
+ // lexically-surrounding class.
+ if (Old->getType()->castAs<FunctionProtoType>()->getExceptionSpecType() ==
+ EST_Unparsed) {
+ DelayedExceptionSpecChecks.push_back(std::make_pair(New, Old));
+ return false;
+ }
unsigned DiagID = diag::err_override_exception_spec;
if (getLangOpts().MicrosoftExt)
DiagID = diag::ext_override_exception_spec;
@@ -1051,6 +1092,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::CXXDependentScopeMemberExprClass:
case Expr::CXXUnresolvedConstructExprClass:
case Expr::DependentScopeDeclRefExprClass:
+ case Expr::CXXFoldExprClass:
return CT_Dependent;
case Expr::AsTypeExprClass:
@@ -1071,6 +1113,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::UnaryExprOrTypeTraitExprClass:
case Expr::UnresolvedLookupExprClass:
case Expr::UnresolvedMemberExprClass:
+ case Expr::TypoExprClass:
// FIXME: Can any of the above throw? If so, when?
return CT_Cannot;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 35dad82523c9..fba7a2d23ffd 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -42,6 +42,7 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaFixItUtils.h"
#include "clang/Sema/Template.h"
+#include "llvm/Support/ConvertUTF.h"
using namespace clang;
using namespace sema;
@@ -59,7 +60,7 @@ bool Sema::CanUseDecl(NamedDecl *D) {
// 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->getReturnType()->isUndeducedType() &&
+ if (getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() &&
DeduceReturnType(FD, SourceLocation(), /*Diagnose*/ false))
return false;
}
@@ -302,7 +303,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
// 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->getReturnType()->isUndeducedType() &&
+ if (getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() &&
DeduceReturnType(FD, Loc))
return true;
}
@@ -397,8 +398,8 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
if (sentinelExpr->isValueDependent()) return;
if (Context.isSentinelNullExpr(sentinelExpr)) return;
- // Pick a reasonable string to insert. Optimistically use 'nil' or
- // 'NULL' if those are actually defined in the context. Only use
+ // Pick a reasonable string to insert. Optimistically use 'nil', 'nullptr',
+ // or 'NULL' if those are actually defined in the context. Only use
// 'nil' for ObjC methods, where it's much more likely that the
// variadic arguments form a list of object pointers.
SourceLocation MissingNilLoc
@@ -407,6 +408,8 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
if (calleeType == CT_Method &&
PP.getIdentifierInfo("nil")->hasMacroDefinition())
NullValue = "nil";
+ else if (getLangOpts().CPlusPlus11)
+ NullValue = "nullptr";
else if (PP.getIdentifierInfo("NULL")->hasMacroDefinition())
NullValue = "NULL";
else
@@ -800,6 +803,9 @@ Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) {
if (Ty->isObjCObjectType())
return VAK_Invalid;
+ if (getLangOpts().MSVCCompat)
+ return VAK_MSVCUndefined;
+
// FIXME: In C++11, these cases are conditionally-supported, meaning we're
// permitted to reject them. We should consider doing so.
return VAK_Undefined;
@@ -829,6 +835,7 @@ void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) {
break;
case VAK_Undefined:
+ case VAK_MSVCUndefined:
DiagRuntimeBehavior(
E->getLocStart(), nullptr,
PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
@@ -933,68 +940,6 @@ static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr,
return false;
}
-/// \brief Takes two complex float types and converts them to the same type.
-/// Helper function of UsualArithmeticConversions()
-static QualType
-handleComplexFloatToComplexFloatConverstion(Sema &S, ExprResult &LHS,
- ExprResult &RHS, QualType LHSType,
- QualType RHSType,
- bool IsCompAssign) {
- int order = S.Context.getFloatingTypeOrder(LHSType, RHSType);
-
- if (order < 0) {
- // _Complex float -> _Complex double
- if (!IsCompAssign)
- LHS = S.ImpCastExprToType(LHS.get(), RHSType, CK_FloatingComplexCast);
- return RHSType;
- }
- if (order > 0)
- // _Complex float -> _Complex double
- RHS = S.ImpCastExprToType(RHS.get(), LHSType, CK_FloatingComplexCast);
- return LHSType;
-}
-
-/// \brief Converts otherExpr to complex float and promotes complexExpr if
-/// necessary. Helper function of UsualArithmeticConversions()
-static QualType handleOtherComplexFloatConversion(Sema &S,
- ExprResult &ComplexExpr,
- ExprResult &OtherExpr,
- QualType ComplexTy,
- QualType OtherTy,
- bool ConvertComplexExpr,
- bool ConvertOtherExpr) {
- int order = S.Context.getFloatingTypeOrder(ComplexTy, OtherTy);
-
- // If just the complexExpr is complex, the otherExpr needs to be converted,
- // and the complexExpr might need to be promoted.
- if (order > 0) { // complexExpr is wider
- // float -> _Complex double
- if (ConvertOtherExpr) {
- QualType fp = cast<ComplexType>(ComplexTy)->getElementType();
- OtherExpr = S.ImpCastExprToType(OtherExpr.get(), fp, CK_FloatingCast);
- OtherExpr = S.ImpCastExprToType(OtherExpr.get(), ComplexTy,
- CK_FloatingRealToComplex);
- }
- return ComplexTy;
- }
-
- // otherTy is at least as wide. Find its corresponding complex type.
- QualType result = (order == 0 ? ComplexTy :
- S.Context.getComplexType(OtherTy));
-
- // double -> _Complex double
- if (ConvertOtherExpr)
- OtherExpr = S.ImpCastExprToType(OtherExpr.get(), result,
- CK_FloatingRealToComplex);
-
- // _Complex float -> _Complex double
- if (ConvertComplexExpr && order < 0)
- ComplexExpr = S.ImpCastExprToType(ComplexExpr.get(), result,
- CK_FloatingComplexCast);
-
- return result;
-}
-
/// \brief Handle arithmetic conversion with complex types. Helper function of
/// UsualArithmeticConversions()
static QualType handleComplexFloatConversion(Sema &S, ExprResult &LHS,
@@ -1020,26 +965,35 @@ static QualType handleComplexFloatConversion(Sema &S, ExprResult &LHS,
// when combining a "long double" with a "double _Complex", the
// "double _Complex" is promoted to "long double _Complex".
- bool LHSComplexFloat = LHSType->isComplexType();
- bool RHSComplexFloat = RHSType->isComplexType();
-
- // If both are complex, just cast to the more precise type.
- if (LHSComplexFloat && RHSComplexFloat)
- return handleComplexFloatToComplexFloatConverstion(S, LHS, RHS,
- LHSType, RHSType,
- IsCompAssign);
-
- // If only one operand is complex, promote it if necessary and convert the
- // other operand to complex.
- if (LHSComplexFloat)
- return handleOtherComplexFloatConversion(
- S, LHS, RHS, LHSType, RHSType, /*convertComplexExpr*/!IsCompAssign,
- /*convertOtherExpr*/ true);
-
- assert(RHSComplexFloat);
- return handleOtherComplexFloatConversion(
- S, RHS, LHS, RHSType, LHSType, /*convertComplexExpr*/true,
- /*convertOtherExpr*/ !IsCompAssign);
+ // Compute the rank of the two types, regardless of whether they are complex.
+ int Order = S.Context.getFloatingTypeOrder(LHSType, RHSType);
+
+ auto *LHSComplexType = dyn_cast<ComplexType>(LHSType);
+ auto *RHSComplexType = dyn_cast<ComplexType>(RHSType);
+ QualType LHSElementType =
+ LHSComplexType ? LHSComplexType->getElementType() : LHSType;
+ QualType RHSElementType =
+ RHSComplexType ? RHSComplexType->getElementType() : RHSType;
+
+ QualType ResultType = S.Context.getComplexType(LHSElementType);
+ if (Order < 0) {
+ // Promote the precision of the LHS if not an assignment.
+ ResultType = S.Context.getComplexType(RHSElementType);
+ if (!IsCompAssign) {
+ if (LHSComplexType)
+ LHS =
+ S.ImpCastExprToType(LHS.get(), ResultType, CK_FloatingComplexCast);
+ else
+ LHS = S.ImpCastExprToType(LHS.get(), RHSElementType, CK_FloatingCast);
+ }
+ } else if (Order > 0) {
+ // Promote the precision of the RHS.
+ if (RHSComplexType)
+ RHS = S.ImpCastExprToType(RHS.get(), ResultType, CK_FloatingComplexCast);
+ else
+ RHS = S.ImpCastExprToType(RHS.get(), LHSElementType, CK_FloatingCast);
+ }
+ return ResultType;
}
/// \brief Hande arithmetic conversion from integer to float. Helper function
@@ -1336,6 +1290,13 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
ControllingExpr = result.get();
}
+ // The controlling expression is an unevaluated operand, so side effects are
+ // likely unintended.
+ if (ActiveTemplateInstantiations.empty() &&
+ ControllingExpr->HasSideEffects(Context, false))
+ Diag(ControllingExpr->getExprLoc(),
+ diag::warn_side_effects_unevaluated_context);
+
bool TypeErrorFound = false,
IsResultDependent = ControllingExpr->isTypeDependent(),
ContainsUnexpandedParameterPack
@@ -1636,40 +1597,37 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
if (getLangOpts().CUDA)
if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext))
if (const FunctionDecl *Callee = dyn_cast<FunctionDecl>(D)) {
- CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller),
- CalleeTarget = IdentifyCUDATarget(Callee);
- if (CheckCUDATarget(CallerTarget, CalleeTarget)) {
+ if (CheckCUDATarget(Caller, Callee)) {
Diag(NameInfo.getLoc(), diag::err_ref_bad_target)
- << CalleeTarget << D->getIdentifier() << CallerTarget;
+ << IdentifyCUDATarget(Callee) << D->getIdentifier()
+ << IdentifyCUDATarget(Caller);
Diag(D->getLocation(), diag::note_previous_decl)
<< D->getIdentifier();
return ExprError();
}
}
- bool refersToEnclosingScope =
- (CurContext != D->getDeclContext() &&
- D->getDeclContext()->isFunctionOrMethod()) ||
- (isa<VarDecl>(D) &&
- cast<VarDecl>(D)->isInitCapture());
+ bool RefersToCapturedVariable =
+ isa<VarDecl>(D) &&
+ NeedToCaptureVariable(cast<VarDecl>(D), NameInfo.getLoc());
DeclRefExpr *E;
if (isa<VarTemplateSpecializationDecl>(D)) {
VarTemplateSpecializationDecl *VarSpec =
cast<VarTemplateSpecializationDecl>(D);
- E = DeclRefExpr::Create(
- Context,
- SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
- VarSpec->getTemplateKeywordLoc(), D, refersToEnclosingScope,
- NameInfo.getLoc(), Ty, VK, FoundD, TemplateArgs);
+ E = DeclRefExpr::Create(Context, SS ? SS->getWithLocInContext(Context)
+ : NestedNameSpecifierLoc(),
+ VarSpec->getTemplateKeywordLoc(), D,
+ RefersToCapturedVariable, NameInfo.getLoc(), Ty, VK,
+ FoundD, TemplateArgs);
} else {
assert(!TemplateArgs && "No template arguments for non-variable"
" template specialization references");
- E = DeclRefExpr::Create(
- Context,
- SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
- SourceLocation(), D, refersToEnclosingScope, NameInfo, Ty, VK, FoundD);
+ E = DeclRefExpr::Create(Context, SS ? SS->getWithLocInContext(Context)
+ : NestedNameSpecifierLoc(),
+ SourceLocation(), D, RefersToCapturedVariable,
+ NameInfo, Ty, VK, FoundD);
}
MarkDeclRefReferenced(E);
@@ -1719,13 +1677,48 @@ Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id,
}
}
+static void emitEmptyLookupTypoDiagnostic(
+ const TypoCorrection &TC, Sema &SemaRef, const CXXScopeSpec &SS,
+ DeclarationName Typo, SourceLocation TypoLoc, ArrayRef<Expr *> Args,
+ unsigned DiagnosticID, unsigned DiagnosticSuggestID) {
+ DeclContext *Ctx =
+ SS.isEmpty() ? nullptr : SemaRef.computeDeclContext(SS, false);
+ if (!TC) {
+ // Emit a special diagnostic for failed member lookups.
+ // FIXME: computing the declaration context might fail here (?)
+ if (Ctx)
+ SemaRef.Diag(TypoLoc, diag::err_no_member) << Typo << Ctx
+ << SS.getRange();
+ else
+ SemaRef.Diag(TypoLoc, DiagnosticID) << Typo;
+ return;
+ }
+
+ std::string CorrectedStr = TC.getAsString(SemaRef.getLangOpts());
+ bool DroppedSpecifier =
+ TC.WillReplaceSpecifier() && Typo.getAsString() == CorrectedStr;
+ unsigned NoteID =
+ (TC.getCorrectionDecl() && isa<ImplicitParamDecl>(TC.getCorrectionDecl()))
+ ? diag::note_implicit_param_decl
+ : diag::note_previous_decl;
+ if (!Ctx)
+ SemaRef.diagnoseTypo(TC, SemaRef.PDiag(DiagnosticSuggestID) << Typo,
+ SemaRef.PDiag(NoteID));
+ else
+ SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest)
+ << Typo << Ctx << DroppedSpecifier
+ << SS.getRange(),
+ SemaRef.PDiag(NoteID));
+}
+
/// Diagnose an empty lookup.
///
/// \return false if new lookup candidates were found
-bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
- CorrectionCandidateCallback &CCC,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- ArrayRef<Expr *> Args) {
+bool
+Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+ std::unique_ptr<CorrectionCandidateCallback> CCC,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ ArrayRef<Expr *> Args, TypoExpr **Out) {
DeclarationName Name = R.getLookupName();
unsigned diagnostic = diag::err_undeclared_var_use;
@@ -1842,8 +1835,22 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// We didn't find anything, so try to correct for a typo.
TypoCorrection Corrected;
- if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(),
- S, &SS, CCC, CTK_ErrorRecovery))) {
+ if (S && Out) {
+ SourceLocation TypoLoc = R.getNameLoc();
+ assert(!ExplicitTemplateArgs &&
+ "Diagnosing an empty lookup with explicit template args!");
+ *Out = CorrectTypoDelayed(
+ R.getLookupNameInfo(), R.getLookupKind(), S, &SS, std::move(CCC),
+ [=](const TypoCorrection &TC) {
+ emitEmptyLookupTypoDiagnostic(TC, *this, SS, Name, TypoLoc, Args,
+ diagnostic, diagnostic_suggest);
+ },
+ nullptr, CTK_ErrorRecovery);
+ if (*Out)
+ return true;
+ } else if (S && (Corrected =
+ CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S,
+ &SS, std::move(CCC), CTK_ErrorRecovery))) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
bool DroppedSpecifier =
Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr;
@@ -1990,14 +1997,12 @@ recoverFromMSUnqualifiedLookup(Sema &S, ASTContext &Context,
TemplateArgs);
}
-ExprResult Sema::ActOnIdExpression(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- UnqualifiedId &Id,
- bool HasTrailingLParen,
- bool IsAddressOfOperand,
- CorrectionCandidateCallback *CCC,
- bool IsInlineAsmIdentifier) {
+ExprResult
+Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc, UnqualifiedId &Id,
+ bool HasTrailingLParen, bool IsAddressOfOperand,
+ std::unique_ptr<CorrectionCandidateCallback> CCC,
+ bool IsInlineAsmIdentifier, Token *KeywordReplacement) {
assert(!(IsAddressOfOperand && HasTrailingLParen) &&
"cannot be direct & operand and have a trailing lparen");
if (SS.isInvalid())
@@ -2109,12 +2114,43 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
// If this name wasn't predeclared and if this is not a function
// call, diagnose the problem.
- CorrectionCandidateCallback DefaultValidator;
- DefaultValidator.IsAddressOfOperand = IsAddressOfOperand;
+ TypoExpr *TE = nullptr;
+ auto DefaultValidator = llvm::make_unique<CorrectionCandidateCallback>(
+ II, SS.isValid() ? SS.getScopeRep() : nullptr);
+ DefaultValidator->IsAddressOfOperand = IsAddressOfOperand;
assert((!CCC || CCC->IsAddressOfOperand == IsAddressOfOperand) &&
"Typo correction callback misconfigured");
- if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator))
- return ExprError();
+ if (CCC) {
+ // Make sure the callback knows what the typo being diagnosed is.
+ CCC->setTypoName(II);
+ if (SS.isValid())
+ CCC->setTypoNNS(SS.getScopeRep());
+ }
+ if (DiagnoseEmptyLookup(S, SS, R,
+ CCC ? std::move(CCC) : std::move(DefaultValidator),
+ nullptr, None, &TE)) {
+ if (TE && KeywordReplacement) {
+ auto &State = getTypoExprState(TE);
+ auto BestTC = State.Consumer->getNextCorrection();
+ if (BestTC.isKeyword()) {
+ auto *II = BestTC.getCorrectionAsIdentifierInfo();
+ if (State.DiagHandler)
+ State.DiagHandler(BestTC);
+ KeywordReplacement->startToken();
+ KeywordReplacement->setKind(II->getTokenID());
+ KeywordReplacement->setIdentifierInfo(II);
+ KeywordReplacement->setLocation(BestTC.getCorrectionRange().getBegin());
+ // Clean up the state associated with the TypoExpr, since it has
+ // now been diagnosed (without a call to CorrectDelayedTyposInExpr).
+ clearDelayedTypo(TE);
+ // Signal that a correction to a keyword was performed by returning a
+ // valid-but-null ExprResult.
+ return (Expr*)nullptr;
+ }
+ State.Consumer->resetCorrectionStream();
+ }
+ return TE ? TE : ExprError();
+ }
assert(!R.empty() &&
"DiagnoseEmptyLookup returned false but added no results");
@@ -2364,10 +2400,9 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
!IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV))
Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName();
- ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(),
- Loc, IV->getLocation(),
- SelfExpr.get(),
- true, true);
+ ObjCIvarRefExpr *Result = new (Context)
+ ObjCIvarRefExpr(IV, IV->getType(), Loc, IV->getLocation(),
+ SelfExpr.get(), true, true);
if (getLangOpts().ObjCAutoRefCount) {
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
@@ -2660,15 +2695,15 @@ static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) {
return false;
}
-ExprResult
-Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
- LookupResult &R,
- bool NeedsADL) {
+ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ LookupResult &R, bool NeedsADL,
+ bool AcceptInvalidDecl) {
// If this is a single, fully-resolved result and we don't need ADL,
// just build an ordinary singleton decl ref.
if (!NeedsADL && R.isSingleResult() && !R.getAsSingle<FunctionTemplateDecl>())
return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(),
- R.getRepresentativeDecl());
+ R.getRepresentativeDecl(), nullptr,
+ AcceptInvalidDecl);
// We only need to check the declaration if there's exactly one
// result, because in the overloaded case the results can only be
@@ -2695,7 +2730,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
/// \brief Complete semantic analysis for a reference to the given declaration.
ExprResult Sema::BuildDeclarationNameExpr(
const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
- NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs) {
+ NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs,
+ bool AcceptInvalidDecl) {
assert(D && "Cannot refer to a NULL declaration");
assert(!isa<FunctionTemplateDecl>(D) &&
"Cannot refer unambiguously to a function template");
@@ -2730,7 +2766,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
return ExprError();
// Only create DeclRefExpr's for valid Decl's.
- if (VD->isInvalidDecl())
+ if (VD->isInvalidDecl() && !AcceptInvalidDecl)
return ExprError();
// Handle members of anonymous structs and unions. If we got here,
@@ -2902,6 +2938,17 @@ ExprResult Sema::BuildDeclarationNameExpr(
}
}
+static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
+ SmallString<32> &Target) {
+ Target.resize(CharByteWidth * (Source.size() + 1));
+ char *ResultPtr = &Target[0];
+ const UTF8 *ErrorPtr;
+ bool success = ConvertUTF8toWide(CharByteWidth, Source, ResultPtr, ErrorPtr);
+ (void)success;
+ assert(success);
+ Target.resize(ResultPtr - &Target[0]);
+}
+
ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
PredefinedExpr::IdentType IT) {
// Pick the current block, lambda, captured statement or function.
@@ -2921,22 +2968,35 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
}
QualType ResTy;
+ StringLiteral *SL = nullptr;
if (cast<DeclContext>(currentDecl)->isDependentContext())
ResTy = Context.DependentTy;
else {
// Pre-defined identifiers are of type char[x], where x is the length of
// the string.
- unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
+ auto Str = PredefinedExpr::ComputeName(IT, currentDecl);
+ unsigned Length = Str.length();
llvm::APInt LengthI(32, Length + 1);
- if (IT == PredefinedExpr::LFunction)
+ if (IT == PredefinedExpr::LFunction) {
ResTy = Context.WideCharTy.withConst();
- else
+ SmallString<32> RawChars;
+ ConvertUTF8ToWideString(Context.getTypeSizeInChars(ResTy).getQuantity(),
+ Str, RawChars);
+ ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal,
+ /*IndexTypeQuals*/ 0);
+ SL = StringLiteral::Create(Context, RawChars, StringLiteral::Wide,
+ /*Pascal*/ false, ResTy, Loc);
+ } else {
ResTy = Context.CharTy.withConst();
- ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
+ ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal,
+ /*IndexTypeQuals*/ 0);
+ SL = StringLiteral::Create(Context, Str, StringLiteral::Ascii,
+ /*Pascal*/ false, ResTy, Loc);
+ }
}
- return new (Context) PredefinedExpr(Loc, ResTy, IT);
+ return new (Context) PredefinedExpr(Loc, ResTy, IT, SL);
}
ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
@@ -3046,6 +3106,34 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal,
return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc);
}
+bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc) {
+ assert(E && "Invalid expression");
+
+ if (E->isValueDependent())
+ return false;
+
+ QualType QT = E->getType();
+ if (!QT->isIntegerType() || QT->isBooleanType() || QT->isCharType()) {
+ Diag(E->getExprLoc(), diag::err_pragma_loop_invalid_argument_type) << QT;
+ return true;
+ }
+
+ llvm::APSInt ValueAPS;
+ ExprResult R = VerifyIntegerConstantExpression(E, &ValueAPS);
+
+ if (R.isInvalid())
+ return true;
+
+ bool ValueIsPositive = ValueAPS.isStrictlyPositive();
+ if (!ValueIsPositive || ValueAPS.getActiveBits() > 31) {
+ Diag(E->getExprLoc(), diag::err_pragma_loop_invalid_argument_value)
+ << ValueAPS.toString(10) << ValueIsPositive;
+ return true;
+ }
+
+ return false;
+}
+
ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// Fast path for a single digit (which is quite common). A single digit
// cannot have a trigraph, escaped newline, radix prefix, or suffix.
@@ -3117,7 +3205,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
} else {
llvm::APInt ResultVal(Context.getTargetInfo().getLongLongWidth(), 0);
if (Literal.GetIntegerValue(ResultVal))
- Diag(Tok.getLocation(), diag::err_integer_too_large);
+ Diag(Tok.getLocation(), diag::err_integer_literal_too_large)
+ << /* Unsigned */ 1;
Lit = IntegerLiteral::Create(Context, ResultVal, CookedTy,
Tok.getLocation());
}
@@ -3210,7 +3299,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
if (Literal.GetIntegerValue(ResultVal)) {
// If this value didn't fit into uintmax_t, error and force to ull.
- Diag(Tok.getLocation(), diag::err_integer_too_large);
+ Diag(Tok.getLocation(), diag::err_integer_literal_too_large)
+ << /* Unsigned */ 1;
Ty = Context.UnsignedLongLongTy;
assert(Context.getTypeSize(Ty) == ResultVal.getBitWidth() &&
"long long is not intmax_t?");
@@ -3290,7 +3380,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// 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::ext_integer_too_large_for_signed);
+ Diag(Tok.getLocation(), diag::ext_integer_literal_too_large_for_signed);
Ty = Context.UnsignedLongLongTy;
Width = Context.getTargetInfo().getLongLongWidth();
}
@@ -3442,6 +3532,12 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
return true;
}
+ // The operand for sizeof and alignof is in an unevaluated expression context,
+ // so side effects could result in unintended consequences.
+ if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf) &&
+ ActiveTemplateInstantiations.empty() && E->HasSideEffects(Context, false))
+ Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
+
if (CheckObjCTraitOperandConstraints(*this, ExprTy, E->getExprLoc(),
E->getSourceRange(), ExprKind))
return true;
@@ -4083,11 +4179,12 @@ static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn,
MemberExpr *ME = dyn_cast<MemberExpr>(Fn);
DeclarationName FuncName = FDecl->getDeclName();
SourceLocation NameLoc = ME ? ME->getMemberLoc() : Fn->getLocStart();
- FunctionCallCCC CCC(S, FuncName.getAsIdentifierInfo(), Args.size(), ME);
if (TypoCorrection Corrected = S.CorrectTypo(
DeclarationNameInfo(FuncName, NameLoc), Sema::LookupOrdinaryName,
- S.getScopeForContext(S.CurContext), nullptr, CCC,
+ S.getScopeForContext(S.CurContext), nullptr,
+ llvm::make_unique<FunctionCallCCC>(S, FuncName.getAsIdentifierInfo(),
+ Args.size(), ME),
Sema::CTK_ErrorRecovery)) {
if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
if (Corrected.isOverloaded()) {
@@ -4454,6 +4551,8 @@ static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) {
ExprResult result = S.CheckPlaceholderExpr(args[i]);
if (result.isInvalid()) hasInvalid = true;
else args[i] = result.get();
+ } else if (hasInvalid) {
+ (void)S.CorrectDelayedTyposInExpr(args[i]);
}
}
return hasInvalid;
@@ -4587,23 +4686,6 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
ExecConfig, IsExecConfig);
}
-ExprResult
-Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
- MultiExprArg ExecConfig, SourceLocation GGGLoc) {
- FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl();
- if (!ConfigDecl)
- return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)
- << "cudaConfigureCall");
- QualType ConfigQTy = ConfigDecl->getType();
-
- DeclRefExpr *ConfigDR = new (Context) DeclRefExpr(
- ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc);
- MarkFunctionReferenced(LLLLoc, ConfigDecl);
-
- return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr,
- /*IsExecConfig=*/true);
-}
-
/// ActOnAsTypeExpr - create a new asType (bitcast) from the arguments.
///
/// __builtin_astype( value, dst type )
@@ -4680,8 +4762,12 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
VK_RValue, RParenLoc);
// Bail out early if calling a builtin with custom typechecking.
- if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
- return CheckBuiltinFunctionCall(BuiltinID, TheCall);
+ if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) {
+ ExprResult Res = CorrectDelayedTyposInExpr(TheCall);
+ if (!Res.isUsable() || !isa<CallExpr>(Res.get()))
+ return Res;
+ return CheckBuiltinFunctionCall(FDecl, BuiltinID, cast<CallExpr>(Res.get()));
+ }
retry:
const FunctionType *FuncT;
@@ -4809,7 +4895,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
return ExprError();
if (BuiltinID)
- return CheckBuiltinFunctionCall(BuiltinID, TheCall);
+ return CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall);
} else if (NDecl) {
if (CheckPointerCall(NDecl, TheCall, Proto))
return ExprError();
@@ -5227,6 +5313,12 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
if (getLangOpts().CPlusPlus) {
// Check that there are no default arguments (C++ only).
CheckExtraCXXDefaultArguments(D);
+ } else {
+ // Make sure any TypoExprs have been dealt with.
+ ExprResult Res = CorrectDelayedTyposInExpr(CastExpr);
+ if (!Res.isUsable())
+ return ExprError();
+ CastExpr = Res.get();
}
checkUnusedDeclAttributes(D);
@@ -5693,6 +5785,15 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
ExprObjectKind &OK,
SourceLocation QuestionLoc) {
+ if (!getLangOpts().CPlusPlus) {
+ // C cannot handle TypoExpr nodes on either side of a binop because it
+ // doesn't handle dependent types properly, so make sure any TypoExprs have
+ // been dealt with before checking the operands.
+ ExprResult CondResult = CorrectDelayedTyposInExpr(Cond);
+ if (!CondResult.isUsable()) return QualType();
+ Cond = CondResult;
+ }
+
ExprResult LHSResult = CheckPlaceholderExpr(LHS.get());
if (!LHSResult.isUsable()) return QualType();
LHS = LHSResult;
@@ -5720,7 +5821,7 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
RHS.get()->getType()->isVectorType())
return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false);
- UsualArithmeticConversions(LHS, RHS);
+ QualType ResTy = UsualArithmeticConversions(LHS, RHS);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
@@ -5737,8 +5838,12 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// If both operands have arithmetic type, do the usual arithmetic conversions
// to find a common type: C99 6.5.15p3,5.
- if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType())
- return LHS.get()->getType();
+ if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
+ LHS = ImpCastExprToType(LHS.get(), ResTy, PrepareScalarCast(LHS, ResTy));
+ RHS = ImpCastExprToType(RHS.get(), ResTy, PrepareScalarCast(RHS, ResTy));
+
+ return ResTy;
+ }
// If both operands are the same structure or union type, the result is that
// type.
@@ -6161,7 +6266,7 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) {
if (!lhq.compatiblyIncludes(rhq)) {
// Treat address-space mismatches as fatal. TODO: address subspaces
- if (lhq.getAddressSpace() != rhq.getAddressSpace())
+ if (!lhq.isAddressSpaceSupersetOf(rhq))
ConvTy = Sema::IncompatiblePointerDiscardsQualifiers;
// It's okay to add or remove GC or lifetime qualifiers when converting to
@@ -6446,7 +6551,9 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
if (const PointerType *LHSPointer = dyn_cast<PointerType>(LHSType)) {
// U* -> T*
if (isa<PointerType>(RHSType)) {
- Kind = CK_BitCast;
+ unsigned AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace();
+ unsigned AddrSpaceR = RHSType->getPointeeType().getAddressSpace();
+ Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast;
return checkPointerTypesForAssignment(*this, LHSType, RHSType);
}
@@ -6754,6 +6861,15 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
return Incompatible;
}
+ Expr *PRE = RHS.get()->IgnoreParenCasts();
+ if (ObjCProtocolExpr *OPE = dyn_cast<ObjCProtocolExpr>(PRE)) {
+ ObjCProtocolDecl *PDecl = OPE->getProtocol();
+ if (PDecl && !PDecl->hasDefinition()) {
+ Diag(PRE->getExprLoc(), diag::warn_atprotocol_protocol) << PDecl->getName();
+ Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl;
+ }
+ }
+
CastKind Kind = CK_Invalid;
Sema::AssignConvertType result =
CheckAssignmentConstraints(LHSType, RHS, Kind);
@@ -7120,6 +7236,19 @@ static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc,
if (isLHSPointer) LHSPointeeTy = LHSExpr->getType()->getPointeeType();
if (isRHSPointer) RHSPointeeTy = RHSExpr->getType()->getPointeeType();
+ // if both are pointers check if operation is valid wrt address spaces
+ if (isLHSPointer && isRHSPointer) {
+ const PointerType *lhsPtr = LHSExpr->getType()->getAs<PointerType>();
+ const PointerType *rhsPtr = RHSExpr->getType()->getAs<PointerType>();
+ if (!lhsPtr->isAddressSpaceOverlapping(*rhsPtr)) {
+ S.Diag(Loc,
+ diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
+ << LHSExpr->getType() << RHSExpr->getType() << 1 /*arithmetic op*/
+ << LHSExpr->getSourceRange() << RHSExpr->getSourceRange();
+ return false;
+ }
+ }
+
// Check for arithmetic on pointers to incomplete types.
bool isLHSVoidPtr = isLHSPointer && LHSPointeeTy->isVoidType();
bool isRHSVoidPtr = isRHSPointer && RHSPointeeTy->isVoidType();
@@ -7163,7 +7292,7 @@ static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc,
bool IsStringPlusInt = StrExpr &&
IndexExpr->getType()->isIntegralOrUnscopedEnumerationType();
- if (!IsStringPlusInt)
+ if (!IsStringPlusInt || IndexExpr->isValueDependent())
return;
llvm::APSInt index;
@@ -7193,13 +7322,13 @@ static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc,
/// \brief Emit a warning when adding a char literal to a string.
static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
Expr *LHSExpr, Expr *RHSExpr) {
- const DeclRefExpr *StringRefExpr =
- dyn_cast<DeclRefExpr>(LHSExpr->IgnoreImpCasts());
+ const Expr *StringRefExpr = LHSExpr;
const CharacterLiteral *CharExpr =
dyn_cast<CharacterLiteral>(RHSExpr->IgnoreImpCasts());
- if (!StringRefExpr) {
- StringRefExpr = dyn_cast<DeclRefExpr>(RHSExpr->IgnoreImpCasts());
+
+ if (!CharExpr) {
CharExpr = dyn_cast<CharacterLiteral>(LHSExpr->IgnoreImpCasts());
+ StringRefExpr = RHSExpr;
}
if (!CharExpr || !StringRefExpr)
@@ -7417,7 +7546,7 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
}
static bool isScopedEnumerationType(QualType T) {
- if (const EnumType *ET = dyn_cast<EnumType>(T))
+ if (const EnumType *ET = T->getAs<EnumType>())
return ET->getDecl()->isScoped();
return false;
}
@@ -8048,6 +8177,13 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, /*isError*/false);
}
if (LCanPointeeTy != RCanPointeeTy) {
+ const PointerType *lhsPtr = LHSType->getAs<PointerType>();
+ if (!lhsPtr->isAddressSpaceOverlapping(*RHSType->getAs<PointerType>())) {
+ Diag(Loc,
+ diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
+ << LHSType << RHSType << 0 /* comparison */
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ }
unsigned AddrSpaceL = LCanPointeeTy.getAddressSpace();
unsigned AddrSpaceR = RCanPointeeTy.getAddressSpace();
CastKind Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion
@@ -8462,7 +8598,7 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
// Must be a reference to a declaration from an enclosing scope.
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
if (!DRE) return NCCK_None;
- if (!DRE->refersToEnclosingLocal()) return NCCK_None;
+ if (!DRE->refersToEnclosingVariableOrCapture()) return NCCK_None;
// The declaration must be a variable which is not declared 'const'.
VarDecl *var = dyn_cast<VarDecl>(DRE->getDecl());
@@ -8494,19 +8630,19 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
if (IsLV == Expr::MLV_Valid)
return false;
- unsigned Diag = 0;
+ unsigned DiagID = 0;
bool NeedType = false;
switch (IsLV) { // C99 6.5.16p2
case Expr::MLV_ConstQualified:
- Diag = diag::err_typecheck_assign_const;
+ DiagID = diag::err_typecheck_assign_const;
// Use a specialized diagnostic when we're assigning to an object
// from an enclosing function or block.
if (NonConstCaptureKind NCCK = isReferenceToNonConstCapture(S, E)) {
if (NCCK == NCCK_Block)
- Diag = diag::err_block_decl_ref_not_modifiable_lvalue;
+ DiagID = diag::err_block_decl_ref_not_modifiable_lvalue;
else
- Diag = diag::err_lambda_decl_ref_not_modifiable_lvalue;
+ DiagID = diag::err_lambda_decl_ref_not_modifiable_lvalue;
break;
}
@@ -8526,18 +8662,18 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
// - self
ObjCMethodDecl *method = S.getCurMethodDecl();
if (method && var == method->getSelfDecl())
- Diag = method->isClassMethod()
+ DiagID = method->isClassMethod()
? diag::err_typecheck_arc_assign_self_class_method
: diag::err_typecheck_arc_assign_self;
// - fast enumeration variables
else
- Diag = diag::err_typecheck_arr_assign_enumeration;
+ DiagID = diag::err_typecheck_arr_assign_enumeration;
SourceRange Assign;
if (Loc != OrigLoc)
Assign = SourceRange(OrigLoc, OrigLoc);
- S.Diag(Loc, Diag) << E->getSourceRange() << Assign;
+ S.Diag(Loc, DiagID) << E->getSourceRange() << Assign;
// We need to preserve the AST regardless, so migration tool
// can do its job.
return false;
@@ -8548,37 +8684,37 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
break;
case Expr::MLV_ArrayType:
case Expr::MLV_ArrayTemporary:
- Diag = diag::err_typecheck_array_not_modifiable_lvalue;
+ DiagID = diag::err_typecheck_array_not_modifiable_lvalue;
NeedType = true;
break;
case Expr::MLV_NotObjectType:
- Diag = diag::err_typecheck_non_object_not_modifiable_lvalue;
+ DiagID = diag::err_typecheck_non_object_not_modifiable_lvalue;
NeedType = true;
break;
case Expr::MLV_LValueCast:
- Diag = diag::err_typecheck_lvalue_casts_not_supported;
+ DiagID = diag::err_typecheck_lvalue_casts_not_supported;
break;
case Expr::MLV_Valid:
llvm_unreachable("did not take early return for MLV_Valid");
case Expr::MLV_InvalidExpression:
case Expr::MLV_MemberFunction:
case Expr::MLV_ClassTemporary:
- Diag = diag::err_typecheck_expression_not_modifiable_lvalue;
+ DiagID = diag::err_typecheck_expression_not_modifiable_lvalue;
break;
case Expr::MLV_IncompleteType:
case Expr::MLV_IncompleteVoidType:
return S.RequireCompleteType(Loc, E->getType(),
diag::err_typecheck_incomplete_type_not_modifiable_lvalue, E);
case Expr::MLV_DuplicateVectorComponents:
- Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
+ DiagID = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
break;
case Expr::MLV_NoSetterProperty:
llvm_unreachable("readonly properties should be processed differently");
case Expr::MLV_InvalidMessageExpression:
- Diag = diag::error_readonly_message_assignment;
+ DiagID = diag::error_readonly_message_assignment;
break;
case Expr::MLV_SubObjCPropertySetting:
- Diag = diag::error_no_subobject_property_setting;
+ DiagID = diag::error_no_subobject_property_setting;
break;
}
@@ -8586,9 +8722,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
if (Loc != OrigLoc)
Assign = SourceRange(OrigLoc, OrigLoc);
if (NeedType)
- S.Diag(Loc, Diag) << E->getType() << E->getSourceRange() << Assign;
+ S.Diag(Loc, DiagID) << E->getType() << E->getSourceRange() << Assign;
else
- S.Diag(Loc, Diag) << E->getSourceRange() << Assign;
+ S.Diag(Loc, DiagID) << E->getSourceRange() << Assign;
return true;
}
@@ -8754,6 +8890,7 @@ static QualType CheckCommaOperands(Sema &S, ExprResult &LHS, ExprResult &RHS,
/// doesn't need to call UsualUnaryConversions or UsualArithmeticConversions.
static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
ExprValueKind &VK,
+ ExprObjectKind &OK,
SourceLocation OpLoc,
bool IsInc, bool IsPrefix) {
if (Op->isTypeDependent())
@@ -8799,7 +8936,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
} else if (ResType->isPlaceholderType()) {
ExprResult PR = S.CheckPlaceholderExpr(Op);
if (PR.isInvalid()) return QualType();
- return CheckIncrementDecrementOperand(S, PR.get(), VK, OpLoc,
+ return CheckIncrementDecrementOperand(S, PR.get(), VK, OK, OpLoc,
IsInc, IsPrefix);
} else if (S.getLangOpts().AltiVec && ResType->isVectorType()) {
// OK! ( C/C++ Language Extensions for CBEA(Version 2.6) 10.3 )
@@ -8820,6 +8957,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
// operand.
if (IsPrefix && S.getLangOpts().CPlusPlus) {
VK = VK_LValue;
+ OK = Op->getObjectKind();
return ResType;
} else {
VK = VK_RValue;
@@ -9104,6 +9242,24 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
return Context.getPointerType(op->getType());
}
+static void RecordModifiableNonNullParam(Sema &S, const Expr *Exp) {
+ const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp);
+ if (!DRE)
+ return;
+ const Decl *D = DRE->getDecl();
+ if (!D)
+ return;
+ const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D);
+ if (!Param)
+ return;
+ if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(Param->getDeclContext()))
+ if (!FD->hasAttr<NonNullAttr>() && !Param->hasAttr<NonNullAttr>())
+ return;
+ if (FunctionScopeInfo *FD = S.getCurFunction())
+ if (!FD->ModifiedNonNullParams.count(Param))
+ FD->ModifiedNonNullParams.insert(Param);
+}
+
/// CheckIndirectionOperand - Type check unary indirection (prefix '*').
static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
SourceLocation OpLoc) {
@@ -9164,8 +9320,7 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
return Result;
}
-static inline BinaryOperatorKind ConvertTokenKindToBinaryOpcode(
- tok::TokenKind Kind) {
+BinaryOperatorKind Sema::ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind) {
BinaryOperatorKind Opc;
switch (Kind) {
default: llvm_unreachable("Unknown binop!");
@@ -9334,6 +9489,16 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
+ if (!getLangOpts().CPlusPlus) {
+ // C cannot handle TypoExpr nodes on either side of a binop because it
+ // doesn't handle dependent types properly, so make sure any TypoExprs have
+ // been dealt with before checking the operands.
+ LHS = CorrectDelayedTyposInExpr(LHSExpr);
+ RHS = CorrectDelayedTyposInExpr(RHSExpr);
+ if (!LHS.isUsable() || !RHS.isUsable())
+ return ExprError();
+ }
+
switch (Opc) {
case BO_Assign:
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType());
@@ -9342,8 +9507,11 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
VK = LHS.get()->getValueKind();
OK = LHS.get()->getObjectKind();
}
- if (!ResultTy.isNull())
+ if (!ResultTy.isNull()) {
DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc);
+ DiagnoseSelfMove(LHS.get(), RHS.get(), OpLoc);
+ }
+ RecordModifiableNonNullParam(*this, LHS.get());
break;
case BO_PtrMemD:
case BO_PtrMemI:
@@ -9503,7 +9671,7 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
StringRef OpStr = isLeftComp ? LHSBO->getOpcodeStr() : RHSBO->getOpcodeStr();
SourceRange ParensRange = isLeftComp ?
SourceRange(LHSBO->getRHS()->getLocStart(), RHSExpr->getLocEnd())
- : SourceRange(LHSExpr->getLocStart(), RHSBO->getLHS()->getLocStart());
+ : SourceRange(LHSExpr->getLocStart(), RHSBO->getLHS()->getLocEnd());
Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel)
<< DiagRange << BinaryOperator::getOpcodeStr(Opc) << OpStr;
@@ -9709,7 +9877,7 @@ static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
UnresolvedSet<16> Functions;
OverloadedOperatorKind OverOp
= BinaryOperator::getOverloadedOperator(Opc);
- if (Sc && OverOp != OO_None)
+ if (Sc && OverOp != OO_None && OverOp != OO_Equal)
S.LookupOverloadedOperatorName(OverOp, Sc, LHS->getType(),
RHS->getType(), Functions);
@@ -9808,7 +9976,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
case UO_PreDec:
case UO_PostInc:
case UO_PostDec:
- resultType = CheckIncrementDecrementOperand(*this, Input.get(), VK, OpLoc,
+ resultType = CheckIncrementDecrementOperand(*this, Input.get(), VK, OK,
+ OpLoc,
Opc == UO_PreInc ||
Opc == UO_PostInc,
Opc == UO_PreInc ||
@@ -9816,6 +9985,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
break;
case UO_AddrOf:
resultType = CheckAddressOfOperand(Input, OpLoc);
+ RecordModifiableNonNullParam(*this, InputExpr);
break;
case UO_Deref: {
Input = DefaultFunctionArrayLvalueConversion(Input.get());
@@ -10107,11 +10277,6 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
assert(!ExprNeedsCleanups && "cleanups within StmtExpr not correctly bound!");
PopExpressionEvaluationContext();
- bool isFileScope
- = (getCurFunctionOrMethodDecl() == nullptr) && (getCurBlock() == nullptr);
- if (isFileScope)
- return ExprError(Diag(LPLoc, diag::err_stmtexpr_file_scope));
-
// FIXME: there are a variety of strange constraints to enforce here, for
// example, it is not possible to goto into a stmt expression apparently.
// More semantic analysis is needed.
@@ -10998,7 +11163,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
PartialDiagnostic FDiag = PDiag(DiagKind);
if (Action == AA_Passing_CFAudited)
- FDiag << FirstType << SecondType << SrcExpr->getSourceRange();
+ FDiag << FirstType << SecondType << AA_Passing << SrcExpr->getSourceRange();
else
FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange();
@@ -11285,6 +11450,7 @@ Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
void Sema::PopExpressionEvaluationContext() {
ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
+ unsigned NumTypos = Rec.NumTypos;
if (!Rec.Lambdas.empty()) {
if (Rec.isUnevaluated() || Rec.Context == ConstantEvaluated) {
@@ -11301,19 +11467,14 @@ void Sema::PopExpressionEvaluationContext() {
// evaluate [...] a lambda-expression.
D = diag::err_lambda_in_constant_expression;
}
- for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I)
- Diag(Rec.Lambdas[I]->getLocStart(), D);
+ for (const auto *L : Rec.Lambdas)
+ Diag(L->getLocStart(), D);
} else {
// Mark the capture expressions odr-used. This was deferred
// during lambda expression creation.
- for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I) {
- LambdaExpr *Lambda = Rec.Lambdas[I];
- for (LambdaExpr::capture_init_iterator
- C = Lambda->capture_init_begin(),
- CEnd = Lambda->capture_init_end();
- C != CEnd; ++C) {
- MarkDeclarationsReferencedInExpr(*C);
- }
+ for (auto *Lambda : Rec.Lambdas) {
+ for (auto *C : Lambda->capture_inits())
+ MarkDeclarationsReferencedInExpr(C);
}
}
}
@@ -11337,6 +11498,12 @@ void Sema::PopExpressionEvaluationContext() {
// Pop the current expression evaluation context off the stack.
ExprEvalContexts.pop_back();
+
+ if (!ExprEvalContexts.empty())
+ ExprEvalContexts.back().NumTypos += NumTypos;
+ else
+ assert(NumTypos == 0 && "There are outstanding typos after popping the "
+ "last ExpressionEvaluationContextRecord");
}
void Sema::DiscardCleanupsInEvaluationContext() {
@@ -11385,7 +11552,8 @@ static bool IsPotentiallyEvaluatedContext(Sema &SemaRef) {
/// \brief Mark a function referenced, and check whether it is odr-used
/// (C++ [basic.def.odr]p2, C99 6.9p3)
-void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
+void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
+ bool OdrUse) {
assert(Func && "No function?");
Func->setReferenced();
@@ -11484,6 +11652,8 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
if (FPT && isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
ResolveExceptionSpec(Loc, FPT);
+ if (!OdrUse) return;
+
// Implicit instantiation of function templates and member functions of
// class templates.
if (Func->isImplicitlyInstantiable()) {
@@ -11636,7 +11806,7 @@ static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *
const bool Diagnose, Sema &S) {
if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC) || isLambdaCallOperator(DC))
return getLambdaAwareParentOfDeclContext(DC);
- else {
+ else if (Var->hasLocalStorage()) {
if (Diagnose)
diagnoseUncapturableValueReference(S, Loc, Var, DC);
}
@@ -11665,13 +11835,10 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
return false;
}
- // Prohibit variably-modified types; they're difficult to deal with.
- if (Var->getType()->isVariablyModifiedType() && (IsBlock || IsLambda)) {
+ // Prohibit variably-modified types in blocks; they're difficult to deal with.
+ if (Var->getType()->isVariablyModifiedType() && IsBlock) {
if (Diagnose) {
- if (IsBlock)
- S.Diag(Loc, diag::err_ref_vm_type);
- else
- S.Diag(Loc, diag::err_lambda_capture_vm_type) << Var->getDeclName();
+ S.Diag(Loc, diag::err_ref_vm_type);
S.Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
}
@@ -11807,7 +11974,7 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
const bool BuildAndDiagnose,
QualType &CaptureType,
QualType &DeclRefType,
- const bool RefersToEnclosingLocal,
+ const bool RefersToCapturedVariable,
Sema &S) {
// By default, capture variables by reference.
@@ -11829,7 +11996,7 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
Field->setAccess(AS_private);
RD->addDecl(Field);
- CopyExpr = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal,
+ CopyExpr = new (S.Context) DeclRefExpr(Var, RefersToCapturedVariable,
DeclRefType, VK_LValue, Loc);
Var->setReferenced(true);
Var->markUsed(S.Context);
@@ -11837,7 +12004,7 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
// Actually capture the variable.
if (BuildAndDiagnose)
- RSI->addCapture(Var, /*isBlock*/false, ByRef, RefersToEnclosingLocal, Loc,
+ RSI->addCapture(Var, /*isBlock*/false, ByRef, RefersToCapturedVariable, Loc,
SourceLocation(), CaptureType, CopyExpr);
@@ -11851,7 +12018,7 @@ static ExprResult addAsFieldToClosureType(Sema &S,
VarDecl *Var, QualType FieldType,
QualType DeclRefType,
SourceLocation Loc,
- bool RefersToEnclosingLocal) {
+ bool RefersToCapturedVariable) {
CXXRecordDecl *Lambda = LSI->Lambda;
// Build the non-static data member.
@@ -11880,7 +12047,7 @@ static ExprResult addAsFieldToClosureType(Sema &S,
// C++ [expr.prim.labda]p12:
// An entity captured by a lambda-expression is odr-used (3.2) in
// the scope containing the lambda-expression.
- Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal,
+ Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToCapturedVariable,
DeclRefType, VK_LValue, Loc);
Var->setReferenced(true);
Var->markUsed(S.Context);
@@ -11974,7 +12141,7 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
const bool BuildAndDiagnose,
QualType &CaptureType,
QualType &DeclRefType,
- const bool RefersToEnclosingLocal,
+ const bool RefersToCapturedVariable,
const Sema::TryCaptureKind Kind,
SourceLocation EllipsisLoc,
const bool IsTopScope,
@@ -12048,7 +12215,7 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
if (BuildAndDiagnose) {
ExprResult Result = addAsFieldToClosureType(S, LSI, Var,
CaptureType, DeclRefType, Loc,
- RefersToEnclosingLocal);
+ RefersToCapturedVariable);
if (!Result.isInvalid())
CopyExpr = Result.get();
}
@@ -12069,20 +12236,19 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
// Add the capture.
if (BuildAndDiagnose)
- LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToEnclosingLocal,
+ LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToCapturedVariable,
Loc, EllipsisLoc, CaptureType, CopyExpr);
return true;
}
-
bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
TryCaptureKind Kind, SourceLocation EllipsisLoc,
bool BuildAndDiagnose,
QualType &CaptureType,
QualType &DeclRefType,
const unsigned *const FunctionScopeIndexToStopAt) {
- bool Nested = false;
+ bool Nested = Var->isInitCapture();
DeclContext *DC = CurContext;
const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
@@ -12100,8 +12266,13 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
// If the variable is declared in the current context (and is not an
// init-capture), there is no need to capture it.
- if (!Var->isInitCapture() && Var->getDeclContext() == DC) return true;
- if (!Var->hasLocalStorage()) return true;
+ if (!Nested && Var->getDeclContext() == DC) return true;
+
+ // Capture global variables if it is required to use private copy of this
+ // variable.
+ bool IsGlobal = !Var->hasLocalStorage();
+ if (IsGlobal && !(LangOpts.OpenMP && IsOpenMPCapturedVar(Var)))
+ return true;
// Walk up the stack to determine whether we can capture the variable,
// performing the "simple" checks that don't depend on type. We stop when
@@ -12122,8 +12293,17 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
ExprLoc,
BuildAndDiagnose,
*this);
- if (!ParentDC) return true;
-
+ // We need to check for the parent *first* because, if we *have*
+ // private-captured a global variable, we need to recursively capture it in
+ // intermediate blocks, lambdas, etc.
+ if (!ParentDC) {
+ if (IsGlobal) {
+ FunctionScopesIndex = MaxFunctionScopesIndex - 1;
+ break;
+ }
+ return true;
+ }
+
FunctionScopeInfo *FSI = FunctionScopes[FunctionScopesIndex];
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FSI);
@@ -12212,14 +12392,37 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc,
break;
case Type::VariableArray: {
// Losing element qualification here is fine.
- const VariableArrayType *Vat = cast<VariableArrayType>(Ty);
+ const VariableArrayType *VAT = cast<VariableArrayType>(Ty);
// Unknown size indication requires no size computation.
// Otherwise, evaluate and record it.
- if (Expr *Size = Vat->getSizeExpr()) {
- MarkDeclarationsReferencedInExpr(Size);
+ if (auto Size = VAT->getSizeExpr()) {
+ if (!CSI->isVLATypeCaptured(VAT)) {
+ RecordDecl *CapRecord = nullptr;
+ if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) {
+ CapRecord = LSI->Lambda;
+ } else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
+ CapRecord = CRSI->TheRecordDecl;
+ }
+ if (CapRecord) {
+ auto ExprLoc = Size->getExprLoc();
+ auto SizeType = Context.getSizeType();
+ // Build the non-static data member.
+ auto Field = FieldDecl::Create(
+ Context, CapRecord, ExprLoc, ExprLoc,
+ /*Id*/ nullptr, SizeType, /*TInfo*/ nullptr,
+ /*BW*/ nullptr, /*Mutable*/ false,
+ /*InitStyle*/ ICIS_NoInit);
+ Field->setImplicit(true);
+ Field->setAccess(AS_private);
+ Field->setCapturedVLAType(VAT);
+ CapRecord->addDecl(Field);
+
+ CSI->addVLATypeCapture(ExprLoc, SizeType);
+ }
+ }
}
- QTy = Vat->getElementType();
+ QTy = VAT->getElementType();
break;
}
case Type::FunctionProto:
@@ -12326,6 +12529,14 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
DeclRefType, nullptr);
}
+bool Sema::NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc) {
+ QualType CaptureType;
+ QualType DeclRefType;
+ return !tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(),
+ /*BuildAndDiagnose=*/false, CaptureType,
+ DeclRefType, nullptr);
+}
+
QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
QualType CaptureType;
QualType DeclRefType;
@@ -12388,6 +12599,8 @@ void Sema::UpdateMarkingForLValueToRValue(Expr *E) {
}
ExprResult Sema::ActOnConstantExpression(ExprResult Res) {
+ Res = CorrectDelayedTyposInExpr(Res);
+
if (!Res.isUsable())
return Res;
@@ -12412,7 +12625,7 @@ void Sema::CleanupVarDeclMarking() {
Var = cast<VarDecl>(ME->getMemberDecl());
Loc = ME->getMemberLoc();
} else {
- llvm_unreachable("Unexpcted expression");
+ llvm_unreachable("Unexpected expression");
}
MarkVarDeclODRUsed(Var, Loc, *this,
@@ -12429,6 +12642,9 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
"Invalid Expr argument to DoMarkVarDeclReferenced");
Var->setReferenced();
+ TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
+ bool MarkODRUsed = true;
+
// If the context is not potentially evaluated, this is not an odr-use and
// does not trigger instantiation.
if (!IsPotentiallyEvaluatedContext(SemaRef)) {
@@ -12443,25 +12659,29 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
// arguments, where local variables can't be used.
const bool RefersToEnclosingScope =
(SemaRef.CurContext != Var->getDeclContext() &&
- Var->getDeclContext()->isFunctionOrMethod() &&
- Var->hasLocalStorage());
- if (!RefersToEnclosingScope)
- return;
-
- if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) {
- // If a variable could potentially be odr-used, defer marking it so
- // until we finish analyzing the full expression for any lvalue-to-rvalue
- // or discarded value conversions that would obviate odr-use.
- // Add it to the list of potential captures that will be analyzed
- // later (ActOnFinishFullExpr) for eventual capture and odr-use marking
- // unless the variable is a reference that was initialized by a constant
- // expression (this will never need to be captured or odr-used).
- assert(E && "Capture variable should be used in an expression.");
- if (!Var->getType()->isReferenceType() ||
- !IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context))
- LSI->addPotentialCapture(E->IgnoreParens());
+ Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage());
+ if (RefersToEnclosingScope) {
+ if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) {
+ // If a variable could potentially be odr-used, defer marking it so
+ // until we finish analyzing the full expression for any
+ // lvalue-to-rvalue
+ // or discarded value conversions that would obviate odr-use.
+ // Add it to the list of potential captures that will be analyzed
+ // later (ActOnFinishFullExpr) for eventual capture and odr-use marking
+ // unless the variable is a reference that was initialized by a constant
+ // expression (this will never need to be captured or odr-used).
+ assert(E && "Capture variable should be used in an expression.");
+ if (!Var->getType()->isReferenceType() ||
+ !IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context))
+ LSI->addPotentialCapture(E->IgnoreParens());
+ }
}
- return;
+
+ if (!isTemplateInstantiation(TSK))
+ return;
+
+ // Instantiate, but do not mark as odr-used, variable templates.
+ MarkODRUsed = false;
}
VarTemplateSpecializationDecl *VarSpec =
@@ -12473,7 +12693,6 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
// 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;
@@ -12513,6 +12732,8 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
}
}
+ if(!MarkODRUsed) return;
+
// 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)
@@ -12555,6 +12776,10 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ME->getMemberDecl());
if (!MD)
return;
+ // Only attempt to devirtualize if this is truly a virtual call.
+ bool IsVirtualCall = MD->isVirtual() && !ME->hasQualifier();
+ if (!IsVirtualCall)
+ return;
const Expr *Base = ME->getBase();
const CXXRecordDecl *MostDerivedClassDecl = Base->getBestDynamicClassType();
if (!MostDerivedClassDecl)
@@ -12602,14 +12827,14 @@ void Sema::MarkMemberReferenced(MemberExpr *E) {
/// normal expression which refers to a variable.
void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool OdrUse) {
if (OdrUse) {
- if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (auto *VD = dyn_cast<VarDecl>(D)) {
MarkVariableReferenced(Loc, VD);
return;
}
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- MarkFunctionReferenced(Loc, FD);
- return;
- }
+ }
+ if (auto *FD = dyn_cast<FunctionDecl>(D)) {
+ MarkFunctionReferenced(Loc, FD, OdrUse);
+ return;
}
D->setReferenced();
}
@@ -12935,6 +13160,7 @@ ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) {
<< T << E->getSourceRange();
return ExprError();
}
+ CheckBoolLikeConversion(E, Loc);
}
return E;
@@ -13306,6 +13532,39 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
<< VD << E->getSourceRange();
return ExprError();
}
+ if (const FunctionProtoType *FT = Type->getAs<FunctionProtoType>()) {
+ // We must match the FunctionDecl's type to the hack introduced in
+ // RebuildUnknownAnyExpr::VisitCallExpr to vararg functions of unknown
+ // type. See the lengthy commentary in that routine.
+ QualType FDT = FD->getType();
+ const FunctionType *FnType = FDT->castAs<FunctionType>();
+ const FunctionProtoType *Proto = dyn_cast_or_null<FunctionProtoType>(FnType);
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
+ if (DRE && Proto && Proto->getParamTypes().empty() && Proto->isVariadic()) {
+ SourceLocation Loc = FD->getLocation();
+ FunctionDecl *NewFD = FunctionDecl::Create(FD->getASTContext(),
+ FD->getDeclContext(),
+ Loc, Loc, FD->getNameInfo().getName(),
+ DestType, FD->getTypeSourceInfo(),
+ SC_None, false/*isInlineSpecified*/,
+ FD->hasPrototype(),
+ false/*isConstexprSpecified*/);
+
+ if (FD->getQualifier())
+ NewFD->setQualifierInfo(FD->getQualifierLoc());
+
+ SmallVector<ParmVarDecl*, 16> Params;
+ for (const auto &AI : FT->param_types()) {
+ ParmVarDecl *Param =
+ S.BuildParmVarDeclForTypedef(FD, Loc, AI);
+ Param->setScopeInfo(0, Params.size());
+ Params.push_back(Param);
+ }
+ NewFD->setParams(Params);
+ DRE->setDecl(NewFD);
+ VD = DRE->getDecl();
+ }
+ }
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
if (MD->isInstance()) {
@@ -13431,6 +13690,15 @@ static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {
/// Check for operands with placeholder types and complain if found.
/// Returns true if there was an error and no recovery was possible.
ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
+ if (!getLangOpts().CPlusPlus) {
+ // C cannot handle TypoExpr nodes on either side of a binop because it
+ // doesn't handle dependent types properly, so make sure any TypoExprs have
+ // been dealt with before checking the operands.
+ ExprResult Result = CorrectDelayedTyposInExpr(E);
+ if (!Result.isUsable()) return ExprError();
+ E = Result.get();
+ }
+
const BuiltinType *placeholderType = E->getType()->getAsPlaceholderType();
if (!placeholderType) return E;
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 0dabdca29553..422398ebeb1e 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "TreeTransform.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
@@ -67,6 +68,7 @@ ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS,
break;
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
llvm_unreachable("Nested name specifier is not a type for inheriting ctor");
@@ -198,6 +200,7 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) {
QualType T = Context.getTypeDeclType(Type);
+ MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false);
if (SearchType.isNull() || SearchType->isDependentType() ||
Context.hasSameUnqualifiedType(T, SearchType)) {
@@ -354,6 +357,7 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
return true;
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
return false;
@@ -380,6 +384,9 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid))
return ExprError();
+ if (T->isVariablyModifiedType())
+ return ExprError(Diag(TypeidLoc, diag::err_variably_modified_typeid) << T);
+
return new (Context) CXXTypeidExpr(TypeInfoType.withConst(), Operand,
SourceRange(TypeidLoc, RParenLoc));
}
@@ -389,6 +396,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
SourceLocation TypeidLoc,
Expr *E,
SourceLocation RParenLoc) {
+ bool WasEvaluated = false;
if (E && !E->isTypeDependent()) {
if (E->getType()->isPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
@@ -418,6 +426,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
// We require a vtable to query the type at run time.
MarkVTableUsed(TypeidLoc, RecordD);
+ WasEvaluated = true;
}
}
@@ -434,6 +443,18 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
}
}
+ if (E->getType()->isVariablyModifiedType())
+ return ExprError(Diag(TypeidLoc, diag::err_variably_modified_typeid)
+ << E->getType());
+ else if (ActiveTemplateInstantiations.empty() &&
+ E->HasSideEffects(Context, WasEvaluated)) {
+ // The expression operand for typeid is in an unevaluated expression
+ // context, so side effects could result in unintended consequences.
+ Diag(E->getExprLoc(), WasEvaluated
+ ? diag::warn_side_effects_typeid
+ : diag::warn_side_effects_unevaluated_context);
+ }
+
return new (Context) CXXTypeidExpr(TypeInfoType.withConst(), E,
SourceRange(TypeidLoc, RParenLoc));
}
@@ -580,15 +601,15 @@ Sema::ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *Ex) {
bool IsThrownVarInScope = false;
if (Ex) {
// C++0x [class.copymove]p31:
- // When certain criteria are met, an implementation is allowed to omit the
+ // When certain criteria are met, an implementation is allowed to omit the
// copy/move construction of a class object [...]
//
- // - in a throw-expression, when the operand is the name of a
+ // - in a throw-expression, when the operand is the name of a
// non-volatile automatic object (other than a function or catch-
- // clause parameter) whose scope does not extend beyond the end of the
- // innermost enclosing try-block (if there is one), the copy/move
- // operation from the operand to the exception object (15.1) can be
- // omitted by constructing the automatic object directly into the
+ // clause parameter) whose scope does not extend beyond the end of the
+ // innermost enclosing try-block (if there is one), the copy/move
+ // operation from the operand to the exception object (15.1) can be
+ // omitted by constructing the automatic object directly into the
// exception object
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Ex->IgnoreParens()))
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
@@ -1083,7 +1104,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr;
if (Expr *NumElts = (Expr *)Array.NumElts) {
if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) {
- if (getLangOpts().CPlusPlus1y) {
+ if (getLangOpts().CPlusPlus14) {
// C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator
// shall be a converted constant expression (5.19) of type std::size_t
// and shall evaluate to a strictly positive value.
@@ -1257,7 +1278,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// std::size_t.
if (ArraySize && !ArraySize->isTypeDependent()) {
ExprResult ConvertedSize;
- if (getLangOpts().CPlusPlus1y) {
+ if (getLangOpts().CPlusPlus14) {
assert(Context.getTargetInfo().getIntWidth() && "Builtin type of size 0?");
ConvertedSize = PerformImplicitConversion(ArraySize, Context.getSizeType(),
@@ -2072,19 +2093,18 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
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;
+ EPI.ExceptionSpec.Type = EST_Dynamic;
+ EPI.ExceptionSpec.Exceptions = llvm::makeArrayRef(BadAllocType);
}
} else {
- EPI.ExceptionSpecType = getLangOpts().CPlusPlus11 ?
- EST_BasicNoexcept : EST_DynamicNone;
+ EPI.ExceptionSpec =
+ getLangOpts().CPlusPlus11 ? EST_BasicNoexcept : EST_DynamicNone;
}
QualType Params[] = { Param1, Param2 };
QualType FnType = Context.getFunctionType(
- Return, ArrayRef<QualType>(Params, NumParams), EPI);
+ Return, llvm::makeArrayRef(Params, NumParams), EPI);
FunctionDecl *Alloc =
FunctionDecl::Create(Context, GlobalCtx, SourceLocation(),
SourceLocation(), Name,
@@ -2102,7 +2122,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
SC_None, nullptr);
ParamDecls[I]->setImplicit();
}
- Alloc->setParams(ArrayRef<ParmVarDecl*>(ParamDecls, NumParams));
+ Alloc->setParams(llvm::makeArrayRef(ParamDecls, NumParams));
Context.getTranslationUnitDecl()->addDecl(Alloc);
IdResolver.tryAddTopLevelDecl(Alloc, Name);
@@ -2622,8 +2642,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// Do no conversion if dealing with ... for the first conversion.
if (!ICS.UserDefined.EllipsisConversion) {
// If the user-defined conversion is specified by a constructor, the
- // initial standard conversion sequence converts the source type to the
- // type required by the argument of the constructor
+ // initial standard conversion sequence converts the source type to
+ // the type required by the argument of the constructor
BeforeToType = Ctor->getParamDecl(0)->getType().getNonReferenceType();
}
}
@@ -2739,15 +2759,19 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// Perform the first implicit conversion.
switch (SCS.First) {
case ICK_Identity:
- // Nothing to do.
+ if (const AtomicType *FromAtomic = FromType->getAs<AtomicType>()) {
+ FromType = FromAtomic->getValueType().getUnqualifiedType();
+ From = ImplicitCastExpr::Create(Context, FromType, CK_AtomicToNonAtomic,
+ From, /*BasePath=*/nullptr, VK_RValue);
+ }
break;
case ICK_Lvalue_To_Rvalue: {
assert(From->getObjectKind() != OK_ObjCProperty);
- FromType = FromType.getUnqualifiedType();
ExprResult FromRes = DefaultLvalueConversion(From);
assert(!FromRes.isInvalid() && "Can't perform deduced conversion?!");
From = FromRes.get();
+ FromType = From->getType();
break;
}
@@ -2770,10 +2794,29 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// Perform the second implicit conversion
switch (SCS.Second) {
case ICK_Identity:
- // If both sides are functions (or pointers/references to them), there could
- // be incompatible exception declarations.
- if (CheckExceptionSpecCompatibility(From, ToType))
- return ExprError();
+ // C++ [except.spec]p5:
+ // [For] assignment to and initialization of pointers to functions,
+ // pointers to member functions, and references to functions: the
+ // target entity shall allow at least the exceptions allowed by the
+ // source value in the assignment or initialization.
+ switch (Action) {
+ case AA_Assigning:
+ case AA_Initializing:
+ // Note, function argument passing and returning are initialization.
+ case AA_Passing:
+ case AA_Returning:
+ case AA_Sending:
+ case AA_Passing_CFAudited:
+ if (CheckExceptionSpecCompatibility(From, ToType))
+ return ExprError();
+ break;
+
+ case AA_Casting:
+ case AA_Converting:
+ // Casts and implicit conversions are not initialization, so are not
+ // checked for exception specification mismatches.
+ break;
+ }
// Nothing else to do.
break;
@@ -2899,6 +2942,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
return ExprError();
if (CheckExceptionSpecCompatibility(From, ToType))
return ExprError();
+
+ // We may not have been able to figure out what this member pointer resolved
+ // to up until this exact point. Attempt to lock-in it's inheritance model.
+ QualType FromType = From->getType();
+ if (FromType->isMemberPointerType())
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ RequireCompleteType(From->getExprLoc(), FromType, 0);
+
From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
.get();
break;
@@ -3642,12 +3693,13 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
if (T->isObjectType() || T->isFunctionType())
T = S.Context.getRValueReferenceType(T);
OpaqueArgExprs.push_back(
- OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(),
+ OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(),
T.getNonLValueExprType(S.Context),
Expr::getValueKindForType(T)));
- ArgExprs.push_back(&OpaqueArgExprs.back());
}
-
+ for (Expr &E : OpaqueArgExprs)
+ ArgExprs.push_back(&E);
+
// Perform the initialization in an unevaluated context within a SFINAE
// trap at translation unit scope.
EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
@@ -4549,10 +4601,14 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// the usual arithmetic conversions are performed to bring them to a
// common type, and the result is of that type.
if (LTy->isArithmeticType() && RTy->isArithmeticType()) {
- UsualArithmeticConversions(LHS, RHS);
+ QualType ResTy = UsualArithmeticConversions(LHS, RHS);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
- return LHS.get()->getType();
+
+ LHS = ImpCastExprToType(LHS.get(), ResTy, PrepareScalarCast(LHS, ResTy));
+ RHS = ImpCastExprToType(RHS.get(), ResTy, PrepareScalarCast(RHS, ResTy));
+
+ return ResTy;
}
// -- The second and third operands have pointer type, or one has pointer
@@ -4993,9 +5049,8 @@ Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) {
if (!ExprNeedsCleanups)
return SubExpr;
- ArrayRef<ExprWithCleanups::CleanupObject> Cleanups
- = llvm::makeArrayRef(ExprCleanupObjects.begin() + FirstCleanup,
- ExprCleanupObjects.size() - FirstCleanup);
+ auto Cleanups = llvm::makeArrayRef(ExprCleanupObjects.begin() + FirstCleanup,
+ ExprCleanupObjects.size() - FirstCleanup);
Expr *E = ExprWithCleanups::Create(Context, SubExpr, Cleanups);
DiscardCleanupsInEvaluationContext();
@@ -5231,7 +5286,7 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
OperatorArrows.push_back(OpCall->getDirectCallee());
BaseType = Base->getType();
CanQualType CBaseType = Context.getCanonicalType(BaseType);
- if (!CTypes.insert(CBaseType)) {
+ if (!CTypes.insert(CBaseType).second) {
Diag(OpLoc, diag::err_operator_arrow_circular) << StartingType;
noteOperatorArrows(*this, OperatorArrows);
return ExprError();
@@ -5581,7 +5636,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc))
return ExprError();
- QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
+ QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc(),
+ false);
TypeLocBuilder TLB;
DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
@@ -5649,6 +5705,13 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
SourceLocation RParen) {
+ if (ActiveTemplateInstantiations.empty() &&
+ Operand->HasSideEffects(Context, false)) {
+ // The expression operand for noexcept is in an unevaluated expression
+ // context, so side effects could result in unintended consequences.
+ Diag(Operand->getExprLoc(), diag::warn_side_effects_unevaluated_context);
+ }
+
CanThrowResult CanThrow = canThrow(Operand);
return new (Context)
CXXNoexceptExpr(Context.BoolTy, Operand, CanThrow, KeyLoc, RParen);
@@ -5905,6 +5968,284 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
CurrentLSI->clearPotentialCaptures();
}
+static ExprResult attemptRecovery(Sema &SemaRef,
+ const TypoCorrectionConsumer &Consumer,
+ TypoCorrection TC) {
+ LookupResult R(SemaRef, Consumer.getLookupResult().getLookupNameInfo(),
+ Consumer.getLookupResult().getLookupKind());
+ const CXXScopeSpec *SS = Consumer.getSS();
+ CXXScopeSpec NewSS;
+
+ // Use an approprate CXXScopeSpec for building the expr.
+ if (auto *NNS = TC.getCorrectionSpecifier())
+ NewSS.MakeTrivial(SemaRef.Context, NNS, TC.getCorrectionRange());
+ else if (SS && !TC.WillReplaceSpecifier())
+ NewSS = *SS;
+
+ if (auto *ND = TC.getCorrectionDecl()) {
+ R.setLookupName(ND->getDeclName());
+ R.addDecl(ND);
+ if (ND->isCXXClassMember()) {
+ // Figure out the correct naming class to add to the LookupResult.
+ CXXRecordDecl *Record = nullptr;
+ if (auto *NNS = TC.getCorrectionSpecifier())
+ Record = NNS->getAsType()->getAsCXXRecordDecl();
+ if (!Record)
+ Record =
+ dyn_cast<CXXRecordDecl>(ND->getDeclContext()->getRedeclContext());
+ if (Record)
+ R.setNamingClass(Record);
+
+ // Detect and handle the case where the decl might be an implicit
+ // member.
+ bool MightBeImplicitMember;
+ if (!Consumer.isAddressOfOperand())
+ MightBeImplicitMember = true;
+ else if (!NewSS.isEmpty())
+ MightBeImplicitMember = false;
+ else if (R.isOverloadedResult())
+ MightBeImplicitMember = false;
+ else if (R.isUnresolvableResult())
+ MightBeImplicitMember = true;
+ else
+ MightBeImplicitMember = isa<FieldDecl>(ND) ||
+ isa<IndirectFieldDecl>(ND) ||
+ isa<MSPropertyDecl>(ND);
+
+ if (MightBeImplicitMember)
+ return SemaRef.BuildPossibleImplicitMemberExpr(
+ NewSS, /*TemplateKWLoc*/ SourceLocation(), R,
+ /*TemplateArgs*/ nullptr);
+ } else if (auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
+ return SemaRef.LookupInObjCMethod(R, Consumer.getScope(),
+ Ivar->getIdentifier());
+ }
+ }
+
+ return SemaRef.BuildDeclarationNameExpr(NewSS, R, /*NeedsADL*/ false,
+ /*AcceptInvalidDecl*/ true);
+}
+
+namespace {
+class FindTypoExprs : public RecursiveASTVisitor<FindTypoExprs> {
+ llvm::SmallSetVector<TypoExpr *, 2> &TypoExprs;
+
+public:
+ explicit FindTypoExprs(llvm::SmallSetVector<TypoExpr *, 2> &TypoExprs)
+ : TypoExprs(TypoExprs) {}
+ bool VisitTypoExpr(TypoExpr *TE) {
+ TypoExprs.insert(TE);
+ return true;
+ }
+};
+
+class TransformTypos : public TreeTransform<TransformTypos> {
+ typedef TreeTransform<TransformTypos> BaseTransform;
+
+ llvm::function_ref<ExprResult(Expr *)> ExprFilter;
+ llvm::SmallSetVector<TypoExpr *, 2> TypoExprs, AmbiguousTypoExprs;
+ llvm::SmallDenseMap<TypoExpr *, ExprResult, 2> TransformCache;
+ llvm::SmallDenseMap<OverloadExpr *, Expr *, 4> OverloadResolution;
+
+ /// \brief Emit diagnostics for all of the TypoExprs encountered.
+ /// If the TypoExprs were successfully corrected, then the diagnostics should
+ /// suggest the corrections. Otherwise the diagnostics will not suggest
+ /// anything (having been passed an empty TypoCorrection).
+ void EmitAllDiagnostics() {
+ for (auto E : TypoExprs) {
+ TypoExpr *TE = cast<TypoExpr>(E);
+ auto &State = SemaRef.getTypoExprState(TE);
+ if (State.DiagHandler) {
+ TypoCorrection TC = State.Consumer->getCurrentCorrection();
+ ExprResult Replacement = TransformCache[TE];
+
+ // Extract the NamedDecl from the transformed TypoExpr and add it to the
+ // TypoCorrection, replacing the existing decls. This ensures the right
+ // NamedDecl is used in diagnostics e.g. in the case where overload
+ // resolution was used to select one from several possible decls that
+ // had been stored in the TypoCorrection.
+ if (auto *ND = getDeclFromExpr(
+ Replacement.isInvalid() ? nullptr : Replacement.get()))
+ TC.setCorrectionDecl(ND);
+
+ State.DiagHandler(TC);
+ }
+ SemaRef.clearDelayedTypo(TE);
+ }
+ }
+
+ /// \brief If corrections for the first TypoExpr have been exhausted for a
+ /// given combination of the other TypoExprs, retry those corrections against
+ /// the next combination of substitutions for the other TypoExprs by advancing
+ /// to the next potential correction of the second TypoExpr. For the second
+ /// and subsequent TypoExprs, if its stream of corrections has been exhausted,
+ /// the stream is reset and the next TypoExpr's stream is advanced by one (a
+ /// TypoExpr's correction stream is advanced by removing the TypoExpr from the
+ /// TransformCache). Returns true if there is still any untried combinations
+ /// of corrections.
+ bool CheckAndAdvanceTypoExprCorrectionStreams() {
+ for (auto TE : TypoExprs) {
+ auto &State = SemaRef.getTypoExprState(TE);
+ TransformCache.erase(TE);
+ if (!State.Consumer->finished())
+ return true;
+ State.Consumer->resetCorrectionStream();
+ }
+ return false;
+ }
+
+ NamedDecl *getDeclFromExpr(Expr *E) {
+ if (auto *OE = dyn_cast_or_null<OverloadExpr>(E))
+ E = OverloadResolution[OE];
+
+ if (!E)
+ return nullptr;
+ if (auto *DRE = dyn_cast<DeclRefExpr>(E))
+ return DRE->getDecl();
+ if (auto *ME = dyn_cast<MemberExpr>(E))
+ return ME->getMemberDecl();
+ // FIXME: Add any other expr types that could be be seen by the delayed typo
+ // correction TreeTransform for which the corresponding TypoCorrection could
+ // contain multiple decls.
+ return nullptr;
+ }
+
+ ExprResult TryTransform(Expr *E) {
+ Sema::SFINAETrap Trap(SemaRef);
+ ExprResult Res = TransformExpr(E);
+ if (Trap.hasErrorOccurred() || Res.isInvalid())
+ return ExprError();
+
+ return ExprFilter(Res.get());
+ }
+
+public:
+ TransformTypos(Sema &SemaRef, llvm::function_ref<ExprResult(Expr *)> Filter)
+ : BaseTransform(SemaRef), ExprFilter(Filter) {}
+
+ ExprResult RebuildCallExpr(Expr *Callee, SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation RParenLoc,
+ Expr *ExecConfig = nullptr) {
+ auto Result = BaseTransform::RebuildCallExpr(Callee, LParenLoc, Args,
+ RParenLoc, ExecConfig);
+ if (auto *OE = dyn_cast<OverloadExpr>(Callee)) {
+ if (Result.isUsable()) {
+ Expr *ResultCall = Result.get();
+ if (auto *BE = dyn_cast<CXXBindTemporaryExpr>(ResultCall))
+ ResultCall = BE->getSubExpr();
+ if (auto *CE = dyn_cast<CallExpr>(ResultCall))
+ OverloadResolution[OE] = CE->getCallee();
+ }
+ }
+ return Result;
+ }
+
+ ExprResult TransformLambdaExpr(LambdaExpr *E) { return Owned(E); }
+
+ ExprResult TransformOpaqueValueExpr(OpaqueValueExpr *E) {
+ if (Expr *SE = E->getSourceExpr())
+ return TransformExpr(SE);
+ return BaseTransform::TransformOpaqueValueExpr(E);
+ }
+
+ ExprResult Transform(Expr *E) {
+ ExprResult Res;
+ while (true) {
+ Res = TryTransform(E);
+
+ // Exit if either the transform was valid or if there were no TypoExprs
+ // to transform that still have any untried correction candidates..
+ if (!Res.isInvalid() ||
+ !CheckAndAdvanceTypoExprCorrectionStreams())
+ break;
+ }
+
+ // Ensure none of the TypoExprs have multiple typo correction candidates
+ // with the same edit length that pass all the checks and filters.
+ // TODO: Properly handle various permutations of possible corrections when
+ // there is more than one potentially ambiguous typo correction.
+ while (!AmbiguousTypoExprs.empty()) {
+ auto TE = AmbiguousTypoExprs.back();
+ auto Cached = TransformCache[TE];
+ AmbiguousTypoExprs.pop_back();
+ TransformCache.erase(TE);
+ if (!TryTransform(E).isInvalid()) {
+ SemaRef.getTypoExprState(TE).Consumer->resetCorrectionStream();
+ TransformCache.erase(TE);
+ Res = ExprError();
+ break;
+ } else
+ TransformCache[TE] = Cached;
+ }
+
+ // Ensure that all of the TypoExprs within the current Expr have been found.
+ if (!Res.isUsable())
+ FindTypoExprs(TypoExprs).TraverseStmt(E);
+
+ EmitAllDiagnostics();
+
+ return Res;
+ }
+
+ ExprResult TransformTypoExpr(TypoExpr *E) {
+ // If the TypoExpr hasn't been seen before, record it. Otherwise, return the
+ // cached transformation result if there is one and the TypoExpr isn't the
+ // first one that was encountered.
+ auto &CacheEntry = TransformCache[E];
+ if (!TypoExprs.insert(E) && !CacheEntry.isUnset()) {
+ return CacheEntry;
+ }
+
+ auto &State = SemaRef.getTypoExprState(E);
+ assert(State.Consumer && "Cannot transform a cleared TypoExpr");
+
+ // For the first TypoExpr and an uncached TypoExpr, find the next likely
+ // typo correction and return it.
+ while (TypoCorrection TC = State.Consumer->getNextCorrection()) {
+ ExprResult NE = State.RecoveryHandler ?
+ State.RecoveryHandler(SemaRef, E, TC) :
+ attemptRecovery(SemaRef, *State.Consumer, TC);
+ if (!NE.isInvalid()) {
+ // Check whether there may be a second viable correction with the same
+ // edit distance; if so, remember this TypoExpr may have an ambiguous
+ // correction so it can be more thoroughly vetted later.
+ TypoCorrection Next;
+ if ((Next = State.Consumer->peekNextCorrection()) &&
+ Next.getEditDistance(false) == TC.getEditDistance(false)) {
+ AmbiguousTypoExprs.insert(E);
+ } else {
+ AmbiguousTypoExprs.remove(E);
+ }
+ assert(!NE.isUnset() &&
+ "Typo was transformed into a valid-but-null ExprResult");
+ return CacheEntry = NE;
+ }
+ }
+ return CacheEntry = ExprError();
+ }
+};
+}
+
+ExprResult Sema::CorrectDelayedTyposInExpr(
+ Expr *E, llvm::function_ref<ExprResult(Expr *)> Filter) {
+ // If the current evaluation context indicates there are uncorrected typos
+ // and the current expression isn't guaranteed to not have typos, try to
+ // resolve any TypoExpr nodes that might be in the expression.
+ if (E && !ExprEvalContexts.empty() && ExprEvalContexts.back().NumTypos &&
+ (E->isTypeDependent() || E->isValueDependent() ||
+ E->isInstantiationDependent())) {
+ auto TyposResolved = DelayedTypos.size();
+ auto Result = TransformTypos(*this, Filter).Transform(E);
+ TyposResolved -= DelayedTypos.size();
+ if (Result.isInvalid() || Result.get() != E) {
+ ExprEvalContexts.back().NumTypos -= TyposResolved;
+ return Result;
+ }
+ assert(TyposResolved == 0 && "Corrected typo but got same Expr back?");
+ }
+ return E;
+}
ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
bool DiscardedValue,
@@ -5952,6 +6293,10 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
return ExprError();
}
+ FullExpr = CorrectDelayedTyposInExpr(FullExpr.get());
+ if (FullExpr.isInvalid())
+ return ExprError();
+
CheckCompletedExpr(FullExpr.get(), CC, IsConstexpr);
// At the end of this full expression (which could be a deeply nested
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index ef7898208cae..af1cf9046113 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -10,7 +10,7 @@
// This file implements semantic analysis member access expressions.
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Overload.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
@@ -21,6 +21,7 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
using namespace clang;
using namespace sema;
@@ -89,7 +90,6 @@ enum IMAKind {
/// conservatively answer "yes", in which case some errors will simply
/// not be caught until template-instantiation.
static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
- Scope *CurScope,
const LookupResult &R) {
assert(!R.empty() && (*R.begin())->isCXXClassMember());
@@ -204,6 +204,9 @@ static void diagnoseInstanceReference(Sema &SemaRef,
SourceRange Range(Loc);
if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());
+ // Look through using shadow decls and aliases.
+ Rep = Rep->getUnderlyingDecl();
+
DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext();
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC);
CXXRecordDecl *ContextClass = Method ? Method->getParent() : nullptr;
@@ -236,7 +239,7 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs) {
- switch (ClassifyImplicitMemberAccess(*this, CurScope, R)) {
+ switch (ClassifyImplicitMemberAccess(*this, R)) {
case IMA_Instance:
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true);
@@ -536,9 +539,17 @@ namespace {
// FunctionTemplateDecl and are declared in the current record or, for a C++
// classes, one of its base classes.
class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
- public:
+public:
explicit RecordMemberExprValidatorCCC(const RecordType *RTy)
- : Record(RTy->getDecl()) {}
+ : Record(RTy->getDecl()) {
+ // Don't add bare keywords to the consumer since they will always fail
+ // validation by virtue of not being associated with any decls.
+ WantTypeSpecifiers = false;
+ WantExpressionKeywords = false;
+ WantCXXNamedCasts = false;
+ WantFunctionLikeCasts = false;
+ WantRemainingKeywords = false;
+ }
bool ValidateCandidate(const TypoCorrection &candidate) override {
NamedDecl *ND = candidate.getCorrectionDecl();
@@ -554,8 +565,8 @@ class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record)) {
// Accept candidates that occur in any of the current class' base classes.
for (const auto &BS : RD->bases()) {
- if (const RecordType *BSTy = dyn_cast_or_null<RecordType>(
- BS.getType().getTypePtrOrNull())) {
+ if (const RecordType *BSTy =
+ dyn_cast_or_null<RecordType>(BS.getType().getTypePtrOrNull())) {
if (BSTy->getDecl()->containsDecl(ND))
return true;
}
@@ -565,17 +576,19 @@ class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
return false;
}
- private:
+private:
const RecordDecl *const Record;
};
}
-static bool
-LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
- SourceRange BaseRange, const RecordType *RTy,
- SourceLocation OpLoc, CXXScopeSpec &SS,
- bool HasTemplateArgs) {
+static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
+ Expr *BaseExpr,
+ const RecordType *RTy,
+ SourceLocation OpLoc, bool IsArrow,
+ CXXScopeSpec &SS, bool HasTemplateArgs,
+ TypoExpr *&TE) {
+ SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange();
RecordDecl *RDecl = RTy->getDecl();
if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) &&
SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
@@ -600,7 +613,7 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
if (SemaRef.RequireCompleteDeclContext(SS, DC)) {
SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag)
- << SS.getRange() << DC;
+ << SS.getRange() << DC;
return true;
}
@@ -608,47 +621,48 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
if (!isa<TypeDecl>(DC)) {
SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_nonclass)
- << DC << SS.getRange();
+ << DC << SS.getRange();
return true;
}
}
// The record definition is complete, now look up the member.
- SemaRef.LookupQualifiedName(R, DC);
+ SemaRef.LookupQualifiedName(R, DC, SS);
if (!R.empty())
return false;
- // We didn't find anything with the given name, so try to correct
- // for typos.
- DeclarationName Name = R.getLookupName();
- RecordMemberExprValidatorCCC Validator(RTy);
- TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(),
- R.getLookupKind(), nullptr,
- &SS, Validator,
- Sema::CTK_ErrorRecovery, DC);
- R.clear();
- if (Corrected.isResolved() && !Corrected.isKeyword()) {
- R.setLookupName(Corrected.getCorrection());
- for (TypoCorrection::decl_iterator DI = Corrected.begin(),
- DIEnd = Corrected.end();
- DI != DIEnd; ++DI) {
- R.addDecl(*DI);
- }
- R.resolveKind();
-
- // If we're typo-correcting to an overloaded name, we don't yet have enough
- // information to do overload resolution, so we don't know which previous
- // declaration to point to.
- if (Corrected.isOverloaded())
- Corrected.setCorrectionDecl(nullptr);
- bool DroppedSpecifier =
- Corrected.WillReplaceSpecifier() &&
- Name.getAsString() == Corrected.getAsString(SemaRef.getLangOpts());
- SemaRef.diagnoseTypo(Corrected,
- SemaRef.PDiag(diag::err_no_member_suggest)
- << Name << DC << DroppedSpecifier << SS.getRange());
- }
+ DeclarationName Typo = R.getLookupName();
+ SourceLocation TypoLoc = R.getNameLoc();
+ TE = SemaRef.CorrectTypoDelayed(
+ R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS,
+ llvm::make_unique<RecordMemberExprValidatorCCC>(RTy),
+ [=, &SemaRef](const TypoCorrection &TC) {
+ if (TC) {
+ assert(!TC.isKeyword() &&
+ "Got a keyword as a correction for a member!");
+ bool DroppedSpecifier =
+ TC.WillReplaceSpecifier() &&
+ Typo.getAsString() == TC.getAsString(SemaRef.getLangOpts());
+ SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest)
+ << Typo << DC << DroppedSpecifier
+ << SS.getRange());
+ } else {
+ SemaRef.Diag(TypoLoc, diag::err_no_member) << Typo << DC << BaseRange;
+ }
+ },
+ [=](Sema &SemaRef, TypoExpr *TE, TypoCorrection TC) mutable {
+ R.clear(); // Ensure there's no decls lingering in the shared state.
+ R.suppressDiagnostics();
+ R.setLookupName(TC.getCorrection());
+ for (NamedDecl *ND : TC)
+ R.addDecl(ND);
+ R.resolveKind();
+ return SemaRef.BuildMemberReferenceExpr(
+ BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS, SourceLocation(),
+ nullptr, R, nullptr);
+ },
+ Sema::CTK_ErrorRecovery, DC);
return false;
}
@@ -678,12 +692,15 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
// Implicit member accesses.
if (!Base) {
+ TypoExpr *TE = nullptr;
QualType RecordTy = BaseType;
if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType();
- if (LookupMemberExprInRecord(*this, R, SourceRange(),
- RecordTy->getAs<RecordType>(),
- OpLoc, SS, TemplateArgs != nullptr))
+ if (LookupMemberExprInRecord(*this, R, nullptr,
+ RecordTy->getAs<RecordType>(), OpLoc, IsArrow,
+ SS, TemplateArgs != nullptr, TE))
return ExprError();
+ if (TE)
+ return TE;
// Explicit member accesses.
} else {
@@ -1211,13 +1228,16 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
// Handle field access to simple records.
if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
- if (LookupMemberExprInRecord(S, R, BaseExpr.get()->getSourceRange(),
- RTy, OpLoc, SS, HasTemplateArgs))
+ TypoExpr *TE = nullptr;
+ if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy,
+ OpLoc, IsArrow, SS, HasTemplateArgs, TE))
return ExprError();
// Returning valid-but-null is how we indicate to the caller that
- // the lookup result was filled in.
- return ExprResult((Expr *)nullptr);
+ // the lookup result was filled in. If typo correction was attempted and
+ // failed, the lookup result will have been cleared--that combined with the
+ // valid-but-null ExprResult will trigger the appropriate diagnostics.
+ return ExprResult(TE);
}
// Handle ivar access to Objective-C objects.
@@ -1262,11 +1282,11 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
if (!IV) {
// Attempt to correct for typos in ivar names.
- DeclFilterCCC<ObjCIvarDecl> Validator;
- Validator.IsObjCIvarLookup = IsArrow;
+ auto Validator = llvm::make_unique<DeclFilterCCC<ObjCIvarDecl>>();
+ Validator->IsObjCIvarLookup = IsArrow;
if (TypoCorrection Corrected = S.CorrectTypo(
R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr,
- Validator, Sema::CTK_ErrorRecovery, IDecl)) {
+ std::move(Validator), Sema::CTK_ErrorRecovery, IDecl)) {
IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();
S.diagnoseTypo(
Corrected,
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 500233203c79..9c3b51c623d3 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -944,7 +944,11 @@ ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
return ExprError();
std::string Str;
- Context.getObjCEncodingForType(EncodedType, Str);
+ QualType NotEncodedT;
+ Context.getObjCEncodingForType(EncodedType, Str, nullptr, &NotEncodedT);
+ if (!NotEncodedT.isNull())
+ Diag(AtLoc, diag::warn_incomplete_encoded_type)
+ << EncodedType << NotEncodedT;
// The type of @encode is the same as the type of the corresponding string,
// which is an array type.
@@ -983,7 +987,7 @@ static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,
ObjCMethodList *M = &MethList;
bool Warned = false;
for (M = M->getNext(); M; M=M->getNext()) {
- ObjCMethodDecl *MatchingMethodDecl = M->Method;
+ ObjCMethodDecl *MatchingMethodDecl = M->getMethod();
if (MatchingMethodDecl == Method ||
isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext()) ||
MatchingMethodDecl->getSelector() != Method->getSelector())
@@ -1086,6 +1090,7 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
case OMF_mutableCopy:
case OMF_new:
case OMF_self:
+ case OMF_initialize:
case OMF_performSelector:
break;
}
@@ -1105,6 +1110,8 @@ ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
return true;
}
+ if (PDecl->hasDefinition())
+ PDecl = PDecl->getDefinition();
QualType Ty = Context.getObjCProtoType();
if (Ty.isNull())
@@ -1222,12 +1229,8 @@ void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) {
// 'instancetype'.
if (const ObjCMethodDecl *overridden =
findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) {
- SourceLocation loc;
- SourceRange range;
- if (TypeSourceInfo *TSI = overridden->getReturnTypeSourceInfo()) {
- range = TSI->getTypeLoc().getSourceRange();
- loc = range.getBegin();
- }
+ SourceRange range = overridden->getReturnTypeSourceRange();
+ SourceLocation loc = range.getBegin();
if (loc.isInvalid())
loc = overridden->getLocation();
Diag(loc, diag::note_related_result_type_explicit)
@@ -1276,6 +1279,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
ObjCMethodDecl *Method,
bool isClassMessage, bool isSuperMessage,
SourceLocation lbrac, SourceLocation rbrac,
+ SourceRange RecRange,
QualType &ReturnType, ExprValueKind &VK) {
SourceLocation SelLoc;
if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
@@ -1317,9 +1321,12 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
: diag::warn_instance_method_not_found_with_typo;
Selector MatchedSel = OMD->getSelector();
SourceRange SelectorRange(SelectorLocs.front(), SelectorLocs.back());
- Diag(SelLoc, DiagID)
- << Sel<< isClassMessage << MatchedSel
- << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());
+ if (MatchedSel.isUnarySelector())
+ Diag(SelLoc, DiagID)
+ << Sel<< isClassMessage << MatchedSel
+ << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());
+ else
+ Diag(SelLoc, DiagID) << Sel<< isClassMessage << MatchedSel;
}
else
Diag(SelLoc, DiagID)
@@ -1327,9 +1334,15 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
SelectorLocs.back());
// Find the class to which we are sending this message.
if (ReceiverType->isObjCObjectPointerType()) {
- if (ObjCInterfaceDecl *Class =
- ReceiverType->getAs<ObjCObjectPointerType>()->getInterfaceDecl())
- Diag(Class->getLocation(), diag::note_receiver_class_declared);
+ if (ObjCInterfaceDecl *ThisClass =
+ ReceiverType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()) {
+ Diag(ThisClass->getLocation(), diag::note_receiver_class_declared);
+ if (!RecRange.isInvalid())
+ if (ThisClass->lookupClassMethod(Sel))
+ Diag(RecRange.getBegin(),diag::note_receiver_expr_here)
+ << FixItHint::CreateReplacement(RecRange,
+ ThisClass->getNameAsString());
+ }
}
}
@@ -1400,7 +1413,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
param);
- ExprResult ArgE = PerformCopyInitialization(Entity, SelLoc, argExpr);
+ ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), argExpr);
if (ArgE.isInvalid())
IsError = true;
else
@@ -1434,7 +1447,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
// Do additional checkings on method.
IsError |= CheckObjCMethodCall(
- Method, SelLoc, makeArrayRef<const Expr *>(Args.data(), Args.size()));
+ Method, SelLoc, makeArrayRef(Args.data(), Args.size()));
return IsError;
}
@@ -1651,6 +1664,22 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
return ExprError();
+ // Special warning if member name used in a property-dot for a setter accessor
+ // does not use a property with same name; e.g. obj.X = ... for a property with
+ // name 'x'.
+ if (Setter && Setter->isImplicit() && Setter->isPropertyAccessor()
+ && !IFace->FindPropertyDeclaration(Member)) {
+ if (const ObjCPropertyDecl *PDecl = Setter->findPropertyDecl()) {
+ // Do not warn if user is using property-dot syntax to make call to
+ // user named setter.
+ if (!(PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter))
+ Diag(MemberLoc,
+ diag::warn_property_access_suggest)
+ << MemberName << QualType(OPT, 0) << PDecl->getName()
+ << FixItHint::CreateReplacement(MemberLoc, PDecl->getName());
+ }
+ }
+
if (Getter || Setter) {
if (Super)
return new (Context)
@@ -1664,10 +1693,11 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
}
// Attempt to correct for typos in property names.
- DeclFilterCCC<ObjCPropertyDecl> Validator;
- if (TypoCorrection Corrected = CorrectTypo(
- DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName,
- nullptr, nullptr, Validator, CTK_ErrorRecovery, IFace, false, OPT)) {
+ if (TypoCorrection Corrected =
+ CorrectTypo(DeclarationNameInfo(MemberName, MemberLoc),
+ LookupOrdinaryName, nullptr, nullptr,
+ llvm::make_unique<DeclFilterCCC<ObjCPropertyDecl>>(),
+ CTK_ErrorRecovery, IFace, false, OPT)) {
diagnoseTypo(Corrected, PDiag(diag::err_property_not_found_suggest)
<< MemberName << QualType(OPT, 0));
DeclarationName TypoResult = Corrected.getCorrection();
@@ -1892,11 +1922,10 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
}
}
- ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl());
- if (TypoCorrection Corrected =
- CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S,
- nullptr, Validator, CTK_ErrorRecovery, nullptr, false,
- nullptr, false)) {
+ if (TypoCorrection Corrected = CorrectTypo(
+ Result.getLookupNameInfo(), Result.getLookupKind(), S, nullptr,
+ llvm::make_unique<ObjCInterfaceOrSuperCCC>(getCurMethodDecl()),
+ CTK_ErrorRecovery, nullptr, false, nullptr, false)) {
if (Corrected.isKeyword()) {
// If we've found the keyword "super" (the only keyword that would be
// returned by CorrectTypo), this is a send to super.
@@ -2034,6 +2063,45 @@ static void checkCocoaAPI(Sema &S, const ObjCMessageExpr *Msg) {
edit::rewriteObjCRedundantCallWithLiteral);
}
+/// \brief Diagnose use of %s directive in an NSString which is being passed
+/// as formatting string to formatting method.
+static void
+DiagnoseCStringFormatDirectiveInObjCAPI(Sema &S,
+ ObjCMethodDecl *Method,
+ Selector Sel,
+ Expr **Args, unsigned NumArgs) {
+ unsigned Idx = 0;
+ bool Format = false;
+ ObjCStringFormatFamily SFFamily = Sel.getStringFormatFamily();
+ if (SFFamily == ObjCStringFormatFamily::SFF_NSString) {
+ Idx = 0;
+ Format = true;
+ }
+ else if (Method) {
+ for (const auto *I : Method->specific_attrs<FormatAttr>()) {
+ if (S.GetFormatNSStringIdx(I, Idx)) {
+ Format = true;
+ break;
+ }
+ }
+ }
+ if (!Format || NumArgs <= Idx)
+ return;
+
+ Expr *FormatExpr = Args[Idx];
+ if (ObjCStringLiteral *OSL =
+ dyn_cast<ObjCStringLiteral>(FormatExpr->IgnoreParenImpCasts())) {
+ StringLiteral *FormatString = OSL->getString();
+ if (S.FormatStringHasSArg(FormatString)) {
+ S.Diag(FormatExpr->getExprLoc(), diag::warn_objc_cdirective_format_string)
+ << "%s" << 0 << 0;
+ if (Method)
+ S.Diag(Method->getLocation(), diag::note_method_declared_at)
+ << Method->getDeclName();
+ }
+ }
+}
+
/// \brief Build an Objective-C class message expression.
///
/// This routine takes care of both normal class messages and
@@ -2146,7 +2214,8 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs),
Sel, SelectorLocs,
Method, true,
- SuperLoc.isValid(), LBracLoc, RBracLoc,
+ SuperLoc.isValid(), LBracLoc, RBracLoc,
+ SourceRange(),
ReturnType, VK))
return ExprError();
@@ -2154,7 +2223,32 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
RequireCompleteType(LBracLoc, Method->getReturnType(),
diag::err_illegal_message_expr_incomplete_type))
return ExprError();
-
+
+ // Warn about explicit call of +initialize on its own class. But not on 'super'.
+ if (Method && Method->getMethodFamily() == OMF_initialize) {
+ if (!SuperLoc.isValid()) {
+ const ObjCInterfaceDecl *ID =
+ dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext());
+ if (ID == Class) {
+ Diag(Loc, diag::warn_direct_initialize_call);
+ Diag(Method->getLocation(), diag::note_method_declared_at)
+ << Method->getDeclName();
+ }
+ }
+ else if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
+ // [super initialize] is allowed only within an +initialize implementation
+ if (CurMeth->getMethodFamily() != OMF_initialize) {
+ Diag(Loc, diag::warn_direct_super_initialize_call);
+ Diag(Method->getLocation(), diag::note_method_declared_at)
+ << Method->getDeclName();
+ Diag(CurMeth->getLocation(), diag::note_method_declared_at)
+ << CurMeth->getDeclName();
+ }
+ }
+ }
+
+ DiagnoseCStringFormatDirectiveInObjCAPI(*this, Method, Sel, Args, NumArgs);
+
// Construct the appropriate ObjCMessageExpr.
ObjCMessageExpr *Result;
if (SuperLoc.isValid())
@@ -2354,11 +2448,19 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
Method = LookupFactoryMethodInGlobalPool(Sel,
SourceRange(LBracLoc,RBracLoc),
receiverIsId);
+ if (Method) {
+ if (ObjCMethodDecl *BestMethod =
+ SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod()))
+ Method = BestMethod;
+ if (!AreMultipleMethodsInGlobalPool(Sel, Method->isInstanceMethod()))
+ DiagnoseUseOfDecl(Method, SelLoc);
+ }
} else if (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType()) {
// Handle messages to Class.
- // We allow sending a message to a qualified Class ("Class<foo>"), which
- // is ok as long as one of the protocols implements the selector (if not, warn).
+ // We allow sending a message to a qualified Class ("Class<foo>"), which
+ // is ok as long as one of the protocols implements the selector (if not,
+ // warn).
if (const ObjCObjectPointerType *QClassTy
= ReceiverType->getAsObjCQualifiedClassType()) {
// Search protocols for class methods.
@@ -2405,6 +2507,10 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
<< Sel << SourceRange(LBracLoc, RBracLoc);
}
}
+ if (Method)
+ if (ObjCMethodDecl *BestMethod =
+ SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod()))
+ Method = BestMethod;
}
}
}
@@ -2543,7 +2649,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs),
Sel, SelectorLocs, Method,
ClassMessage, SuperLoc.isValid(),
- LBracLoc, RBracLoc, ReturnType, VK))
+ LBracLoc, RBracLoc, RecRange, ReturnType, VK))
return ExprError();
if (Method && !Method->getReturnType()->isVoidType() &&
@@ -2568,6 +2674,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
case OMF_mutableCopy:
case OMF_new:
case OMF_self:
+ case OMF_initialize:
break;
case OMF_dealloc:
@@ -2630,6 +2737,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
}
}
+ DiagnoseCStringFormatDirectiveInObjCAPI(*this, Method, Sel, Args, NumArgs);
+
// Construct the appropriate ObjCMessageExpr instance.
ObjCMessageExpr *Result;
if (SuperLoc.isValid())
@@ -3296,6 +3405,9 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr,
if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
HadTheAttribute = true;
+ if (Parm->isStr("id"))
+ return true;
+
NamedDecl *Target = nullptr;
// Check for an existing type with this name.
LookupResult R(S, DeclarationName(Parm), SourceLocation(),
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 06ca9aed6a87..569ef307474f 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -466,11 +466,15 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
// members in the aggregate, then each member not explicitly initialized
// shall be initialized from its brace-or-equal-initializer [...]
if (Field->hasInClassInitializer()) {
- Expr *DIE = CXXDefaultInitExpr::Create(SemaRef.Context, Loc, Field);
+ ExprResult DIE = SemaRef.BuildCXXDefaultInitExpr(Loc, Field);
+ if (DIE.isInvalid()) {
+ hadError = true;
+ return;
+ }
if (Init < NumInits)
- ILE->setInit(Init, DIE);
+ ILE->setInit(Init, DIE.get());
else {
- ILE->updateInit(SemaRef.Context, Init, DIE);
+ ILE->updateInit(SemaRef.Context, Init, DIE.get());
RequiresSecondPass = true;
}
return;
@@ -1555,10 +1559,11 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
}
}
- // Value-initialize the first named member of the union.
+ // Value-initialize the first member of the union that isn't an unnamed
+ // bitfield.
for (RecordDecl::field_iterator FieldEnd = RD->field_end();
Field != FieldEnd; ++Field) {
- if (Field->getDeclName()) {
+ if (!Field->isUnnamedBitfield()) {
if (VerifyOnly)
CheckEmptyInitializable(
InitializedEntity::InitializeMember(*Field, &Entity),
@@ -1734,24 +1739,6 @@ static void ExpandAnonymousFieldDesignator(Sema &SemaRef,
&Replacements[0] + Replacements.size());
}
-/// \brief Given an implicit anonymous field, search the IndirectField that
-/// corresponds to FieldName.
-static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField,
- IdentifierInfo *FieldName) {
- if (!FieldName)
- return nullptr;
-
- assert(AnonField->isAnonymousStructOrUnion());
- Decl *NextDecl = AnonField->getNextDeclInContext();
- while (IndirectFieldDecl *IF =
- dyn_cast_or_null<IndirectFieldDecl>(NextDecl)) {
- if (FieldName == IF->getAnonField()->getIdentifier())
- return IF;
- NextDecl = NextDecl->getNextDeclInContext();
- }
- return nullptr;
-}
-
static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef,
DesignatedInitExpr *DIE) {
unsigned NumIndexExprs = DIE->getNumSubExprs() - 1;
@@ -1892,103 +1879,76 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
return true;
}
- // Note: we perform a linear search of the fields here, despite
- // the fact that we have a faster lookup method, because we always
- // need to compute the field's index.
FieldDecl *KnownField = D->getField();
- IdentifierInfo *FieldName = D->getFieldName();
- unsigned FieldIndex = 0;
- RecordDecl::field_iterator
- Field = RT->getDecl()->field_begin(),
- FieldEnd = RT->getDecl()->field_end();
- for (; Field != FieldEnd; ++Field) {
- if (Field->isUnnamedBitfield())
- continue;
-
- // If we find a field representing an anonymous field, look in the
- // IndirectFieldDecl that follow for the designated initializer.
- if (!KnownField && Field->isAnonymousStructOrUnion()) {
- if (IndirectFieldDecl *IF =
- FindIndirectFieldDesignator(*Field, FieldName)) {
+ if (!KnownField) {
+ IdentifierInfo *FieldName = D->getFieldName();
+ DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
+ for (NamedDecl *ND : Lookup) {
+ if (auto *FD = dyn_cast<FieldDecl>(ND)) {
+ KnownField = FD;
+ break;
+ }
+ if (auto *IFD = dyn_cast<IndirectFieldDecl>(ND)) {
// In verify mode, don't modify the original.
if (VerifyOnly)
DIE = CloneDesignatedInitExpr(SemaRef, DIE);
- ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IF);
+ ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IFD);
D = DIE->getDesignator(DesigIdx);
+ KnownField = cast<FieldDecl>(*IFD->chain_begin());
break;
}
}
- if (KnownField && KnownField == *Field)
- break;
- if (FieldName && FieldName == Field->getIdentifier())
- break;
-
- ++FieldIndex;
- }
+ if (!KnownField) {
+ if (VerifyOnly) {
+ ++Index;
+ return true; // No typo correction when just trying this out.
+ }
- if (Field == FieldEnd) {
- if (VerifyOnly) {
- ++Index;
- return true; // No typo correction when just trying this out.
- }
+ // Name lookup found something, but it wasn't a field.
+ if (!Lookup.empty()) {
+ SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
+ << FieldName;
+ SemaRef.Diag(Lookup.front()->getLocation(),
+ diag::note_field_designator_found);
+ ++Index;
+ return true;
+ }
- // There was no normal field in the struct with the designated
- // name. Perform another lookup for this name, which may find
- // something that we can't designate (e.g., a member function),
- // may find nothing, or may find a member of an anonymous
- // struct/union.
- DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
- FieldDecl *ReplacementField = nullptr;
- if (Lookup.empty()) {
- // Name lookup didn't find anything. Determine whether this
- // was a typo for another field name.
- FieldInitializerValidatorCCC Validator(RT->getDecl());
+ // Name lookup didn't find anything.
+ // Determine whether this was a typo for another field name.
if (TypoCorrection Corrected = SemaRef.CorrectTypo(
DeclarationNameInfo(FieldName, D->getFieldLoc()),
- Sema::LookupMemberName, /*Scope=*/ nullptr, /*SS=*/ nullptr,
- Validator, Sema::CTK_ErrorRecovery, RT->getDecl())) {
+ Sema::LookupMemberName, /*Scope=*/nullptr, /*SS=*/nullptr,
+ llvm::make_unique<FieldInitializerValidatorCCC>(RT->getDecl()),
+ Sema::CTK_ErrorRecovery, RT->getDecl())) {
SemaRef.diagnoseTypo(
Corrected,
SemaRef.PDiag(diag::err_field_designator_unknown_suggest)
- << FieldName << CurrentObjectType);
- ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>();
+ << FieldName << CurrentObjectType);
+ KnownField = Corrected.getCorrectionDeclAs<FieldDecl>();
hadError = true;
} else {
+ // Typo correction didn't find anything.
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
<< FieldName << CurrentObjectType;
++Index;
return true;
}
}
+ }
- if (!ReplacementField) {
- // Name lookup found something, but it wasn't a field.
- SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
- << FieldName;
- SemaRef.Diag(Lookup.front()->getLocation(),
- diag::note_field_designator_found);
- ++Index;
- return true;
- }
-
- if (!KnownField) {
- // The replacement field comes from typo correction; find it
- // in the list of fields.
- FieldIndex = 0;
- Field = RT->getDecl()->field_begin();
- for (; Field != FieldEnd; ++Field) {
- if (Field->isUnnamedBitfield())
- continue;
-
- if (ReplacementField == *Field ||
- Field->getIdentifier() == ReplacementField->getIdentifier())
- break;
-
- ++FieldIndex;
- }
- }
+ unsigned FieldIndex = 0;
+ for (auto *FI : RT->getDecl()->fields()) {
+ if (FI->isUnnamedBitfield())
+ continue;
+ if (KnownField == FI)
+ break;
+ ++FieldIndex;
}
+ RecordDecl::field_iterator Field =
+ RecordDecl::field_iterator(DeclContext::decl_iterator(KnownField));
+
// All of the fields of a union are located at the same place in
// the initializer list.
if (RT->getDecl()->isUnion()) {
@@ -5537,18 +5497,18 @@ static void performLifetimeExtension(Expr *Init,
static bool
performReferenceExtension(Expr *Init,
const InitializedEntity *ExtendingEntity) {
- if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
- if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
- // This is just redundant braces around an initializer. Step over it.
- Init = ILE->getInit(0);
- }
- }
-
// Walk past any constructs which we can lifetime-extend across.
Expr *Old;
do {
Old = Init;
+ if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
+ if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
+ // This is just redundant braces around an initializer. Step over it.
+ Init = ILE->getInit(0);
+ }
+ }
+
// Step over any subobject adjustments; we may have a materialized
// temporary inside them.
SmallVector<const Expr *, 2> CommaLHSs;
@@ -6476,12 +6436,45 @@ static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
return diagnoseListInit(S, HiddenArray, InitList);
}
+ if (DestType->isReferenceType()) {
+ // A list-initialization failure for a reference means that we tried to
+ // create a temporary of the inner type (per [dcl.init.list]p3.6) and the
+ // inner initialization failed.
+ QualType T = DestType->getAs<ReferenceType>()->getPointeeType();
+ diagnoseListInit(S, InitializedEntity::InitializeTemporary(T), InitList);
+ SourceLocation Loc = InitList->getLocStart();
+ if (auto *D = Entity.getDecl())
+ Loc = D->getLocation();
+ S.Diag(Loc, diag::note_in_reference_temporary_list_initializer) << T;
+ return;
+ }
+
InitListChecker DiagnoseInitList(S, Entity, InitList, DestType,
/*VerifyOnly=*/false);
assert(DiagnoseInitList.HadError() &&
"Inconsistent init list check result.");
}
+/// Prints a fixit for adding a null initializer for |Entity|. Call this only
+/// right after emitting a diagnostic.
+static void maybeEmitZeroInitializationFixit(Sema &S,
+ InitializationSequence &Sequence,
+ const InitializedEntity &Entity) {
+ if (Entity.getKind() != InitializedEntity::EK_Variable)
+ return;
+
+ VarDecl *VD = cast<VarDecl>(Entity.getDecl());
+ if (VD->getInit() || VD->getLocEnd().isMacroID())
+ return;
+
+ QualType VariableTy = VD->getType().getCanonicalType();
+ SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd());
+ std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
+
+ S.Diag(Loc, diag::note_add_initializer)
+ << VD << FixItHint::CreateInsertion(Loc, Init);
+}
+
bool InitializationSequence::Diagnose(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -6812,7 +6805,8 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Entity.getName();
} else {
S.Diag(Kind.getLocation(), diag::err_default_init_const)
- << DestType << (bool)DestType->getAs<RecordType>();
+ << DestType << (bool)DestType->getAs<RecordType>();
+ maybeEmitZeroInitializationFixit(S, *this, Entity);
}
break;
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 0cf4ed7c6081..90a81f4ec452 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -617,7 +617,7 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
// If it was ever a placeholder, it had to been deduced to DependentTy.
assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType());
- // C++ Core Issue #975, proposed resolution:
+ // C++ core issue 975:
// If a lambda-expression does not include a trailing-return-type,
// it is as if the trailing-return-type denotes the following type:
// - if there are no return statements in the compound-statement,
@@ -631,6 +631,10 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
// same, that common type;
// - otherwise, the program is ill-formed.
//
+ // C++ core issue 1048 additionally removes top-level cv-qualifiers
+ // from the types of returned expressions to match the C++14 auto
+ // deduction rules.
+ //
// In addition, in blocks in non-C++ modes, if all of the return
// statements are enumerator-like expressions of some type T, where
// T has a name for linkage, then we infer the return type of the
@@ -679,7 +683,8 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
const ReturnStmt *RS = *I;
const Expr *RetE = RS->getRetValue();
- QualType ReturnType = (RetE ? RetE->getType() : Context.VoidTy);
+ QualType ReturnType =
+ (RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType();
if (Context.hasSameType(ReturnType, CSI.ReturnType))
continue;
@@ -873,7 +878,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// We don't do this before C++1y, because we don't support deduced return
// types there.
QualType DefaultTypeForNoTrailingReturn =
- getLangOpts().CPlusPlus1y ? Context.getAutoDeductType()
+ getLangOpts().CPlusPlus14 ? Context.getAutoDeductType()
: Context.DependentTy;
QualType MethodTy =
Context.getFunctionType(DefaultTypeForNoTrailingReturn, None, EPI);
@@ -999,7 +1004,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
VarDecl *Var = nullptr;
if (C->Init.isUsable()) {
- Diag(C->Loc, getLangOpts().CPlusPlus1y
+ Diag(C->Loc, getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_init_capture
: diag::ext_init_capture);
@@ -1049,8 +1054,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
if (R.empty()) {
// FIXME: Disable corrections that would add qualification?
CXXScopeSpec ScopeSpec;
- DeclFilterCCC<VarDecl> Validator;
- if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator))
+ if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R,
+ llvm::make_unique<DeclFilterCCC<VarDecl>>()))
continue;
}
@@ -1062,7 +1067,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// C++11 [expr.prim.lambda]p8:
// An identifier or this shall not appear more than once in a
// lambda-capture.
- if (!CaptureNames.insert(C->Id)) {
+ if (!CaptureNames.insert(C->Id).second) {
if (Var && LSI->isCaptured(Var)) {
Diag(C->Loc, diag::err_capture_more_than_once)
<< C->Id << SourceRange(LSI->getCapture(Var).getLocation())
@@ -1414,6 +1419,12 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
/*isImplicit=*/true));
continue;
}
+ if (From.isVLATypeCapture()) {
+ Captures.push_back(
+ LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType));
+ CaptureInits.push_back(nullptr);
+ continue;
+ }
VarDecl *Var = From.getVariable();
LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef;
@@ -1451,7 +1462,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
// different machinery.
// FIXME: Refactor and Merge the return type deduction machinery.
// FIXME: Assumes current resolution to core issue 975.
- if (LSI->HasImplicitReturnType && !getLangOpts().CPlusPlus1y) {
+ if (LSI->HasImplicitReturnType && !getLangOpts().CPlusPlus14) {
deduceClosureReturnType(*LSI);
// - if there are no return statements in the
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index fe2c8161b871..3445264461f7 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -128,7 +128,7 @@ namespace {
// that contexts be visited from the inside out in order to get
// the effective DCs right.
void visit(DeclContext *DC, DeclContext *EffectiveDC) {
- if (!visited.insert(DC))
+ if (!visited.insert(DC).second)
return;
addUsingDirectives(DC, EffectiveDC);
@@ -139,7 +139,7 @@ namespace {
// were declared in the effective DC.
void visit(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) {
DeclContext *NS = UD->getNominatedNamespace();
- if (!visited.insert(NS))
+ if (!visited.insert(NS).second)
return;
addUsingDirective(UD, EffectiveDC);
@@ -154,7 +154,7 @@ namespace {
while (true) {
for (auto UD : DC->using_directives()) {
DeclContext *NS = UD->getNominatedNamespace();
- if (visited.insert(NS)) {
+ if (visited.insert(NS).second) {
addUsingDirective(UD, EffectiveDC);
queue.push_back(NS);
}
@@ -285,7 +285,7 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
}
void LookupResult::configure() {
- IDNS = getIDNS(LookupKind, SemaRef.getLangOpts().CPlusPlus,
+ IDNS = getIDNS(LookupKind, getSema().getLangOpts().CPlusPlus,
isForRedeclaration());
// If we're looking for one of the allocation or deallocation
@@ -296,7 +296,7 @@ void LookupResult::configure() {
case OO_Delete:
case OO_Array_New:
case OO_Array_Delete:
- SemaRef.DeclareGlobalNewDelete();
+ getSema().DeclareGlobalNewDelete();
break;
default:
@@ -307,7 +307,7 @@ void LookupResult::configure() {
// up being declared.
if (IdentifierInfo *Id = NameInfo.getName().getAsIdentifierInfo()) {
if (unsigned BuiltinID = Id->getBuiltinID()) {
- if (!SemaRef.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+ if (!getSema().Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
AllowHidden = true;
}
}
@@ -400,8 +400,8 @@ void LookupResult::resolveKind() {
// canonical type.
if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
if (!TD->getDeclContext()->isRecord()) {
- QualType T = SemaRef.Context.getTypeDeclType(TD);
- if (!UniqueTypes.insert(SemaRef.Context.getCanonicalType(T))) {
+ QualType T = getSema().Context.getTypeDeclType(TD);
+ if (!UniqueTypes.insert(getSema().Context.getCanonicalType(T)).second) {
// The type is not unique; pull something off the back and continue
// at this index.
Decls[I] = Decls[--N];
@@ -410,7 +410,7 @@ void LookupResult::resolveKind() {
}
}
- if (!Unique.insert(D)) {
+ if (!Unique.insert(D).second) {
// If it's not unique, pull something off the back (and
// continue at this index).
Decls[I] = Decls[--N];
@@ -735,8 +735,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
// FIXME: Calling convention!
FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo();
EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_C);
- EPI.ExceptionSpecType = EST_None;
- EPI.NumExceptions = 0;
+ EPI.ExceptionSpec = EST_None;
QualType ExpectedType
= R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(),
None, EPI);
@@ -1176,21 +1175,8 @@ static Module *getDefiningModule(Decl *Entity) {
if (FunctionDecl *Pattern = FD->getTemplateInstantiationPattern())
Entity = Pattern;
} else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Entity)) {
- // If it's a class template specialization, find the template or partial
- // specialization from which it was instantiated.
- if (ClassTemplateSpecializationDecl *SpecRD =
- dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
- llvm::PointerUnion<ClassTemplateDecl*,
- ClassTemplatePartialSpecializationDecl*> From =
- SpecRD->getInstantiatedFrom();
- if (ClassTemplateDecl *FromTemplate = From.dyn_cast<ClassTemplateDecl*>())
- Entity = FromTemplate->getTemplatedDecl();
- else if (From)
- Entity = From.get<ClassTemplatePartialSpecializationDecl*>();
- // Otherwise, it's an explicit specialization.
- } else if (MemberSpecializationInfo *MSInfo =
- RD->getMemberSpecializationInfo())
- Entity = getInstantiatedFrom(RD, MSInfo);
+ if (CXXRecordDecl *Pattern = RD->getTemplateInstantiationPattern())
+ Entity = Pattern;
} else if (EnumDecl *ED = dyn_cast<EnumDecl>(Entity)) {
if (MemberSpecializationInfo *MSInfo = ED->getMemberSpecializationInfo())
Entity = getInstantiatedFrom(ED, MSInfo);
@@ -1279,7 +1265,7 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
}
NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
- return findAcceptableDecl(SemaRef, D);
+ return findAcceptableDecl(getSema(), D);
}
/// @brief Perform unqualified name lookup starting from a given
@@ -1466,7 +1452,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
// with its using-children.
for (auto *I : UsingDirectives) {
NamespaceDecl *ND = I->getNominatedNamespace()->getOriginalNamespace();
- if (Visited.insert(ND))
+ if (Visited.insert(ND).second)
Queue.push_back(ND);
}
@@ -1514,7 +1500,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
for (auto I : ND->using_directives()) {
NamespaceDecl *Nom = I->getNominatedNamespace();
- if (Visited.insert(Nom))
+ if (Visited.insert(Nom).second)
Queue.push_back(Nom);
}
}
@@ -1776,6 +1762,31 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
return true;
}
+/// \brief Performs qualified name lookup or special type of lookup for
+/// "__super::" scope specifier.
+///
+/// This routine is a convenience overload meant to be called from contexts
+/// that need to perform a qualified name lookup with an optional C++ scope
+/// specifier that might require special kind of lookup.
+///
+/// \param R captures both the lookup criteria and any lookup results found.
+///
+/// \param LookupCtx The context in which qualified name lookup will
+/// search.
+///
+/// \param SS An optional C++ scope-specifier.
+///
+/// \returns true if lookup succeeded, false if it failed.
+bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
+ CXXScopeSpec &SS) {
+ auto *NNS = SS.getScopeRep();
+ if (NNS && NNS->getKind() == NestedNameSpecifier::Super)
+ return LookupInSuper(R, NNS->getAsRecordDecl());
+ else
+
+ return LookupQualifiedName(R, LookupCtx);
+}
+
/// @brief Performs name lookup for a name that was parsed in the
/// source code, and may contain a C++ scope specifier.
///
@@ -1783,7 +1794,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
/// contexts that receive a name and an optional C++ scope specifier
/// (e.g., "N::M::x"). It will then perform either qualified or
/// unqualified name lookup (with LookupQualifiedName or LookupName,
-/// respectively) on the given name and return those results.
+/// respectively) on the given name and return those results. It will
+/// perform a special type of lookup for "__super::" scope specifier.
///
/// @param S The scope from which unqualified name lookup will
/// begin.
@@ -1803,6 +1815,10 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
}
if (SS && SS->isSet()) {
+ NestedNameSpecifier *NNS = SS->getScopeRep();
+ if (NNS->getKind() == NestedNameSpecifier::Super)
+ return LookupInSuper(R, NNS->getAsRecordDecl());
+
if (DeclContext *DC = computeDeclContext(*SS, EnteringContext)) {
// We have resolved the scope specifier to a particular declaration
// contex, and will perform name lookup in that context.
@@ -1825,6 +1841,30 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
return LookupName(R, S, AllowBuiltinCreation);
}
+/// \brief Perform qualified name lookup into all base classes of the given
+/// class.
+///
+/// \param R captures both the lookup criteria and any lookup results found.
+///
+/// \param Class The context in which qualified name lookup will
+/// search. Name lookup will search in all base classes merging the results.
+///
+/// @returns True if any decls were found (but possibly ambiguous)
+bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) {
+ for (const auto &BaseSpec : Class->bases()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(
+ BaseSpec.getType()->castAs<RecordType>()->getDecl());
+ LookupResult Result(*this, R.getLookupNameInfo(), R.getLookupKind());
+ Result.setBaseObjectType(Context.getRecordType(Class));
+ LookupQualifiedName(Result, RD);
+ for (auto *Decl : Result)
+ R.addDecl(Decl);
+ }
+
+ R.resolveKind();
+
+ return !R.empty();
+}
/// \brief Produce a diagnostic describing the ambiguity that resulted
/// from name lookup.
@@ -2024,7 +2064,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
// 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))
+ if (!Result.Classes.insert(Class).second)
return;
// -- If T is a template-id, its associated namespaces and classes are
@@ -2073,7 +2113,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
if (!BaseType)
continue;
CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl());
- if (Result.Classes.insert(BaseDecl)) {
+ if (Result.Classes.insert(BaseDecl).second) {
// Find the associated namespace for this base class.
DeclContext *BaseCtx = BaseDecl->getDeclContext();
CollectEnclosingNamespace(Result.Namespaces, BaseCtx);
@@ -2875,7 +2915,7 @@ public:
/// \brief Determine whether we have already visited this context
/// (and, if not, note that we are going to visit that context now).
bool visitedContext(DeclContext *Ctx) {
- return !VisitedContexts.insert(Ctx);
+ return !VisitedContexts.insert(Ctx).second;
}
bool alreadyVisitedContext(DeclContext *Ctx) {
@@ -3263,6 +3303,49 @@ static void LookupPotentialTypoResult(Sema &SemaRef,
bool isObjCIvarLookup,
bool FindHidden);
+/// \brief Check whether the declarations found for a typo correction are
+/// visible, and if none of them are, convert the correction to an 'import
+/// a module' correction.
+static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
+ if (TC.begin() == TC.end())
+ return;
+
+ TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end();
+
+ for (/**/; DI != DE; ++DI)
+ if (!LookupResult::isVisible(SemaRef, *DI))
+ break;
+ // Nothing to do if all decls are visible.
+ if (DI == DE)
+ return;
+
+ llvm::SmallVector<NamedDecl*, 4> NewDecls(TC.begin(), DI);
+ bool AnyVisibleDecls = !NewDecls.empty();
+
+ for (/**/; DI != DE; ++DI) {
+ NamedDecl *VisibleDecl = *DI;
+ if (!LookupResult::isVisible(SemaRef, *DI))
+ VisibleDecl = findAcceptableDecl(SemaRef, *DI);
+
+ if (VisibleDecl) {
+ if (!AnyVisibleDecls) {
+ // Found a visible decl, discard all hidden ones.
+ AnyVisibleDecls = true;
+ NewDecls.clear();
+ }
+ NewDecls.push_back(VisibleDecl);
+ } else if (!AnyVisibleDecls && !(*DI)->isModulePrivate())
+ NewDecls.push_back(*DI);
+ }
+
+ if (NewDecls.empty())
+ TC = TypoCorrection();
+ else {
+ TC.setCorrectionDecls(NewDecls);
+ TC.setRequiresImport(!AnyVisibleDecls);
+ }
+}
+
// Fill the supplied vector with the IdentifierInfo pointers for each piece of
// the given NestedNameSpecifier (i.e. given a NestedNameSpecifier "foo::bar::",
// fill the vector with the IdentifierInfo pointers for "foo" and "bar").
@@ -3297,6 +3380,7 @@ static void getNestedNameSpecifierIdentifiers(
break;
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
return;
}
@@ -3304,157 +3388,6 @@ static void getNestedNameSpecifierIdentifiers(
Identifiers.push_back(II);
}
-namespace {
-
-static const unsigned MaxTypoDistanceResultSets = 5;
-
-class TypoCorrectionConsumer : public VisibleDeclConsumer {
- typedef SmallVector<TypoCorrection, 1> TypoResultList;
- typedef llvm::StringMap<TypoResultList> TypoResultsMap;
- typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
-
-public:
- explicit TypoCorrectionConsumer(Sema &SemaRef,
- const DeclarationNameInfo &TypoName,
- Sema::LookupNameKind LookupKind,
- Scope *S, CXXScopeSpec *SS,
- CorrectionCandidateCallback &CCC,
- DeclContext *MemberContext,
- bool EnteringContext)
- : Typo(TypoName.getName().getAsIdentifierInfo()), SemaRef(SemaRef), S(S),
- SS(SS), CorrectionValidator(CCC), MemberContext(MemberContext),
- Result(SemaRef, TypoName, LookupKind),
- Namespaces(SemaRef.Context, SemaRef.CurContext, SS),
- EnteringContext(EnteringContext), SearchNamespaces(false) {
- Result.suppressDiagnostics();
- }
-
- bool includeHiddenDecls() const override { return true; }
-
- // Methods for adding potential corrections to the consumer.
- void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
- bool InBaseClass) override;
- void FoundName(StringRef Name);
- void addKeywordResult(StringRef Keyword);
- void addCorrection(TypoCorrection Correction);
-
- bool empty() const { return CorrectionResults.empty(); }
-
- /// \brief Return the list of TypoCorrections for the given identifier from
- /// the set of corrections that have the closest edit distance, if any.
- TypoResultList &operator[](StringRef Name) {
- return CorrectionResults.begin()->second[Name];
- }
-
- /// \brief Return the edit distance of the corrections that have the
- /// closest/best edit distance from the original typop.
- unsigned getBestEditDistance(bool Normalized) {
- if (CorrectionResults.empty())
- return (std::numeric_limits<unsigned>::max)();
-
- unsigned BestED = CorrectionResults.begin()->first;
- return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED;
- }
-
- /// \brief Set-up method to add to the consumer the set of namespaces to use
- /// in performing corrections to nested name specifiers. This method also
- /// implicitly adds all of the known classes in the current AST context to the
- /// to the consumer for correcting nested name specifiers.
- void
- addNamespaces(const llvm::MapVector<NamespaceDecl *, bool> &KnownNamespaces);
-
- /// \brief Return the next typo correction that passes all internal filters
- /// and is deemed valid by the consumer's CorrectionCandidateCallback,
- /// starting with the corrections that have the closest edit distance. An
- /// empty TypoCorrection is returned once no more viable corrections remain
- /// in the consumer.
- TypoCorrection getNextCorrection();
-
-private:
- class NamespaceSpecifierSet {
- struct SpecifierInfo {
- DeclContext* DeclCtx;
- NestedNameSpecifier* NameSpecifier;
- unsigned EditDistance;
- };
-
- typedef SmallVector<DeclContext*, 4> DeclContextList;
- typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList;
-
- ASTContext &Context;
- DeclContextList CurContextChain;
- std::string CurNameSpecifier;
- SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers;
- SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers;
- bool isSorted;
-
- SpecifierInfoList Specifiers;
- llvm::SmallSetVector<unsigned, 4> Distances;
- llvm::DenseMap<unsigned, SpecifierInfoList> DistanceMap;
-
- /// \brief Helper for building the list of DeclContexts between the current
- /// context and the top of the translation unit
- static DeclContextList buildContextChain(DeclContext *Start);
-
- void sortNamespaces();
-
- unsigned buildNestedNameSpecifier(DeclContextList &DeclChain,
- NestedNameSpecifier *&NNS);
-
- public:
- NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext,
- CXXScopeSpec *CurScopeSpec);
-
- /// \brief Add the DeclContext (a namespace or record) to the set, computing
- /// the corresponding NestedNameSpecifier and its distance in the process.
- void addNameSpecifier(DeclContext *Ctx);
-
- typedef SpecifierInfoList::iterator iterator;
- iterator begin() {
- if (!isSorted) sortNamespaces();
- return Specifiers.begin();
- }
- iterator end() { return Specifiers.end(); }
- };
-
- void addName(StringRef Name, NamedDecl *ND,
- NestedNameSpecifier *NNS = nullptr, bool isKeyword = false);
-
- /// \brief Find any visible decls for the given typo correction candidate.
- /// If none are found, it to the set of candidates for which qualified lookups
- /// will be performed to find possible nested name specifier changes.
- bool resolveCorrection(TypoCorrection &Candidate);
-
- /// \brief Perform qualified lookups on the queued set of typo correction
- /// candidates and add the nested name specifier changes to each candidate if
- /// a lookup succeeds (at which point the candidate will be returned to the
- /// main pool of potential corrections).
- void performQualifiedLookups();
-
- /// \brief The name written that is a typo in the source.
- IdentifierInfo *Typo;
-
- /// \brief The results found that have the smallest edit distance
- /// found (so far) with the typo name.
- ///
- /// The pointer value being set to the current DeclContext indicates
- /// whether there is a keyword with this name.
- TypoEditDistanceMap CorrectionResults;
-
- Sema &SemaRef;
- Scope *S;
- CXXScopeSpec *SS;
- CorrectionCandidateCallback &CorrectionValidator;
- DeclContext *MemberContext;
- LookupResult Result;
- NamespaceSpecifierSet Namespaces;
- SmallVector<TypoCorrection, 2> QualifiedResults;
- bool EnteringContext;
- bool SearchNamespaces;
-};
-
-}
-
void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
DeclContext *Ctx, bool InBaseClass) {
// Don't consider hidden names for typo correction.
@@ -3506,9 +3439,12 @@ void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND,
TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, ED);
if (isKeyword) TC.makeKeyword();
+ TC.setCorrectionRange(nullptr, Result.getLookupNameInfo());
addCorrection(TC);
}
+static const unsigned MaxTypoDistanceResultSets = 5;
+
void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
StringRef TypoStr = Typo->getName();
StringRef Name = Correction.getCorrectionAsIdentifierInfo()->getName();
@@ -3521,9 +3457,11 @@ void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
return;
// If the correction is resolved but is not viable, ignore it.
- if (Correction.isResolved() &&
- !isCandidateViable(CorrectionValidator, Correction))
- return;
+ if (Correction.isResolved()) {
+ checkCorrectionVisibility(SemaRef, Correction);
+ if (!Correction || !isCandidateViable(*CorrectionValidator, Correction))
+ return;
+ }
TypoResultList &CList =
CorrectionResults[Correction.getEditDistance(false)][Name];
@@ -3577,7 +3515,11 @@ void TypoCorrectionConsumer::addNamespaces(
}
}
-TypoCorrection TypoCorrectionConsumer::getNextCorrection() {
+const TypoCorrection &TypoCorrectionConsumer::getNextCorrection() {
+ if (++CurrentTCIndex < ValidatedCorrections.size())
+ return ValidatedCorrections[CurrentTCIndex];
+
+ CurrentTCIndex = ValidatedCorrections.size();
while (!CorrectionResults.empty()) {
auto DI = CorrectionResults.begin();
if (DI->second.empty()) {
@@ -3593,20 +3535,22 @@ TypoCorrection TypoCorrectionConsumer::getNextCorrection() {
}
TypoCorrection TC = RI->second.pop_back_val();
- if (TC.isResolved() || resolveCorrection(TC))
- return TC;
+ if (TC.isResolved() || TC.requiresImport() || resolveCorrection(TC)) {
+ ValidatedCorrections.push_back(TC);
+ return ValidatedCorrections[CurrentTCIndex];
+ }
}
- return TypoCorrection();
+ return ValidatedCorrections[0]; // The empty correction.
}
bool TypoCorrectionConsumer::resolveCorrection(TypoCorrection &Candidate) {
IdentifierInfo *Name = Candidate.getCorrectionAsIdentifierInfo();
DeclContext *TempMemberContext = MemberContext;
- CXXScopeSpec *TempSS = SS;
+ CXXScopeSpec *TempSS = SS.get();
retry_lookup:
LookupPotentialTypoResult(SemaRef, Result, Name, S, TempSS, TempMemberContext,
EnteringContext,
- CorrectionValidator.IsObjCIvarLookup,
+ CorrectionValidator->IsObjCIvarLookup,
Name == Typo && !Candidate.WillReplaceSpecifier());
switch (Result.getResultKind()) {
case LookupResult::NotFound:
@@ -3620,7 +3564,7 @@ retry_lookup:
}
if (TempMemberContext) {
if (SS && !TempSS)
- TempSS = SS;
+ TempSS = SS.get();
TempMemberContext = nullptr;
goto retry_lookup;
}
@@ -3637,11 +3581,13 @@ retry_lookup:
// Store all of the Decls for overloaded symbols
for (auto *TRD : Result)
Candidate.addCorrectionDecl(TRD);
- if (!isCandidateViable(CorrectionValidator, Candidate)) {
+ checkCorrectionVisibility(SemaRef, Candidate);
+ if (!isCandidateViable(*CorrectionValidator, Candidate)) {
if (SearchNamespaces)
QualifiedResults.push_back(Candidate);
break;
}
+ Candidate.setCorrectionRange(TempSS, Result.getLookupNameInfo());
return true;
}
return false;
@@ -3707,8 +3653,10 @@ void TypoCorrectionConsumer::performQualifiedLookups() {
TRD.getPair()) == Sema::AR_accessible)
TC.addCorrectionDecl(*TRD);
}
- if (TC.isResolved())
+ if (TC.isResolved()) {
+ TC.setCorrectionRange(SS.get(), Result.getLookupNameInfo());
addCorrection(TC);
+ }
break;
}
case LookupResult::NotFound:
@@ -3856,8 +3804,8 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier(
SmallVector<const IdentifierInfo*, 4> NewNameSpecifierIdentifiers;
getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers);
NumSpecifiers = llvm::ComputeEditDistance(
- ArrayRef<const IdentifierInfo *>(CurNameSpecifierIdentifiers),
- ArrayRef<const IdentifierInfo *>(NewNameSpecifierIdentifiers));
+ llvm::makeArrayRef(CurNameSpecifierIdentifiers),
+ llvm::makeArrayRef(NewNameSpecifierIdentifiers));
}
isSorted = false;
@@ -3972,6 +3920,13 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
if (SemaRef.getLangOpts().GNUMode)
Consumer.addKeywordResult("typeof");
+ } else if (CCC.WantFunctionLikeCasts) {
+ static const char *const CastableTypeSpecs[] = {
+ "char", "double", "float", "int", "long", "short",
+ "signed", "unsigned", "void"
+ };
+ for (auto *kw : CastableTypeSpecs)
+ Consumer.addKeywordResult(kw);
}
if (CCC.WantCXXNamedCasts && SemaRef.getLangOpts().CPlusPlus) {
@@ -4063,212 +4018,96 @@ static void AddKeywordsToConsumer(Sema &SemaRef,
}
}
-/// \brief Check whether the declarations found for a typo correction are
-/// visible, and if none of them are, convert the correction to an 'import
-/// a module' correction.
-static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
- if (TC.begin() == TC.end())
- return;
-
- TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end();
-
- for (/**/; DI != DE; ++DI)
- if (!LookupResult::isVisible(SemaRef, *DI))
- break;
- // Nothing to do if all decls are visible.
- if (DI == DE)
- return;
-
- llvm::SmallVector<NamedDecl*, 4> NewDecls(TC.begin(), DI);
- bool AnyVisibleDecls = !NewDecls.empty();
-
- for (/**/; DI != DE; ++DI) {
- NamedDecl *VisibleDecl = *DI;
- if (!LookupResult::isVisible(SemaRef, *DI))
- VisibleDecl = findAcceptableDecl(SemaRef, *DI);
-
- if (VisibleDecl) {
- if (!AnyVisibleDecls) {
- // Found a visible decl, discard all hidden ones.
- AnyVisibleDecls = true;
- NewDecls.clear();
- }
- NewDecls.push_back(VisibleDecl);
- } else if (!AnyVisibleDecls && !(*DI)->isModulePrivate())
- NewDecls.push_back(*DI);
- }
-
- if (NewDecls.empty())
- TC = TypoCorrection();
- else {
- TC.setCorrectionDecls(NewDecls);
- TC.setRequiresImport(!AnyVisibleDecls);
- }
-}
-
-/// \brief Try to "correct" a typo in the source code by finding
-/// visible declarations whose names are similar to the name that was
-/// present in the source code.
-///
-/// \param TypoName the \c DeclarationNameInfo structure that contains
-/// the name that was present in the source code along with its location.
-///
-/// \param LookupKind the name-lookup criteria used to search for the name.
-///
-/// \param S the scope in which name lookup occurs.
-///
-/// \param SS the nested-name-specifier that precedes the name we're
-/// looking for, if present.
-///
-/// \param CCC A CorrectionCandidateCallback object that provides further
-/// validation of typo correction candidates. It also provides flags for
-/// determining the set of keywords permitted.
-///
-/// \param MemberContext if non-NULL, the context in which to look for
-/// a member access expression.
-///
-/// \param EnteringContext whether we're entering the context described by
-/// the nested-name-specifier SS.
-///
-/// \param OPT when non-NULL, the search for visible declarations will
-/// also walk the protocols in the qualified interfaces of \p OPT.
-///
-/// \returns a \c TypoCorrection containing the corrected name if the typo
-/// along with information such as the \c NamedDecl where the corrected name
-/// was declared, and any additional \c NestedNameSpecifier needed to access
-/// it (C++ only). The \c TypoCorrection is empty if there is no correction.
-TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
- Sema::LookupNameKind LookupKind,
- Scope *S, CXXScopeSpec *SS,
- CorrectionCandidateCallback &CCC,
- CorrectTypoKind Mode,
- DeclContext *MemberContext,
- bool EnteringContext,
- const ObjCObjectPointerType *OPT,
- bool RecordFailure) {
- // Always let the ExternalSource have the first chance at correction, even
- // if we would otherwise have given up.
- if (ExternalSource) {
- if (TypoCorrection Correction = ExternalSource->CorrectTypo(
- TypoName, LookupKind, S, SS, CCC, MemberContext, EnteringContext, OPT))
- return Correction;
- }
+std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
+ const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind,
+ Scope *S, CXXScopeSpec *SS,
+ std::unique_ptr<CorrectionCandidateCallback> CCC,
+ DeclContext *MemberContext, bool EnteringContext,
+ const ObjCObjectPointerType *OPT, bool ErrorRecovery) {
if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking ||
DisableTypoCorrection)
- return TypoCorrection();
+ return nullptr;
// 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().MSVCCompat && CurContext->isDependentContext() &&
isa<CXXMethodDecl>(CurContext))
- return TypoCorrection();
+ return nullptr;
// We only attempt to correct typos for identifiers.
IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();
if (!Typo)
- return TypoCorrection();
+ return nullptr;
// If the scope specifier itself was invalid, don't try to correct
// typos.
if (SS && SS->isInvalid())
- return TypoCorrection();
+ return nullptr;
// Never try to correct typos during template deduction or
// instantiation.
if (!ActiveTemplateInstantiations.empty())
- return TypoCorrection();
+ return nullptr;
// Don't try to correct 'super'.
if (S && S->isInObjcMethodScope() && Typo == getSuperIdentifier())
- return TypoCorrection();
+ return nullptr;
// Abort if typo correction already failed for this specific typo.
IdentifierSourceLocations::iterator locs = TypoCorrectionFailures.find(Typo);
if (locs != TypoCorrectionFailures.end() &&
locs->second.count(TypoName.getLoc()))
- return TypoCorrection();
+ return nullptr;
// Don't try to correct the identifier "vector" when in AltiVec mode.
// TODO: Figure out why typo correction misbehaves in this case, fix it, and
// remove this workaround.
if (getLangOpts().AltiVec && Typo->isStr("vector"))
- return TypoCorrection();
+ return nullptr;
+
+ // Provide a stop gap for files that are just seriously broken. Trying
+ // to correct all typos can turn into a HUGE performance penalty, causing
+ // some files to take minutes to get rejected by the parser.
+ unsigned Limit = getDiagnostics().getDiagnosticOptions().SpellCheckingLimit;
+ if (Limit && TyposCorrected >= Limit)
+ return nullptr;
+ ++TyposCorrected;
// If we're handling a missing symbol error, using modules, and the
// special search all modules option is used, look for a missing import.
- if ((Mode == CTK_ErrorRecovery) && getLangOpts().Modules &&
+ if (ErrorRecovery && getLangOpts().Modules &&
getLangOpts().ModulesSearchAll) {
// The following has the side effect of loading the missing module.
getModuleLoader().lookupMissingImports(Typo->getName(),
TypoName.getLocStart());
}
- TypoCorrectionConsumer Consumer(*this, TypoName, LookupKind, S, SS, CCC,
- MemberContext, EnteringContext);
-
- // If a callback object considers an empty typo correction candidate to be
- // viable, assume it does not do any actual validation of the candidates.
- TypoCorrection EmptyCorrection;
- bool ValidatingCallback = !isCandidateViable(CCC, EmptyCorrection);
+ CorrectionCandidateCallback &CCCRef = *CCC;
+ auto Consumer = llvm::make_unique<TypoCorrectionConsumer>(
+ *this, TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
+ EnteringContext);
// Perform name lookup to find visible, similarly-named entities.
bool IsUnqualifiedLookup = false;
DeclContext *QualifiedDC = MemberContext;
if (MemberContext) {
- LookupVisibleDecls(MemberContext, LookupKind, Consumer);
+ LookupVisibleDecls(MemberContext, LookupKind, *Consumer);
// Look in qualified interfaces.
if (OPT) {
for (auto *I : OPT->quals())
- LookupVisibleDecls(I, LookupKind, Consumer);
+ LookupVisibleDecls(I, LookupKind, *Consumer);
}
} else if (SS && SS->isSet()) {
QualifiedDC = computeDeclContext(*SS, EnteringContext);
if (!QualifiedDC)
- return TypoCorrection();
+ return nullptr;
- // Provide a stop gap for files that are just seriously broken. Trying
- // to correct all typos can turn into a HUGE performance penalty, causing
- // some files to take minutes to get rejected by the parser.
- if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)
- return TypoCorrection();
- ++TyposCorrected;
-
- LookupVisibleDecls(QualifiedDC, LookupKind, Consumer);
+ LookupVisibleDecls(QualifiedDC, LookupKind, *Consumer);
} else {
IsUnqualifiedLookup = true;
- UnqualifiedTyposCorrectedMap::iterator Cached
- = UnqualifiedTyposCorrected.find(Typo);
- if (Cached != UnqualifiedTyposCorrected.end()) {
- // Add the cached value, unless it's a keyword or fails validation. In the
- // keyword case, we'll end up adding the keyword below.
- if (Cached->second) {
- if (!Cached->second.isKeyword() &&
- isCandidateViable(CCC, Cached->second)) {
- // Do not use correction that is unaccessible in the given scope.
- NamedDecl *CorrectionDecl = Cached->second.getCorrectionDecl();
- DeclarationNameInfo NameInfo(CorrectionDecl->getDeclName(),
- CorrectionDecl->getLocation());
- LookupResult R(*this, NameInfo, LookupOrdinaryName);
- if (LookupName(R, S))
- Consumer.addCorrection(Cached->second);
- }
- } else {
- // Only honor no-correction cache hits when a callback that will validate
- // correction candidates is not being used.
- if (!ValidatingCallback)
- return TypoCorrection();
- }
- }
- if (Cached == UnqualifiedTyposCorrected.end()) {
- // Provide a stop gap for files that are just seriously broken. Trying
- // to correct all typos can turn into a HUGE performance penalty, causing
- // some files to take minutes to get rejected by the parser.
- if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)
- return TypoCorrection();
- }
}
// Determine whether we are going to search in the various namespaces for
@@ -4276,17 +4115,13 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
bool SearchNamespaces
= getLangOpts().CPlusPlus &&
(IsUnqualifiedLookup || (SS && SS->isSet()));
- // In a few cases we *only* want to search for corrections based on just
- // adding or changing the nested name specifier.
- unsigned TypoLen = Typo->getName().size();
- bool AllowOnlyNNSChanges = TypoLen < 3;
if (IsUnqualifiedLookup || SearchNamespaces) {
// For unqualified lookup, look through all of the names that we have
// seen in this translation unit.
// FIXME: Re-add the ability to skip very unlikely potential corrections.
for (const auto &I : Context.Idents)
- Consumer.FoundName(I.getKey());
+ Consumer->FoundName(I.getKey());
// Walk through identifiers in external identifier sources.
// FIXME: Re-add the ability to skip very unlikely potential corrections.
@@ -4298,24 +4133,12 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
if (Name.empty())
break;
- Consumer.FoundName(Name);
+ Consumer->FoundName(Name);
} while (true);
}
}
- AddKeywordsToConsumer(*this, Consumer, S, CCC, SS && SS->isNotEmpty());
-
- // If we haven't found anything, we're done.
- if (Consumer.empty())
- return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
- IsUnqualifiedLookup);
-
- // Make sure the best edit distance (prior to adding any namespace qualifiers)
- // is not more that about a third of the length of the typo's identifier.
- unsigned ED = Consumer.getBestEditDistance(true);
- if (ED > 0 && TypoLen / ED < 3)
- return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
- IsUnqualifiedLookup);
+ AddKeywordsToConsumer(*this, *Consumer, S, CCCRef, SS && SS->isNotEmpty());
// Build the NestedNameSpecifiers for the KnownNamespaces, if we're going
// to search those namespaces.
@@ -4329,22 +4152,99 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
KnownNamespaces[N] = true;
}
- Consumer.addNamespaces(KnownNamespaces);
+ Consumer->addNamespaces(KnownNamespaces);
}
- TypoCorrection BestTC = Consumer.getNextCorrection();
- TypoCorrection SecondBestTC = Consumer.getNextCorrection();
+ return Consumer;
+}
+
+/// \brief Try to "correct" a typo in the source code by finding
+/// visible declarations whose names are similar to the name that was
+/// present in the source code.
+///
+/// \param TypoName the \c DeclarationNameInfo structure that contains
+/// the name that was present in the source code along with its location.
+///
+/// \param LookupKind the name-lookup criteria used to search for the name.
+///
+/// \param S the scope in which name lookup occurs.
+///
+/// \param SS the nested-name-specifier that precedes the name we're
+/// looking for, if present.
+///
+/// \param CCC A CorrectionCandidateCallback object that provides further
+/// validation of typo correction candidates. It also provides flags for
+/// determining the set of keywords permitted.
+///
+/// \param MemberContext if non-NULL, the context in which to look for
+/// a member access expression.
+///
+/// \param EnteringContext whether we're entering the context described by
+/// the nested-name-specifier SS.
+///
+/// \param OPT when non-NULL, the search for visible declarations will
+/// also walk the protocols in the qualified interfaces of \p OPT.
+///
+/// \returns a \c TypoCorrection containing the corrected name if the typo
+/// along with information such as the \c NamedDecl where the corrected name
+/// was declared, and any additional \c NestedNameSpecifier needed to access
+/// it (C++ only). The \c TypoCorrection is empty if there is no correction.
+TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
+ Sema::LookupNameKind LookupKind,
+ Scope *S, CXXScopeSpec *SS,
+ std::unique_ptr<CorrectionCandidateCallback> CCC,
+ CorrectTypoKind Mode,
+ DeclContext *MemberContext,
+ bool EnteringContext,
+ const ObjCObjectPointerType *OPT,
+ bool RecordFailure) {
+ assert(CCC && "CorrectTypo requires a CorrectionCandidateCallback");
+
+ // Always let the ExternalSource have the first chance at correction, even
+ // if we would otherwise have given up.
+ if (ExternalSource) {
+ if (TypoCorrection Correction = ExternalSource->CorrectTypo(
+ TypoName, LookupKind, S, SS, *CCC, MemberContext, EnteringContext, OPT))
+ return Correction;
+ }
+
+ // Ugly hack equivalent to CTC == CTC_ObjCMessageReceiver;
+ // WantObjCSuper is only true for CTC_ObjCMessageReceiver and for
+ // some instances of CTC_Unknown, while WantRemainingKeywords is true
+ // for CTC_Unknown but not for CTC_ObjCMessageReceiver.
+ bool ObjCMessageReceiver = CCC->WantObjCSuper && !CCC->WantRemainingKeywords;
+
+ IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();
+ auto Consumer = makeTypoCorrectionConsumer(
+ TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
+ EnteringContext, OPT, Mode == CTK_ErrorRecovery);
+
+ if (!Consumer)
+ return TypoCorrection();
+
+ // If we haven't found anything, we're done.
+ if (Consumer->empty())
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
+
+ // Make sure the best edit distance (prior to adding any namespace qualifiers)
+ // is not more that about a third of the length of the typo's identifier.
+ unsigned ED = Consumer->getBestEditDistance(true);
+ unsigned TypoLen = Typo->getName().size();
+ if (ED > 0 && TypoLen / ED < 3)
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
+
+ TypoCorrection BestTC = Consumer->getNextCorrection();
+ TypoCorrection SecondBestTC = Consumer->getNextCorrection();
if (!BestTC)
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
ED = BestTC.getEditDistance();
- if (!AllowOnlyNNSChanges && ED > 0 && TypoLen / ED < 3) {
+ if (TypoLen >= 3 && ED > 0 && TypoLen / ED < 3) {
// If this was an unqualified lookup and we believe the callback
// object wouldn't have filtered out possible corrections, note
// that no correction was found.
- return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
- IsUnqualifiedLookup && !ValidatingCallback);
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
}
// If only a single name remains, return that result.
@@ -4357,28 +4257,19 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
if (ED == 0 && Result.isKeyword())
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
- // Record the correction for unqualified lookup.
- if (IsUnqualifiedLookup)
- UnqualifiedTyposCorrected[Typo] = Result;
-
TypoCorrection TC = Result;
TC.setCorrectionRange(SS, TypoName);
checkCorrectionVisibility(*this, TC);
return TC;
- }
- // Ugly hack equivalent to CTC == CTC_ObjCMessageReceiver;
- // WantObjCSuper is only true for CTC_ObjCMessageReceiver and for
- // some instances of CTC_Unknown, while WantRemainingKeywords is true
- // for CTC_Unknown but not for CTC_ObjCMessageReceiver.
- else if (SecondBestTC && CCC.WantObjCSuper && !CCC.WantRemainingKeywords) {
+ } else if (SecondBestTC && ObjCMessageReceiver) {
// Prefer 'super' when we're completing in a message-receiver
// context.
if (BestTC.getCorrection().getAsString() != "super") {
if (SecondBestTC.getCorrection().getAsString() == "super")
BestTC = SecondBestTC;
- else if (Consumer["super"].front().isKeyword())
- BestTC = Consumer["super"].front();
+ else if ((*Consumer)["super"].front().isKeyword())
+ BestTC = (*Consumer)["super"].front();
}
// Don't correct to a keyword that's the same as the typo; the keyword
// wasn't actually in scope.
@@ -4386,10 +4277,6 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
BestTC.getCorrection().getAsString() != "super")
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
- // Record the correction for unqualified lookup.
- if (IsUnqualifiedLookup)
- UnqualifiedTyposCorrected[Typo] = BestTC;
-
BestTC.setCorrectionRange(SS, TypoName);
return BestTC;
}
@@ -4397,8 +4284,75 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// Record the failure's location if needed and return an empty correction. If
// this was an unqualified lookup and we believe the callback object did not
// filter out possible corrections, also cache the failure for the typo.
- return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
- IsUnqualifiedLookup && !ValidatingCallback);
+ return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
+}
+
+/// \brief Try to "correct" a typo in the source code by finding
+/// visible declarations whose names are similar to the name that was
+/// present in the source code.
+///
+/// \param TypoName the \c DeclarationNameInfo structure that contains
+/// the name that was present in the source code along with its location.
+///
+/// \param LookupKind the name-lookup criteria used to search for the name.
+///
+/// \param S the scope in which name lookup occurs.
+///
+/// \param SS the nested-name-specifier that precedes the name we're
+/// looking for, if present.
+///
+/// \param CCC A CorrectionCandidateCallback object that provides further
+/// validation of typo correction candidates. It also provides flags for
+/// determining the set of keywords permitted.
+///
+/// \param TDG A TypoDiagnosticGenerator functor that will be used to print
+/// diagnostics when the actual typo correction is attempted.
+///
+/// \param TRC A TypoRecoveryCallback functor that will be used to build an
+/// Expr from a typo correction candidate.
+///
+/// \param MemberContext if non-NULL, the context in which to look for
+/// a member access expression.
+///
+/// \param EnteringContext whether we're entering the context described by
+/// the nested-name-specifier SS.
+///
+/// \param OPT when non-NULL, the search for visible declarations will
+/// also walk the protocols in the qualified interfaces of \p OPT.
+///
+/// \returns a new \c TypoExpr that will later be replaced in the AST with an
+/// Expr representing the result of performing typo correction, or nullptr if
+/// typo correction is not possible. If nullptr is returned, no diagnostics will
+/// be emitted and it is the responsibility of the caller to emit any that are
+/// needed.
+TypoExpr *Sema::CorrectTypoDelayed(
+ const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind,
+ Scope *S, CXXScopeSpec *SS,
+ std::unique_ptr<CorrectionCandidateCallback> CCC,
+ TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode,
+ DeclContext *MemberContext, bool EnteringContext,
+ const ObjCObjectPointerType *OPT) {
+ assert(CCC && "CorrectTypoDelayed requires a CorrectionCandidateCallback");
+
+ TypoCorrection Empty;
+ auto Consumer = makeTypoCorrectionConsumer(
+ TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
+ EnteringContext, OPT,
+ /*SearchModules=*/(Mode == CTK_ErrorRecovery) && getLangOpts().Modules &&
+ getLangOpts().ModulesSearchAll);
+
+ if (!Consumer || Consumer->empty())
+ return nullptr;
+
+ // Make sure the best edit distance (prior to adding any namespace qualifiers)
+ // is not more that about a third of the length of the typo's identifier.
+ unsigned ED = Consumer->getBestEditDistance(true);
+ IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();
+ if (ED > 0 && Typo->getName().size() / ED < 3)
+ return nullptr;
+
+ ExprEvalContexts.back().NumTypos++;
+ return createDelayedTypo(std::move(Consumer), std::move(TDG), std::move(TRC));
}
void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) {
@@ -4425,7 +4379,8 @@ std::string TypoCorrection::getAsString(const LangOptions &LO) const {
return CorrectionName.getAsString();
}
-bool CorrectionCandidateCallback::ValidateCandidate(const TypoCorrection &candidate) {
+bool CorrectionCandidateCallback::ValidateCandidate(
+ const TypoCorrection &candidate) {
if (!candidate.isResolved())
return true;
@@ -4461,7 +4416,8 @@ FunctionCallFilterCCC::FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs,
MemberExpr *ME)
: NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs),
CurContext(SemaRef.CurContext), MemberFn(ME) {
- WantTypeSpecifiers = SemaRef.getLangOpts().CPlusPlus;
+ WantTypeSpecifiers = false;
+ WantFunctionLikeCasts = SemaRef.getLangOpts().CPlusPlus && NumArgs == 1;
WantRemainingKeywords = false;
}
@@ -4596,3 +4552,26 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
Diag(ChosenDecl->getLocation(), PrevNote)
<< CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo);
}
+
+TypoExpr *Sema::createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
+ TypoDiagnosticGenerator TDG,
+ TypoRecoveryCallback TRC) {
+ assert(TCC && "createDelayedTypo requires a valid TypoCorrectionConsumer");
+ auto TE = new (Context) TypoExpr(Context.DependentTy);
+ auto &State = DelayedTypos[TE];
+ State.Consumer = std::move(TCC);
+ State.DiagHandler = std::move(TDG);
+ State.RecoveryHandler = std::move(TRC);
+ return TE;
+}
+
+const Sema::TypoExprState &Sema::getTypoExprState(TypoExpr *TE) const {
+ auto Entry = DelayedTypos.find(TE);
+ assert(Entry != DelayedTypos.end() &&
+ "Failed to get the state for a TypoExpr!");
+ return Entry->second;
+}
+
+void Sema::clearDelayedTypo(TypoExpr *TE) {
+ DelayedTypos.erase(TE);
+}
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 8eb806ba301a..72b6020351fa 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -116,9 +116,9 @@ static unsigned deduceWeakPropertyFromType(Sema &S, QualType T) {
static void
CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop,
ObjCProtocolDecl *Proto,
- llvm::SmallPtrSet<ObjCProtocolDecl *, 16> &Known) {
+ llvm::SmallPtrSetImpl<ObjCProtocolDecl *> &Known) {
// Have we seen this protocol before?
- if (!Known.insert(Proto))
+ if (!Known.insert(Proto).second)
return;
// Look for a property with the same name.
@@ -1547,36 +1547,22 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,
if (IMPDecl->getInstanceMethod(Prop->getSetterName()))
continue;
}
- // If property to be implemented in the super class, ignore.
- if (SuperPropMap[Prop->getIdentifier()]) {
- ObjCPropertyDecl *PropInSuperClass = SuperPropMap[Prop->getIdentifier()];
- if ((Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite) &&
- (PropInSuperClass->getPropertyAttributes() &
- ObjCPropertyDecl::OBJC_PR_readonly) &&
- !IMPDecl->getInstanceMethod(Prop->getSetterName()) &&
- !IDecl->HasUserDeclaredSetterMethod(Prop)) {
- Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property)
- << Prop->getIdentifier();
- Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
- }
- continue;
- }
if (ObjCPropertyImplDecl *PID =
IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) {
- if (PID->getPropertyDecl() != Prop) {
- Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property)
- << Prop->getIdentifier();
- if (!PID->getLocation().isInvalid())
- Diag(PID->getLocation(), diag::note_property_synthesize);
- }
+ Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property)
+ << Prop->getIdentifier();
+ if (!PID->getLocation().isInvalid())
+ Diag(PID->getLocation(), diag::note_property_synthesize);
continue;
}
+ ObjCPropertyDecl *PropInSuperClass = SuperPropMap[Prop->getIdentifier()];
if (ObjCProtocolDecl *Proto =
dyn_cast<ObjCProtocolDecl>(Prop->getDeclContext())) {
// We won't auto-synthesize properties declared in protocols.
// Suppress the warning if class's superclass implements property's
// getter and implements property's setter (if readwrite property).
- if (!SuperClassImplementsProperty(IDecl, Prop)) {
+ // Or, if property is going to be implemented in its super class.
+ if (!SuperClassImplementsProperty(IDecl, Prop) && !PropInSuperClass) {
Diag(IMPDecl->getLocation(),
diag::warn_auto_synthesizing_protocol_property)
<< Prop << Proto;
@@ -1584,7 +1570,25 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,
}
continue;
}
-
+ // If property to be implemented in the super class, ignore.
+ if (PropInSuperClass) {
+ if ((Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite) &&
+ (PropInSuperClass->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_readonly) &&
+ !IMPDecl->getInstanceMethod(Prop->getSetterName()) &&
+ !IDecl->HasUserDeclaredSetterMethod(Prop)) {
+ Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property)
+ << Prop->getIdentifier();
+ Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
+ }
+ else {
+ Diag(Prop->getLocation(), diag::warn_autosynthesis_property_in_superclass)
+ << Prop->getIdentifier();
+ Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
+ Diag(IMPDecl->getLocation(), diag::note_while_in_implementation);
+ }
+ continue;
+ }
// We use invalid SourceLocations for the synthesized ivars since they
// aren't really synthesized at a particular location; they just exist.
// Saying that they are located at the @implementation isn't really going
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index 7f2af68e55d5..d72942a2ffec 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclOpenMP.h"
@@ -91,15 +92,17 @@ private:
DeclarationNameInfo DirectiveName;
Scope *CurScope;
SourceLocation ConstructLoc;
+ bool OrderedRegion;
+ SourceLocation InnerTeamsRegionLoc;
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
Scope *CurScope, SourceLocation Loc)
: SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope),
- ConstructLoc(Loc) {}
+ ConstructLoc(Loc), OrderedRegion(false), InnerTeamsRegionLoc() {}
SharingMapTy()
: SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr),
- ConstructLoc() {}
+ ConstructLoc(), OrderedRegion(false), InnerTeamsRegionLoc() {}
};
typedef SmallVector<SharingMapTy, 64> StackTy;
@@ -194,13 +197,42 @@ public:
return isOpenMPThreadPrivate(DVar.CKind);
}
+ /// \brief Marks current region as ordered (it has an 'ordered' clause).
+ void setOrderedRegion(bool IsOrdered = true) {
+ Stack.back().OrderedRegion = IsOrdered;
+ }
+ /// \brief Returns true, if parent region is ordered (has associated
+ /// 'ordered' clause), false - otherwise.
+ bool isParentOrderedRegion() const {
+ if (Stack.size() > 2)
+ return Stack[Stack.size() - 2].OrderedRegion;
+ return false;
+ }
+
+ /// \brief Marks current target region as one with closely nested teams
+ /// region.
+ void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
+ if (Stack.size() > 2)
+ Stack[Stack.size() - 2].InnerTeamsRegionLoc = TeamsRegionLoc;
+ }
+ /// \brief Returns true, if current region has closely nested teams region.
+ bool hasInnerTeamsRegion() const {
+ return getInnerTeamsRegionLoc().isValid();
+ }
+ /// \brief Returns location of the nested teams region (if any).
+ SourceLocation getInnerTeamsRegionLoc() const {
+ if (Stack.size() > 1)
+ return Stack.back().InnerTeamsRegionLoc;
+ return SourceLocation();
+ }
+
Scope *getCurScope() const { return Stack.back().CurScope; }
Scope *getCurScope() { return Stack.back().CurScope; }
SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
};
bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
return isOpenMPParallelDirective(DKind) || DKind == OMPD_task ||
- DKind == OMPD_unknown;
+ isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown;
}
} // namespace
@@ -213,7 +245,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
// File-scope or namespace-scope variables referenced in called routines
// in the region are shared unless they appear in a threadprivate
// directive.
- if (!D->isFunctionOrMethodVarDecl())
+ if (!D->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(D))
DVar.CKind = OMPC_shared;
// OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
@@ -263,7 +295,8 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
// In a parallel construct, if no default clause is present, these
// variables are shared.
DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
- if (isOpenMPParallelDirective(DVar.DKind)) {
+ if (isOpenMPParallelDirective(DVar.DKind) ||
+ isOpenMPTeamsDirective(DVar.DKind)) {
DVar.CKind = OMPC_shared;
return DVar;
}
@@ -358,7 +391,8 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct, C/C++, predetermined, p.1]
// Variables appearing in threadprivate directives are threadprivate.
- if (D->getTLSKind() != VarDecl::TLS_None) {
+ if (D->getTLSKind() != VarDecl::TLS_None ||
+ D->getStorageClass() == SC_Register) {
DVar.CKind = OMPC_threadprivate;
return DVar;
}
@@ -380,8 +414,10 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
StartI = std::next(StartI);
}
if (!isParallelOrTaskRegion(Kind)) {
- if (isOpenMPLocal(D, StartI) && D->isLocalVarDecl() &&
- (D->getStorageClass() == SC_Auto || D->getStorageClass() == SC_None)) {
+ if (isOpenMPLocal(D, StartI) &&
+ ((D->isLocalVarDecl() && (D->getStorageClass() == SC_Auto ||
+ D->getStorageClass() == SC_None)) ||
+ isa<ParmVarDecl>(D))) {
DVar.CKind = OMPC_private;
return DVar;
}
@@ -516,6 +552,19 @@ void Sema::InitDataSharingAttributesStack() {
#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
+bool Sema::IsOpenMPCapturedVar(VarDecl *VD) {
+ assert(LangOpts.OpenMP && "OpenMP is not allowed");
+ if (DSAStack->getCurrentDirective() != OMPD_unknown) {
+ auto DVarPrivate = DSAStack->getTopDSA(VD, /*FromParent=*/false);
+ if (DVarPrivate.CKind != OMPC_unknown && isOpenMPPrivate(DVarPrivate.CKind))
+ return true;
+ DVarPrivate = DSAStack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(),
+ /*FromParent=*/false);
+ return DVarPrivate.CKind != OMPC_unknown;
+ }
+ return false;
+}
+
void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
@@ -612,10 +661,9 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
VarDecl *VD;
if (!Lookup.isSingleResult()) {
- VarDeclFilterCCC Validator(*this);
- if (TypoCorrection Corrected =
- CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, Validator,
- CTK_ErrorRecovery)) {
+ if (TypoCorrection Corrected = CorrectTypo(
+ Id, LookupOrdinaryName, CurScope, nullptr,
+ llvm::make_unique<VarDeclFilterCCC>(*this), CTK_ErrorRecovery)) {
diagnoseTypo(Corrected,
PDiag(Lookup.empty()
? diag::err_undeclared_var_use_suggest
@@ -794,8 +842,10 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
}
// Check if this is a TLS variable.
- if (VD->getTLSKind()) {
- Diag(ILoc, diag::err_omp_var_thread_local) << VD;
+ if (VD->getTLSKind() != VarDecl::TLS_None ||
+ VD->getStorageClass() == SC_Register) {
+ Diag(ILoc, diag::err_omp_var_thread_local)
+ << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
bool IsDecl =
VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
Diag(VD->getLocation(),
@@ -814,6 +864,10 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
Vars.push_back(RefExpr);
DSAStack->addDSA(VD, DE, OMPC_threadprivate);
+ VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
+ Context, SourceRange(Loc, Loc)));
+ if (auto *ML = Context.getASTMutationListener())
+ ML->DeclarationMarkedOpenMPThreadPrivate(VD);
}
OMPThreadPrivateDecl *D = nullptr;
if (!Vars.empty()) {
@@ -918,7 +972,8 @@ public:
DVar = Stack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction),
[](OpenMPDirectiveKind K) -> bool {
return isOpenMPParallelDirective(K) ||
- isOpenMPWorksharingDirective(K);
+ isOpenMPWorksharingDirective(K) ||
+ isOpenMPTeamsDirective(K);
},
false);
if (DKind == OMPD_task && DVar.CKind == OMPC_reduction) {
@@ -993,6 +1048,14 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
+ case OMPD_for_simd: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
case OMPD_sections: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
@@ -1045,6 +1108,18 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
+ case OMPD_parallel_for_simd: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(".global_tid.", KmpInt32PtrTy),
+ std::make_pair(".bound_tid.", KmpInt32PtrTy),
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
case OMPD_parallel_sections: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
@@ -1061,7 +1136,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
- case OMPD_taskyield: {
+ case OMPD_ordered: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
@@ -1069,7 +1144,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
- case OMPD_barrier: {
+ case OMPD_atomic: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
@@ -1077,7 +1152,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
- case OMPD_taskwait: {
+ case OMPD_target: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
@@ -1085,8 +1160,12 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
- case OMPD_flush: {
+ case OMPD_teams: {
+ QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
+ QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
Sema::CapturedParamNameType Params[] = {
+ std::make_pair(".global_tid.", KmpInt32PtrTy),
+ std::make_pair(".bound_tid.", KmpInt32PtrTy),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
@@ -1094,6 +1173,10 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
break;
}
case OMPD_threadprivate:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_flush:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -1110,6 +1193,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// +------------------+-----------------+------------------------------------+
// | parallel | parallel | * |
// | parallel | for | * |
+ // | parallel | for simd | * |
// | parallel | master | * |
// | parallel | critical | * |
// | parallel | simd | * |
@@ -1117,15 +1201,21 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel | section | + |
// | parallel | single | * |
// | parallel | parallel for | * |
+ // | parallel |parallel for simd| * |
// | parallel |parallel sections| * |
// | parallel | task | * |
// | parallel | taskyield | * |
// | parallel | barrier | * |
// | parallel | taskwait | * |
// | parallel | flush | * |
+ // | parallel | ordered | + |
+ // | parallel | atomic | * |
+ // | parallel | target | * |
+ // | parallel | teams | + |
// +------------------+-----------------+------------------------------------+
// | for | parallel | * |
// | for | for | + |
+ // | for | for simd | + |
// | for | master | + |
// | for | critical | * |
// | for | simd | * |
@@ -1133,15 +1223,21 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | for | section | + |
// | for | single | + |
// | for | parallel for | * |
+ // | for |parallel for simd| * |
// | for |parallel sections| * |
// | for | task | * |
// | for | taskyield | * |
// | for | barrier | + |
// | for | taskwait | * |
// | for | flush | * |
+ // | for | ordered | * (if construct is ordered) |
+ // | for | atomic | * |
+ // | for | target | * |
+ // | for | teams | + |
// +------------------+-----------------+------------------------------------+
// | master | parallel | * |
// | master | for | + |
+ // | master | for simd | + |
// | master | master | * |
// | master | critical | * |
// | master | simd | * |
@@ -1149,30 +1245,42 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | master | section | + |
// | master | single | + |
// | master | parallel for | * |
+ // | master |parallel for simd| * |
// | master |parallel sections| * |
// | master | task | * |
// | master | taskyield | * |
// | master | barrier | + |
// | master | taskwait | * |
// | master | flush | * |
+ // | master | ordered | + |
+ // | master | atomic | * |
+ // | master | target | * |
+ // | master | teams | + |
// +------------------+-----------------+------------------------------------+
// | critical | parallel | * |
// | critical | for | + |
+ // | critical | for simd | + |
// | critical | master | * |
- // | critical | critical | * (should have dirrerent names) |
+ // | critical | critical | * (should have different names) |
// | critical | simd | * |
// | critical | sections | + |
// | critical | section | + |
// | critical | single | + |
// | critical | parallel for | * |
+ // | critical |parallel for simd| * |
// | critical |parallel sections| * |
// | critical | task | * |
// | critical | taskyield | * |
// | critical | barrier | + |
// | critical | taskwait | * |
+ // | critical | ordered | + |
+ // | critical | atomic | * |
+ // | critical | target | * |
+ // | critical | teams | + |
// +------------------+-----------------+------------------------------------+
// | simd | parallel | |
// | simd | for | |
+ // | simd | for simd | |
// | simd | master | |
// | simd | critical | |
// | simd | simd | |
@@ -1180,15 +1288,65 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | simd | section | |
// | simd | single | |
// | simd | parallel for | |
+ // | simd |parallel for simd| |
// | simd |parallel sections| |
// | simd | task | |
// | simd | taskyield | |
// | simd | barrier | |
// | simd | taskwait | |
// | simd | flush | |
+ // | simd | ordered | |
+ // | simd | atomic | |
+ // | simd | target | |
+ // | simd | teams | |
+ // +------------------+-----------------+------------------------------------+
+ // | for simd | parallel | |
+ // | for simd | for | |
+ // | for simd | for simd | |
+ // | for simd | master | |
+ // | for simd | critical | |
+ // | for simd | simd | |
+ // | for simd | sections | |
+ // | for simd | section | |
+ // | for simd | single | |
+ // | for simd | parallel for | |
+ // | for simd |parallel for simd| |
+ // | for simd |parallel sections| |
+ // | for simd | task | |
+ // | for simd | taskyield | |
+ // | for simd | barrier | |
+ // | for simd | taskwait | |
+ // | for simd | flush | |
+ // | for simd | ordered | |
+ // | for simd | atomic | |
+ // | for simd | target | |
+ // | for simd | teams | |
+ // +------------------+-----------------+------------------------------------+
+ // | parallel for simd| parallel | |
+ // | parallel for simd| for | |
+ // | parallel for simd| for simd | |
+ // | parallel for simd| master | |
+ // | parallel for simd| critical | |
+ // | parallel for simd| simd | |
+ // | parallel for simd| sections | |
+ // | parallel for simd| section | |
+ // | parallel for simd| single | |
+ // | parallel for simd| parallel for | |
+ // | parallel for simd|parallel for simd| |
+ // | parallel for simd|parallel sections| |
+ // | parallel for simd| task | |
+ // | parallel for simd| taskyield | |
+ // | parallel for simd| barrier | |
+ // | parallel for simd| taskwait | |
+ // | parallel for simd| flush | |
+ // | parallel for simd| ordered | |
+ // | parallel for simd| atomic | |
+ // | parallel for simd| target | |
+ // | parallel for simd| teams | |
// +------------------+-----------------+------------------------------------+
// | sections | parallel | * |
// | sections | for | + |
+ // | sections | for simd | + |
// | sections | master | + |
// | sections | critical | * |
// | sections | simd | * |
@@ -1196,15 +1354,21 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | sections | section | * |
// | sections | single | + |
// | sections | parallel for | * |
+ // | sections |parallel for simd| * |
// | sections |parallel sections| * |
// | sections | task | * |
// | sections | taskyield | * |
// | sections | barrier | + |
// | sections | taskwait | * |
// | sections | flush | * |
+ // | sections | ordered | + |
+ // | sections | atomic | * |
+ // | sections | target | * |
+ // | sections | teams | + |
// +------------------+-----------------+------------------------------------+
// | section | parallel | * |
// | section | for | + |
+ // | section | for simd | + |
// | section | master | + |
// | section | critical | * |
// | section | simd | * |
@@ -1212,15 +1376,21 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | section | section | + |
// | section | single | + |
// | section | parallel for | * |
+ // | section |parallel for simd| * |
// | section |parallel sections| * |
// | section | task | * |
// | section | taskyield | * |
// | section | barrier | + |
// | section | taskwait | * |
// | section | flush | * |
+ // | section | ordered | + |
+ // | section | atomic | * |
+ // | section | target | * |
+ // | section | teams | + |
// +------------------+-----------------+------------------------------------+
// | single | parallel | * |
// | single | for | + |
+ // | single | for simd | + |
// | single | master | + |
// | single | critical | * |
// | single | simd | * |
@@ -1228,15 +1398,21 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | single | section | + |
// | single | single | + |
// | single | parallel for | * |
+ // | single |parallel for simd| * |
// | single |parallel sections| * |
// | single | task | * |
// | single | taskyield | * |
// | single | barrier | + |
// | single | taskwait | * |
// | single | flush | * |
+ // | single | ordered | + |
+ // | single | atomic | * |
+ // | single | target | * |
+ // | single | teams | + |
// +------------------+-----------------+------------------------------------+
// | parallel for | parallel | * |
// | parallel for | for | + |
+ // | parallel for | for simd | + |
// | parallel for | master | + |
// | parallel for | critical | * |
// | parallel for | simd | * |
@@ -1244,15 +1420,21 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel for | section | + |
// | parallel for | single | + |
// | parallel for | parallel for | * |
+ // | parallel for |parallel for simd| * |
// | parallel for |parallel sections| * |
// | parallel for | task | * |
// | parallel for | taskyield | * |
// | parallel for | barrier | + |
// | parallel for | taskwait | * |
// | parallel for | flush | * |
+ // | parallel for | ordered | * (if construct is ordered) |
+ // | parallel for | atomic | * |
+ // | parallel for | target | * |
+ // | parallel for | teams | + |
// +------------------+-----------------+------------------------------------+
// | parallel sections| parallel | * |
// | parallel sections| for | + |
+ // | parallel sections| for simd | + |
// | parallel sections| master | + |
// | parallel sections| critical | + |
// | parallel sections| simd | * |
@@ -1260,15 +1442,21 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel sections| section | * |
// | parallel sections| single | + |
// | parallel sections| parallel for | * |
+ // | parallel sections|parallel for simd| * |
// | parallel sections|parallel sections| * |
// | parallel sections| task | * |
// | parallel sections| taskyield | * |
// | parallel sections| barrier | + |
// | parallel sections| taskwait | * |
// | parallel sections| flush | * |
+ // | parallel sections| ordered | + |
+ // | parallel sections| atomic | * |
+ // | parallel sections| target | * |
+ // | parallel sections| teams | + |
// +------------------+-----------------+------------------------------------+
// | task | parallel | * |
// | task | for | + |
+ // | task | for simd | + |
// | task | master | + |
// | task | critical | * |
// | task | simd | * |
@@ -1276,24 +1464,128 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | task | section | + |
// | task | single | + |
// | task | parallel for | * |
+ // | task |parallel for simd| * |
// | task |parallel sections| * |
// | task | task | * |
// | task | taskyield | * |
// | task | barrier | + |
// | task | taskwait | * |
// | task | flush | * |
+ // | task | ordered | + |
+ // | task | atomic | * |
+ // | task | target | * |
+ // | task | teams | + |
+ // +------------------+-----------------+------------------------------------+
+ // | ordered | parallel | * |
+ // | ordered | for | + |
+ // | ordered | for simd | + |
+ // | ordered | master | * |
+ // | ordered | critical | * |
+ // | ordered | simd | * |
+ // | ordered | sections | + |
+ // | ordered | section | + |
+ // | ordered | single | + |
+ // | ordered | parallel for | * |
+ // | ordered |parallel for simd| * |
+ // | ordered |parallel sections| * |
+ // | ordered | task | * |
+ // | ordered | taskyield | * |
+ // | ordered | barrier | + |
+ // | ordered | taskwait | * |
+ // | ordered | flush | * |
+ // | ordered | ordered | + |
+ // | ordered | atomic | * |
+ // | ordered | target | * |
+ // | ordered | teams | + |
+ // +------------------+-----------------+------------------------------------+
+ // | atomic | parallel | |
+ // | atomic | for | |
+ // | atomic | for simd | |
+ // | atomic | master | |
+ // | atomic | critical | |
+ // | atomic | simd | |
+ // | atomic | sections | |
+ // | atomic | section | |
+ // | atomic | single | |
+ // | atomic | parallel for | |
+ // | atomic |parallel for simd| |
+ // | atomic |parallel sections| |
+ // | atomic | task | |
+ // | atomic | taskyield | |
+ // | atomic | barrier | |
+ // | atomic | taskwait | |
+ // | atomic | flush | |
+ // | atomic | ordered | |
+ // | atomic | atomic | |
+ // | atomic | target | |
+ // | atomic | teams | |
+ // +------------------+-----------------+------------------------------------+
+ // | target | parallel | * |
+ // | target | for | * |
+ // | target | for simd | * |
+ // | target | master | * |
+ // | target | critical | * |
+ // | target | simd | * |
+ // | target | sections | * |
+ // | target | section | * |
+ // | target | single | * |
+ // | target | parallel for | * |
+ // | target |parallel for simd| * |
+ // | target |parallel sections| * |
+ // | target | task | * |
+ // | target | taskyield | * |
+ // | target | barrier | * |
+ // | target | taskwait | * |
+ // | target | flush | * |
+ // | target | ordered | * |
+ // | target | atomic | * |
+ // | target | target | * |
+ // | target | teams | * |
+ // +------------------+-----------------+------------------------------------+
+ // | teams | parallel | * |
+ // | teams | for | + |
+ // | teams | for simd | + |
+ // | teams | master | + |
+ // | teams | critical | + |
+ // | teams | simd | + |
+ // | teams | sections | + |
+ // | teams | section | + |
+ // | teams | single | + |
+ // | teams | parallel for | * |
+ // | teams |parallel for simd| * |
+ // | teams |parallel sections| * |
+ // | teams | task | + |
+ // | teams | taskyield | + |
+ // | teams | barrier | + |
+ // | teams | taskwait | + |
+ // | teams | flush | + |
+ // | teams | ordered | + |
+ // | teams | atomic | + |
+ // | teams | target | + |
+ // | teams | teams | + |
// +------------------+-----------------+------------------------------------+
if (Stack->getCurScope()) {
auto ParentRegion = Stack->getParentDirective();
bool NestingProhibited = false;
bool CloseNesting = true;
- bool ShouldBeInParallelRegion = false;
+ enum {
+ NoRecommend,
+ ShouldBeInParallelRegion,
+ ShouldBeInOrderedRegion,
+ ShouldBeInTargetRegion
+ } Recommend = NoRecommend;
if (isOpenMPSimdDirective(ParentRegion)) {
// OpenMP [2.16, Nesting of Regions]
// OpenMP constructs may not be nested inside a simd region.
SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_simd);
return true;
}
+ if (ParentRegion == OMPD_atomic) {
+ // OpenMP [2.16, Nesting of Regions]
+ // OpenMP constructs may not be nested inside an atomic region.
+ SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
+ return true;
+ }
if (CurrentRegion == OMPD_section) {
// OpenMP [2.7.2, sections Construct, Restrictions]
// Orphaned section directives are prohibited. That is, the section
@@ -1308,10 +1600,14 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
}
return false;
}
+ // Allow some constructs to be orphaned (they could be used in functions,
+ // called from OpenMP regions with the required preconditions).
+ if (ParentRegion == OMPD_unknown)
+ return false;
if (CurrentRegion == OMPD_master) {
// OpenMP [2.16, Nesting of Regions]
// A master region may not be closely nested inside a worksharing,
- // atomic (TODO), or explicit task region.
+ // atomic, or explicit task region.
NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
ParentRegion == OMPD_task;
} else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
@@ -1346,30 +1642,52 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
} else if (CurrentRegion == OMPD_barrier) {
// OpenMP [2.16, Nesting of Regions]
// A barrier region may not be closely nested inside a worksharing,
- // explicit task, critical, ordered(TODO), atomic(TODO), or master
- // region.
- NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
- ParentRegion == OMPD_task ||
- ParentRegion == OMPD_master ||
- ParentRegion == OMPD_critical;
+ // explicit task, critical, ordered, atomic, or master region.
+ NestingProhibited =
+ isOpenMPWorksharingDirective(ParentRegion) ||
+ ParentRegion == OMPD_task || ParentRegion == OMPD_master ||
+ ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
} else if (isOpenMPWorksharingDirective(CurrentRegion) &&
- !isOpenMPParallelDirective(CurrentRegion) &&
- !isOpenMPSimdDirective(CurrentRegion)) {
+ !isOpenMPParallelDirective(CurrentRegion)) {
// OpenMP [2.16, Nesting of Regions]
// A worksharing region may not be closely nested inside a worksharing,
// explicit task, critical, ordered, atomic, or master region.
- // TODO
- NestingProhibited = (isOpenMPWorksharingDirective(ParentRegion) &&
- !isOpenMPSimdDirective(ParentRegion)) ||
+ NestingProhibited =
+ isOpenMPWorksharingDirective(ParentRegion) ||
+ ParentRegion == OMPD_task || ParentRegion == OMPD_master ||
+ ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
+ Recommend = ShouldBeInParallelRegion;
+ } else if (CurrentRegion == OMPD_ordered) {
+ // OpenMP [2.16, Nesting of Regions]
+ // An ordered region may not be closely nested inside a critical,
+ // atomic, or explicit task region.
+ // An ordered region must be closely nested inside a loop region (or
+ // parallel loop region) with an ordered clause.
+ NestingProhibited = ParentRegion == OMPD_critical ||
ParentRegion == OMPD_task ||
- ParentRegion == OMPD_master ||
- ParentRegion == OMPD_critical;
- ShouldBeInParallelRegion = true;
+ !Stack->isParentOrderedRegion();
+ Recommend = ShouldBeInOrderedRegion;
+ } else if (isOpenMPTeamsDirective(CurrentRegion)) {
+ // OpenMP [2.16, Nesting of Regions]
+ // If specified, a teams construct must be contained within a target
+ // construct.
+ NestingProhibited = ParentRegion != OMPD_target;
+ Recommend = ShouldBeInTargetRegion;
+ Stack->setParentTeamsRegionLoc(Stack->getConstructLoc());
+ }
+ if (!NestingProhibited && isOpenMPTeamsDirective(ParentRegion)) {
+ // OpenMP [2.16, Nesting of Regions]
+ // distribute, parallel, parallel sections, parallel workshare, and the
+ // parallel loop and parallel loop SIMD constructs are the only OpenMP
+ // constructs that can be closely nested in the teams region.
+ // TODO: add distribute directive.
+ NestingProhibited = !isOpenMPParallelDirective(CurrentRegion);
+ Recommend = ShouldBeInParallelRegion;
}
if (NestingProhibited) {
SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
- << CloseNesting << getOpenMPDirectiveName(ParentRegion)
- << ShouldBeInParallelRegion << getOpenMPDirectiveName(CurrentRegion);
+ << CloseNesting << getOpenMPDirectiveName(ParentRegion) << Recommend
+ << getOpenMPDirectiveName(CurrentRegion);
return true;
}
}
@@ -1426,6 +1744,10 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
VarsWithInheritedDSA);
break;
+ case OMPD_for_simd:
+ Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc, VarsWithInheritedDSA);
+ break;
case OMPD_sections:
Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
@@ -1453,6 +1775,10 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc, VarsWithInheritedDSA);
break;
+ case OMPD_parallel_for_simd:
+ Res = ActOnOpenMPParallelForSimdDirective(
+ ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
+ break;
case OMPD_parallel_sections:
Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
StartLoc, EndLoc);
@@ -1487,6 +1813,23 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
"No associated statement allowed for 'omp flush' directive");
Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
break;
+ case OMPD_ordered:
+ assert(ClausesWithImplicit.empty() &&
+ "No clauses are allowed for 'omp ordered' directive");
+ Res = ActOnOpenMPOrderedDirective(AStmt, StartLoc, EndLoc);
+ break;
+ case OMPD_atomic:
+ Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
+ break;
+ case OMPD_teams:
+ Res =
+ ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
+ break;
+ case OMPD_target:
+ Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
+ break;
case OMPD_threadprivate:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
@@ -1535,10 +1878,16 @@ class OpenMPIterationSpaceChecker {
SourceLocation DefaultLoc;
/// \brief A location for diagnostics (when increment is not compatible).
SourceLocation ConditionLoc;
+ /// \brief A source location for referring to loop init later.
+ SourceRange InitSrcRange;
/// \brief A source location for referring to condition later.
SourceRange ConditionSrcRange;
+ /// \brief A source location for referring to increment later.
+ SourceRange IncrementSrcRange;
/// \brief Loop variable.
VarDecl *Var;
+ /// \brief Reference to loop variable.
+ DeclRefExpr *VarRef;
/// \brief Lower bound (initializer for the var).
Expr *LB;
/// \brief Upper bound.
@@ -1559,9 +1908,10 @@ class OpenMPIterationSpaceChecker {
public:
OpenMPIterationSpaceChecker(Sema &SemaRef, SourceLocation DefaultLoc)
: SemaRef(SemaRef), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
- ConditionSrcRange(SourceRange()), Var(nullptr), LB(nullptr),
- UB(nullptr), Step(nullptr), TestIsLessOp(false), TestIsStrictOp(false),
- SubtractStep(false) {}
+ InitSrcRange(SourceRange()), ConditionSrcRange(SourceRange()),
+ IncrementSrcRange(SourceRange()), Var(nullptr), VarRef(nullptr),
+ LB(nullptr), UB(nullptr), Step(nullptr), TestIsLessOp(false),
+ TestIsStrictOp(false), SubtractStep(false) {}
/// \brief Check init-expr for canonical loop form and save loop counter
/// variable - #Var and its initialization value - #LB.
bool CheckInit(Stmt *S);
@@ -1573,6 +1923,24 @@ public:
bool CheckInc(Expr *S);
/// \brief Return the loop counter variable.
VarDecl *GetLoopVar() const { return Var; }
+ /// \brief Return the reference expression to loop counter variable.
+ DeclRefExpr *GetLoopVarRefExpr() const { return VarRef; }
+ /// \brief Source range of the loop init.
+ SourceRange GetInitSrcRange() const { return InitSrcRange; }
+ /// \brief Source range of the loop condition.
+ SourceRange GetConditionSrcRange() const { return ConditionSrcRange; }
+ /// \brief Source range of the loop increment.
+ SourceRange GetIncrementSrcRange() const { return IncrementSrcRange; }
+ /// \brief True if the step should be subtracted.
+ bool ShouldSubtractStep() const { return SubtractStep; }
+ /// \brief Build the expression to calculate the number of iterations.
+ Expr *BuildNumIterations(Scope *S, const bool LimitedType) const;
+ /// \brief Build reference expression to the counter be used for codegen.
+ Expr *BuildCounterVar() const;
+ /// \brief Build initization of the counter be used for codegen.
+ Expr *BuildCounterInit() const;
+ /// \brief Build step of the counter be used for codegen.
+ Expr *BuildCounterStep() const;
/// \brief Return true if any expression is dependent.
bool Dependent() const;
@@ -1581,7 +1949,7 @@ private:
/// expression.
bool CheckIncRHS(Expr *RHS);
/// \brief Helper to set loop counter variable and its initializer.
- bool SetVarAndLB(VarDecl *NewVar, Expr *NewLB);
+ bool SetVarAndLB(VarDecl *NewVar, DeclRefExpr *NewVarRefExpr, Expr *NewLB);
/// \brief Helper to set upper bound.
bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, const SourceRange &SR,
const SourceLocation &SL);
@@ -1598,13 +1966,16 @@ bool OpenMPIterationSpaceChecker::Dependent() const {
(UB && UB->isValueDependent()) || (Step && Step->isValueDependent());
}
-bool OpenMPIterationSpaceChecker::SetVarAndLB(VarDecl *NewVar, Expr *NewLB) {
+bool OpenMPIterationSpaceChecker::SetVarAndLB(VarDecl *NewVar,
+ DeclRefExpr *NewVarRefExpr,
+ Expr *NewLB) {
// State consistency checking to ensure correct usage.
- assert(Var == nullptr && LB == nullptr && UB == nullptr && Step == nullptr &&
- !TestIsLessOp && !TestIsStrictOp);
+ assert(Var == nullptr && LB == nullptr && VarRef == nullptr &&
+ UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
if (!NewVar || !NewLB)
return true;
Var = NewVar;
+ VarRef = NewVarRefExpr;
LB = NewLB;
return false;
}
@@ -1655,10 +2026,12 @@ bool OpenMPIterationSpaceChecker::SetStep(Expr *NewStep, bool Subtract) {
bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
bool IsConstNeg =
IsConstant && Result.isSigned() && (Subtract != Result.isNegative());
+ bool IsConstPos =
+ IsConstant && Result.isSigned() && (Subtract == Result.isNegative());
bool IsConstZero = IsConstant && !Result.getBoolValue();
if (UB && (IsConstZero ||
(TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
- : (!IsConstNeg || (IsUnsigned && !Subtract))))) {
+ : (IsConstPos || (IsUnsigned && !Subtract))))) {
SemaRef.Diag(NewStep->getExprLoc(),
diag::err_omp_loop_incr_not_compatible)
<< Var << TestIsLessOp << NewStep->getSourceRange();
@@ -1667,6 +2040,11 @@ bool OpenMPIterationSpaceChecker::SetStep(Expr *NewStep, bool Subtract) {
<< TestIsLessOp << ConditionSrcRange;
return true;
}
+ if (TestIsLessOp == Subtract) {
+ NewStep = SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus,
+ NewStep).get();
+ Subtract = !Subtract;
+ }
}
Step = NewStep;
@@ -1687,12 +2065,14 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S) {
SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
return true;
}
+ InitSrcRange = S->getSourceRange();
if (Expr *E = dyn_cast<Expr>(S))
S = E->IgnoreParens();
if (auto BO = dyn_cast<BinaryOperator>(S)) {
if (BO->getOpcode() == BO_Assign)
if (auto DRE = dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParens()))
- return SetVarAndLB(dyn_cast<VarDecl>(DRE->getDecl()), BO->getLHS());
+ return SetVarAndLB(dyn_cast<VarDecl>(DRE->getDecl()), DRE,
+ BO->getRHS());
} else if (auto DS = dyn_cast<DeclStmt>(S)) {
if (DS->isSingleDecl()) {
if (auto Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
@@ -1702,14 +2082,15 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S) {
SemaRef.Diag(S->getLocStart(),
diag::ext_omp_loop_not_canonical_init)
<< S->getSourceRange();
- return SetVarAndLB(Var, Var->getInit());
+ return SetVarAndLB(Var, nullptr, Var->getInit());
}
}
}
} else if (auto CE = dyn_cast<CXXOperatorCallExpr>(S))
if (CE->getOperator() == OO_Equal)
if (auto DRE = dyn_cast<DeclRefExpr>(CE->getArg(0)))
- return SetVarAndLB(dyn_cast<VarDecl>(DRE->getDecl()), CE->getArg(1));
+ return SetVarAndLB(dyn_cast<VarDecl>(DRE->getDecl()), DRE,
+ CE->getArg(1));
SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_init)
<< S->getSourceRange();
@@ -1833,6 +2214,7 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) {
SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << Var;
return true;
}
+ IncrementSrcRange = S->getSourceRange();
S = S->IgnoreParens();
if (auto UO = dyn_cast<UnaryOperator>(S)) {
if (UO->isIncrementDecrementOp() && GetInitVarDecl(UO->getSubExpr()) == Var)
@@ -1882,6 +2264,115 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) {
<< S->getSourceRange() << Var;
return true;
}
+
+/// \brief Build the expression to calculate the number of iterations.
+Expr *
+OpenMPIterationSpaceChecker::BuildNumIterations(Scope *S,
+ const bool LimitedType) const {
+ ExprResult Diff;
+ if (Var->getType()->isIntegerType() || Var->getType()->isPointerType() ||
+ SemaRef.getLangOpts().CPlusPlus) {
+ // Upper - Lower
+ Expr *Upper = TestIsLessOp ? UB : LB;
+ Expr *Lower = TestIsLessOp ? LB : UB;
+
+ Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
+
+ if (!Diff.isUsable() && Var->getType()->getAsCXXRecordDecl()) {
+ // BuildBinOp already emitted error, this one is to point user to upper
+ // and lower bound, and to tell what is passed to 'operator-'.
+ SemaRef.Diag(Upper->getLocStart(), diag::err_omp_loop_diff_cxx)
+ << Upper->getSourceRange() << Lower->getSourceRange();
+ return nullptr;
+ }
+ }
+
+ if (!Diff.isUsable())
+ return nullptr;
+
+ // Upper - Lower [- 1]
+ if (TestIsStrictOp)
+ Diff = SemaRef.BuildBinOp(
+ S, DefaultLoc, BO_Sub, Diff.get(),
+ SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
+ if (!Diff.isUsable())
+ return nullptr;
+
+ // Upper - Lower [- 1] + Step
+ Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(),
+ Step->IgnoreImplicit());
+ if (!Diff.isUsable())
+ return nullptr;
+
+ // Parentheses (for dumping/debugging purposes only).
+ Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
+ if (!Diff.isUsable())
+ return nullptr;
+
+ // (Upper - Lower [- 1] + Step) / Step
+ Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(),
+ Step->IgnoreImplicit());
+ if (!Diff.isUsable())
+ return nullptr;
+
+ // OpenMP runtime requires 32-bit or 64-bit loop variables.
+ if (LimitedType) {
+ auto &C = SemaRef.Context;
+ QualType Type = Diff.get()->getType();
+ unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
+ if (NewSize != C.getTypeSize(Type)) {
+ if (NewSize < C.getTypeSize(Type)) {
+ assert(NewSize == 64 && "incorrect loop var size");
+ SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
+ << InitSrcRange << ConditionSrcRange;
+ }
+ QualType NewType = C.getIntTypeForBitwidth(
+ NewSize, Type->hasSignedIntegerRepresentation());
+ Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
+ Sema::AA_Converting, true);
+ if (!Diff.isUsable())
+ return nullptr;
+ }
+ }
+
+ return Diff.get();
+}
+
+/// \brief Build reference expression to the counter be used for codegen.
+Expr *OpenMPIterationSpaceChecker::BuildCounterVar() const {
+ return DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
+ GetIncrementSrcRange().getBegin(), Var, false,
+ DefaultLoc, Var->getType(), VK_LValue);
+}
+
+/// \brief Build initization of the counter be used for codegen.
+Expr *OpenMPIterationSpaceChecker::BuildCounterInit() const { return LB; }
+
+/// \brief Build step of the counter be used for codegen.
+Expr *OpenMPIterationSpaceChecker::BuildCounterStep() const { return Step; }
+
+/// \brief Iteration space of a single for loop.
+struct LoopIterationSpace {
+ /// \brief This expression calculates the number of iterations in the loop.
+ /// It is always possible to calculate it before starting the loop.
+ Expr *NumIterations;
+ /// \brief The loop counter variable.
+ Expr *CounterVar;
+ /// \brief This is initializer for the initial value of #CounterVar.
+ Expr *CounterInit;
+ /// \brief This is step for the #CounterVar used to generate its update:
+ /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
+ Expr *CounterStep;
+ /// \brief Should step be subtracted?
+ bool Subtract;
+ /// \brief Source range of the loop init.
+ SourceRange InitSrcRange;
+ /// \brief Source range of the loop condition.
+ SourceRange CondSrcRange;
+ /// \brief Source range of the loop increment.
+ SourceRange IncSrcRange;
+};
+
} // namespace
/// \brief Called on a for stmt to check and extract its iteration space
@@ -1890,7 +2381,8 @@ static bool CheckOpenMPIterationSpace(
OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
Expr *NestedLoopCountExpr,
- llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA,
+ LoopIterationSpace &ResultIterSpace) {
// OpenMP [2.6, Canonical Loop Form]
// for (init-expr; test-expr; incr-expr) structured-block
auto For = dyn_cast_or_null<ForStmt>(S);
@@ -1943,8 +2435,7 @@ static bool CheckOpenMPIterationSpace(
// that is the increment of the associated for-loop.
// Exclude loop var from the list of variables with implicitly defined data
// sharing attributes.
- while (VarsWithImplicitDSA.count(Var) > 0)
- VarsWithImplicitDSA.erase(Var);
+ VarsWithImplicitDSA.erase(Var);
// OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced in
// a Construct, C/C++].
@@ -1954,25 +2445,40 @@ static bool CheckOpenMPIterationSpace(
// The loop iteration variable(s) in the associated for-loop(s) of a for or
// parallel for construct may be listed in a private or lastprivate clause.
DSAStackTy::DSAVarData DVar = DSA.getTopDSA(Var, false);
+ auto LoopVarRefExpr = ISC.GetLoopVarRefExpr();
+ // If LoopVarRefExpr is nullptr it means the corresponding loop variable is
+ // declared in the loop and it is predetermined as a private.
auto PredeterminedCKind =
isOpenMPSimdDirective(DKind)
? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate)
: OMPC_private;
if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
DVar.CKind != PredeterminedCKind) ||
- (isOpenMPWorksharingDirective(DKind) && DVar.CKind != OMPC_unknown &&
- DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
+ (isOpenMPWorksharingDirective(DKind) && !isOpenMPSimdDirective(DKind) &&
+ DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private &&
+ DVar.CKind != OMPC_lastprivate)) &&
(DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa)
<< getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
<< getOpenMPClauseName(PredeterminedCKind);
ReportOriginalDSA(SemaRef, &DSA, Var, DVar, true);
HasErrors = true;
- } else {
+ } else if (LoopVarRefExpr != nullptr) {
// Make the loop iteration variable private (for worksharing constructs),
// linear (for simd directives with the only one associated loop) or
// lastprivate (for simd directives with several collapsed loops).
- DSA.addDSA(Var, nullptr, PredeterminedCKind);
+ // FIXME: the next check and error message must be removed once the
+ // capturing of global variables in loops is fixed.
+ if (DVar.CKind == OMPC_unknown)
+ DVar = DSA.hasDSA(Var, isOpenMPPrivate, MatchesAlways(),
+ /*FromParent=*/false);
+ if (!Var->hasLocalStorage() && DVar.CKind == OMPC_unknown) {
+ SemaRef.Diag(Init->getLocStart(), diag::err_omp_global_loop_var_dsa)
+ << getOpenMPClauseName(PredeterminedCKind)
+ << getOpenMPDirectiveName(DKind);
+ HasErrors = true;
+ } else
+ DSA.addDSA(Var, LoopVarRefExpr, PredeterminedCKind);
}
assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
@@ -1983,35 +2489,97 @@ static bool CheckOpenMPIterationSpace(
// Check incr-expr.
HasErrors |= ISC.CheckInc(For->getInc());
- if (ISC.Dependent())
+ if (ISC.Dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
return HasErrors;
- // FIXME: Build loop's iteration space representation.
+ // Build the loop's iteration space representation.
+ ResultIterSpace.NumIterations = ISC.BuildNumIterations(
+ DSA.getCurScope(), /* LimitedType */ isOpenMPWorksharingDirective(DKind));
+ ResultIterSpace.CounterVar = ISC.BuildCounterVar();
+ ResultIterSpace.CounterInit = ISC.BuildCounterInit();
+ ResultIterSpace.CounterStep = ISC.BuildCounterStep();
+ ResultIterSpace.InitSrcRange = ISC.GetInitSrcRange();
+ ResultIterSpace.CondSrcRange = ISC.GetConditionSrcRange();
+ ResultIterSpace.IncSrcRange = ISC.GetIncrementSrcRange();
+ ResultIterSpace.Subtract = ISC.ShouldSubtractStep();
+
+ HasErrors |= (ResultIterSpace.NumIterations == nullptr ||
+ ResultIterSpace.CounterVar == nullptr ||
+ ResultIterSpace.CounterInit == nullptr ||
+ ResultIterSpace.CounterStep == nullptr);
+
return HasErrors;
}
-/// \brief A helper routine to skip no-op (attributed, compound) stmts get the
-/// next nested for loop. If \a IgnoreCaptured is true, it skips captured stmt
-/// to get the first for loop.
-static Stmt *IgnoreContainerStmts(Stmt *S, bool IgnoreCaptured) {
- if (IgnoreCaptured)
- if (auto CapS = dyn_cast_or_null<CapturedStmt>(S))
- S = CapS->getCapturedStmt();
- // OpenMP [2.8.1, simd construct, Restrictions]
- // All loops associated with the construct must be perfectly nested; that is,
- // there must be no intervening code nor any OpenMP directive between any two
- // loops.
- while (true) {
- if (auto AS = dyn_cast_or_null<AttributedStmt>(S))
- S = AS->getSubStmt();
- else if (auto CS = dyn_cast_or_null<CompoundStmt>(S)) {
- if (CS->size() != 1)
- break;
- S = CS->body_back();
- } else
- break;
- }
- return S;
+/// \brief Build a variable declaration for OpenMP loop iteration variable.
+static VarDecl *BuildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
+ StringRef Name) {
+ DeclContext *DC = SemaRef.CurContext;
+ IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
+ TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
+ VarDecl *Decl =
+ VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
+ Decl->setImplicit();
+ return Decl;
+}
+
+/// \brief Build 'VarRef = Start + Iter * Step'.
+static ExprResult BuildCounterUpdate(Sema &SemaRef, Scope *S,
+ SourceLocation Loc, ExprResult VarRef,
+ ExprResult Start, ExprResult Iter,
+ ExprResult Step, bool Subtract) {
+ // Add parentheses (for debugging purposes only).
+ Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
+ if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
+ !Step.isUsable())
+ return ExprError();
+
+ ExprResult Update = SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(),
+ Step.get()->IgnoreImplicit());
+ if (!Update.isUsable())
+ return ExprError();
+
+ // Build 'VarRef = Start + Iter * Step'.
+ Update = SemaRef.BuildBinOp(S, Loc, (Subtract ? BO_Sub : BO_Add),
+ Start.get()->IgnoreImplicit(), Update.get());
+ if (!Update.isUsable())
+ return ExprError();
+
+ Update = SemaRef.PerformImplicitConversion(
+ Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
+ if (!Update.isUsable())
+ return ExprError();
+
+ Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
+ return Update;
+}
+
+/// \brief Convert integer expression \a E to make it have at least \a Bits
+/// bits.
+static ExprResult WidenIterationCount(unsigned Bits, Expr *E,
+ Sema &SemaRef) {
+ if (E == nullptr)
+ return ExprError();
+ auto &C = SemaRef.Context;
+ QualType OldType = E->getType();
+ unsigned HasBits = C.getTypeSize(OldType);
+ if (HasBits >= Bits)
+ return ExprResult(E);
+ // OK to convert to signed, because new type has more bits than old.
+ QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true);
+ return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
+ true);
+}
+
+/// \brief Check if the given expression \a E is a constant integer that fits
+/// into \a Bits bits.
+static bool FitsInto(unsigned Bits, bool Signed, Expr *E, Sema &SemaRef) {
+ if (E == nullptr)
+ return false;
+ llvm::APSInt Result;
+ if (E->isIntegerConstantExpr(Result, SemaRef.Context))
+ return Signed ? Result.isSignedIntN(Bits) : Result.isIntN(Bits);
+ return false;
}
/// \brief Called on a for stmt to check itself and nested loops (if any).
@@ -2020,7 +2588,8 @@ static Stmt *IgnoreContainerStmts(Stmt *S, bool IgnoreCaptured) {
static unsigned
CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA,
- llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA,
+ OMPLoopDirective::HelperExprs &Built) {
unsigned NestedLoopCount = 1;
if (NestedLoopCountExpr) {
// Found 'collapse' clause - calculate collapse number.
@@ -2030,18 +2599,336 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
}
// This is helper routine for loop directives (e.g., 'for', 'simd',
// 'for simd', etc.).
- Stmt *CurStmt = IgnoreContainerStmts(AStmt, true);
+ SmallVector<LoopIterationSpace, 4> IterSpaces;
+ IterSpaces.resize(NestedLoopCount);
+ Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true);
for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt,
NestedLoopCount, NestedLoopCountExpr,
- VarsWithImplicitDSA))
+ VarsWithImplicitDSA, IterSpaces[Cnt]))
return 0;
// Move on to the next nested for loop, or to the loop body.
- CurStmt = IgnoreContainerStmts(cast<ForStmt>(CurStmt)->getBody(), false);
+ // OpenMP [2.8.1, simd construct, Restrictions]
+ // All loops associated with the construct must be perfectly nested; that
+ // is, there must be no intervening code nor any OpenMP directive between
+ // any two loops.
+ CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers();
+ }
+
+ Built.clear(/* size */ NestedLoopCount);
+
+ if (SemaRef.CurContext->isDependentContext())
+ return NestedLoopCount;
+
+ // An example of what is generated for the following code:
+ //
+ // #pragma omp simd collapse(2)
+ // for (i = 0; i < NI; ++i)
+ // for (j = J0; j < NJ; j+=2) {
+ // <loop body>
+ // }
+ //
+ // We generate the code below.
+ // Note: the loop body may be outlined in CodeGen.
+ // Note: some counters may be C++ classes, operator- is used to find number of
+ // iterations and operator+= to calculate counter value.
+ // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
+ // or i64 is currently supported).
+ //
+ // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
+ // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
+ // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
+ // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
+ // // similar updates for vars in clauses (e.g. 'linear')
+ // <loop body (using local i and j)>
+ // }
+ // i = NI; // assign final values of counters
+ // j = NJ;
+ //
+
+ // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
+ // the iteration counts of the collapsed for loops.
+ auto N0 = IterSpaces[0].NumIterations;
+ ExprResult LastIteration32 = WidenIterationCount(32 /* Bits */, N0, SemaRef);
+ ExprResult LastIteration64 = WidenIterationCount(64 /* Bits */, N0, SemaRef);
+
+ if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
+ return NestedLoopCount;
+
+ auto &C = SemaRef.Context;
+ bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
+
+ Scope *CurScope = DSA.getCurScope();
+ for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
+ auto N = IterSpaces[Cnt].NumIterations;
+ AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
+ if (LastIteration32.isUsable())
+ LastIteration32 = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Mul,
+ LastIteration32.get(), N);
+ if (LastIteration64.isUsable())
+ LastIteration64 = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Mul,
+ LastIteration64.get(), N);
+ }
+
+ // Choose either the 32-bit or 64-bit version.
+ ExprResult LastIteration = LastIteration64;
+ if (LastIteration32.isUsable() &&
+ C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
+ (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
+ FitsInto(
+ 32 /* Bits */,
+ LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
+ LastIteration64.get(), SemaRef)))
+ LastIteration = LastIteration32;
+
+ if (!LastIteration.isUsable())
+ return 0;
+
+ // Save the number of iterations.
+ ExprResult NumIterations = LastIteration;
+ {
+ LastIteration = SemaRef.BuildBinOp(
+ CurScope, SourceLocation(), BO_Sub, LastIteration.get(),
+ SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
+ if (!LastIteration.isUsable())
+ return 0;
+ }
+
+ // Calculate the last iteration number beforehand instead of doing this on
+ // each iteration. Do not do this if the number of iterations may be kfold-ed.
+ llvm::APSInt Result;
+ bool IsConstant =
+ LastIteration.get()->isIntegerConstantExpr(Result, SemaRef.Context);
+ ExprResult CalcLastIteration;
+ if (!IsConstant) {
+ SourceLocation SaveLoc;
+ VarDecl *SaveVar =
+ BuildVarDecl(SemaRef, SaveLoc, LastIteration.get()->getType(),
+ ".omp.last.iteration");
+ ExprResult SaveRef = SemaRef.BuildDeclRefExpr(
+ SaveVar, LastIteration.get()->getType(), VK_LValue, SaveLoc);
+ CalcLastIteration = SemaRef.BuildBinOp(CurScope, SaveLoc, BO_Assign,
+ SaveRef.get(), LastIteration.get());
+ LastIteration = SaveRef;
+
+ // Prepare SaveRef + 1.
+ NumIterations = SemaRef.BuildBinOp(
+ CurScope, SaveLoc, BO_Add, SaveRef.get(),
+ SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
+ if (!NumIterations.isUsable())
+ return 0;
+ }
+
+ SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
+
+ // Precondition tests if there is at least one iteration (LastIteration > 0).
+ ExprResult PreCond = SemaRef.BuildBinOp(
+ CurScope, InitLoc, BO_GT, LastIteration.get(),
+ SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get());
+
+ QualType VType = LastIteration.get()->getType();
+ // Build variables passed into runtime, nesessary for worksharing directives.
+ ExprResult LB, UB, IL, ST, EUB;
+ if (isOpenMPWorksharingDirective(DKind)) {
+ // Lower bound variable, initialized with zero.
+ VarDecl *LBDecl = BuildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
+ LB = SemaRef.BuildDeclRefExpr(LBDecl, VType, VK_LValue, InitLoc);
+ SemaRef.AddInitializerToDecl(
+ LBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
+ /*DirectInit*/ false, /*TypeMayContainAuto*/ false);
+
+ // Upper bound variable, initialized with last iteration number.
+ VarDecl *UBDecl = BuildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
+ UB = SemaRef.BuildDeclRefExpr(UBDecl, VType, VK_LValue, InitLoc);
+ SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
+ /*DirectInit*/ false,
+ /*TypeMayContainAuto*/ false);
+
+ // A 32-bit variable-flag where runtime returns 1 for the last iteration.
+ // This will be used to implement clause 'lastprivate'.
+ QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
+ VarDecl *ILDecl = BuildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
+ IL = SemaRef.BuildDeclRefExpr(ILDecl, Int32Ty, VK_LValue, InitLoc);
+ SemaRef.AddInitializerToDecl(
+ ILDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
+ /*DirectInit*/ false, /*TypeMayContainAuto*/ false);
+
+ // Stride variable returned by runtime (we initialize it to 1 by default).
+ VarDecl *STDecl = BuildVarDecl(SemaRef, InitLoc, VType, ".omp.stride");
+ ST = SemaRef.BuildDeclRefExpr(STDecl, VType, VK_LValue, InitLoc);
+ SemaRef.AddInitializerToDecl(
+ STDecl, SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
+ /*DirectInit*/ false, /*TypeMayContainAuto*/ false);
+
+ // Build expression: UB = min(UB, LastIteration)
+ // It is nesessary for CodeGen of directives with static scheduling.
+ ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
+ UB.get(), LastIteration.get());
+ ExprResult CondOp = SemaRef.ActOnConditionalOp(
+ InitLoc, InitLoc, IsUBGreater.get(), LastIteration.get(), UB.get());
+ EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
+ CondOp.get());
+ EUB = SemaRef.ActOnFinishFullExpr(EUB.get());
+ }
+
+ // Build the iteration variable and its initialization before loop.
+ ExprResult IV;
+ ExprResult Init;
+ {
+ VarDecl *IVDecl = BuildVarDecl(SemaRef, InitLoc, VType, ".omp.iv");
+ IV = SemaRef.BuildDeclRefExpr(IVDecl, VType, VK_LValue, InitLoc);
+ Expr *RHS = isOpenMPWorksharingDirective(DKind)
+ ? LB.get()
+ : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
+ Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
+ Init = SemaRef.ActOnFinishFullExpr(Init.get());
}
- // FIXME: Build resulting iteration space for IR generation (collapsing
- // iteration spaces when loop count > 1 ('collapse' clause)).
+ // Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops.
+ SourceLocation CondLoc;
+ ExprResult Cond =
+ isOpenMPWorksharingDirective(DKind)
+ ? SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get())
+ : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
+ NumIterations.get());
+ // Loop condition with 1 iteration separated (IV < LastIteration)
+ ExprResult SeparatedCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT,
+ IV.get(), LastIteration.get());
+
+ // Loop increment (IV = IV + 1)
+ SourceLocation IncLoc;
+ ExprResult Inc =
+ SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
+ SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
+ if (!Inc.isUsable())
+ return 0;
+ Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
+ Inc = SemaRef.ActOnFinishFullExpr(Inc.get());
+ if (!Inc.isUsable())
+ return 0;
+
+ // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
+ // Used for directives with static scheduling.
+ ExprResult NextLB, NextUB;
+ if (isOpenMPWorksharingDirective(DKind)) {
+ // LB + ST
+ NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
+ if (!NextLB.isUsable())
+ return 0;
+ // LB = LB + ST
+ NextLB =
+ SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
+ NextLB = SemaRef.ActOnFinishFullExpr(NextLB.get());
+ if (!NextLB.isUsable())
+ return 0;
+ // UB + ST
+ NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
+ if (!NextUB.isUsable())
+ return 0;
+ // UB = UB + ST
+ NextUB =
+ SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
+ NextUB = SemaRef.ActOnFinishFullExpr(NextUB.get());
+ if (!NextUB.isUsable())
+ return 0;
+ }
+
+ // Build updates and final values of the loop counters.
+ bool HasErrors = false;
+ Built.Counters.resize(NestedLoopCount);
+ Built.Updates.resize(NestedLoopCount);
+ Built.Finals.resize(NestedLoopCount);
+ {
+ ExprResult Div;
+ // Go from inner nested loop to outer.
+ for (int Cnt = NestedLoopCount - 1; Cnt >= 0; --Cnt) {
+ LoopIterationSpace &IS = IterSpaces[Cnt];
+ SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
+ // Build: Iter = (IV / Div) % IS.NumIters
+ // where Div is product of previous iterations' IS.NumIters.
+ ExprResult Iter;
+ if (Div.isUsable()) {
+ Iter =
+ SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, IV.get(), Div.get());
+ } else {
+ Iter = IV;
+ assert((Cnt == (int)NestedLoopCount - 1) &&
+ "unusable div expected on first iteration only");
+ }
+
+ if (Cnt != 0 && Iter.isUsable())
+ Iter = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Rem, Iter.get(),
+ IS.NumIterations);
+ if (!Iter.isUsable()) {
+ HasErrors = true;
+ break;
+ }
+
+ // Build update: IS.CounterVar = IS.Start + Iter * IS.Step
+ ExprResult Update =
+ BuildCounterUpdate(SemaRef, CurScope, UpdLoc, IS.CounterVar,
+ IS.CounterInit, Iter, IS.CounterStep, IS.Subtract);
+ if (!Update.isUsable()) {
+ HasErrors = true;
+ break;
+ }
+
+ // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
+ ExprResult Final = BuildCounterUpdate(
+ SemaRef, CurScope, UpdLoc, IS.CounterVar, IS.CounterInit,
+ IS.NumIterations, IS.CounterStep, IS.Subtract);
+ if (!Final.isUsable()) {
+ HasErrors = true;
+ break;
+ }
+
+ // Build Div for the next iteration: Div <- Div * IS.NumIters
+ if (Cnt != 0) {
+ if (Div.isUnset())
+ Div = IS.NumIterations;
+ else
+ Div = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Div.get(),
+ IS.NumIterations);
+
+ // Add parentheses (for debugging purposes only).
+ if (Div.isUsable())
+ Div = SemaRef.ActOnParenExpr(UpdLoc, UpdLoc, Div.get());
+ if (!Div.isUsable()) {
+ HasErrors = true;
+ break;
+ }
+ }
+ if (!Update.isUsable() || !Final.isUsable()) {
+ HasErrors = true;
+ break;
+ }
+ // Save results
+ Built.Counters[Cnt] = IS.CounterVar;
+ Built.Updates[Cnt] = Update.get();
+ Built.Finals[Cnt] = Final.get();
+ }
+ }
+
+ if (HasErrors)
+ return 0;
+
+ // Save results
+ Built.IterationVarRef = IV.get();
+ Built.LastIteration = LastIteration.get();
+ Built.CalcLastIteration = CalcLastIteration.get();
+ Built.PreCond = PreCond.get();
+ Built.Cond = Cond.get();
+ Built.SeparatedCond = SeparatedCond.get();
+ Built.Init = Init.get();
+ Built.Inc = Inc.get();
+ Built.LB = LB.get();
+ Built.UB = UB.get();
+ Built.IL = IL.get();
+ Built.ST = ST.get();
+ Built.EUB = EUB.get();
+ Built.NLB = NextLB.get();
+ Built.NUB = NextUB.get();
+
return NestedLoopCount;
}
@@ -2060,32 +2947,60 @@ StmtResult Sema::ActOnOpenMPSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse', it will define the nested loops number.
unsigned NestedLoopCount =
CheckOpenMPLoop(OMPD_simd, GetCollapseNumberExpr(Clauses), AStmt, *this,
- *DSAStack, VarsWithImplicitDSA);
+ *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp simd loop exprs were not built");
+
getCurFunction()->setHasBranchProtectedScope();
return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
- Clauses, AStmt);
+ Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse', it will define the nested loops number.
unsigned NestedLoopCount =
CheckOpenMPLoop(OMPD_for, GetCollapseNumberExpr(Clauses), AStmt, *this,
- *DSAStack, VarsWithImplicitDSA);
+ *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp for loop exprs were not built");
+
getCurFunction()->setHasBranchProtectedScope();
return OMPForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
- Clauses, AStmt);
+ Clauses, AStmt, B);
+}
+
+StmtResult Sema::ActOnOpenMPForSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse', it will define the nested loops number.
+ unsigned NestedLoopCount =
+ CheckOpenMPLoop(OMPD_for_simd, GetCollapseNumberExpr(Clauses), AStmt,
+ *this, *DSAStack, VarsWithImplicitDSA, B);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp for simd loop exprs were not built");
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
+ Clauses, AStmt, B);
}
StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
@@ -2178,16 +3093,46 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
+ OMPLoopDirective::HelperExprs B;
// In presence of clause 'collapse', it will define the nested loops number.
unsigned NestedLoopCount =
CheckOpenMPLoop(OMPD_parallel_for, GetCollapseNumberExpr(Clauses), AStmt,
- *this, *DSAStack, VarsWithImplicitDSA);
+ *this, *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp parallel for loop exprs were not built");
+
getCurFunction()->setHasBranchProtectedScope();
return OMPParallelForDirective::Create(Context, StartLoc, EndLoc,
- NestedLoopCount, Clauses, AStmt);
+ NestedLoopCount, Clauses, AStmt, B);
+}
+
+StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse', it will define the nested loops number.
+ unsigned NestedLoopCount =
+ CheckOpenMPLoop(OMPD_parallel_for_simd, GetCollapseNumberExpr(Clauses),
+ AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPParallelForSimdDirective::Create(
+ Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
StmtResult
@@ -2264,6 +3209,271 @@ StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);
}
+StmtResult Sema::ActOnOpenMPOrderedDirective(Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, AStmt);
+}
+
+StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ auto CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ // TODO further analysis of associated statements and clauses.
+ OpenMPClauseKind AtomicKind = OMPC_unknown;
+ SourceLocation AtomicKindLoc;
+ for (auto *C : Clauses) {
+ if (C->getClauseKind() == OMPC_read || C->getClauseKind() == OMPC_write ||
+ C->getClauseKind() == OMPC_update ||
+ C->getClauseKind() == OMPC_capture) {
+ if (AtomicKind != OMPC_unknown) {
+ Diag(C->getLocStart(), diag::err_omp_atomic_several_clauses)
+ << SourceRange(C->getLocStart(), C->getLocEnd());
+ Diag(AtomicKindLoc, diag::note_omp_atomic_previous_clause)
+ << getOpenMPClauseName(AtomicKind);
+ } else {
+ AtomicKind = C->getClauseKind();
+ AtomicKindLoc = C->getLocStart();
+ }
+ }
+ }
+
+ auto Body = CS->getCapturedStmt();
+ Expr *X = nullptr;
+ Expr *V = nullptr;
+ Expr *E = nullptr;
+ // OpenMP [2.12.6, atomic Construct]
+ // In the next expressions:
+ // * x and v (as applicable) are both l-value expressions with scalar type.
+ // * During the execution of an atomic region, multiple syntactic
+ // occurrences of x must designate the same storage location.
+ // * Neither of v and expr (as applicable) may access the storage location
+ // designated by x.
+ // * Neither of x and expr (as applicable) may access the storage location
+ // designated by v.
+ // * expr is an expression with scalar type.
+ // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
+ // * binop, binop=, ++, and -- are not overloaded operators.
+ // * The expression x binop expr must be numerically equivalent to x binop
+ // (expr). This requirement is satisfied if the operators in expr have
+ // precedence greater than binop, or by using parentheses around expr or
+ // subexpressions of expr.
+ // * The expression expr binop x must be numerically equivalent to (expr)
+ // binop x. This requirement is satisfied if the operators in expr have
+ // precedence equal to or greater than binop, or by using parentheses around
+ // expr or subexpressions of expr.
+ // * For forms that allow multiple occurrences of x, the number of times
+ // that x is evaluated is unspecified.
+ enum {
+ NotAnExpression,
+ NotAnAssignmentOp,
+ NotAScalarType,
+ NotAnLValue,
+ NoError
+ } ErrorFound = NoError;
+ if (AtomicKind == OMPC_read) {
+ SourceLocation ErrorLoc, NoteLoc;
+ SourceRange ErrorRange, NoteRange;
+ // If clause is read:
+ // v = x;
+ if (auto AtomicBody = dyn_cast<Expr>(Body)) {
+ auto AtomicBinOp =
+ dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
+ if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
+ X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
+ V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
+ if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
+ (V->isInstantiationDependent() || V->getType()->isScalarType())) {
+ if (!X->isLValue() || !V->isLValue()) {
+ auto NotLValueExpr = X->isLValue() ? V : X;
+ ErrorFound = NotAnLValue;
+ ErrorLoc = AtomicBinOp->getExprLoc();
+ ErrorRange = AtomicBinOp->getSourceRange();
+ NoteLoc = NotLValueExpr->getExprLoc();
+ NoteRange = NotLValueExpr->getSourceRange();
+ }
+ } else if (!X->isInstantiationDependent() ||
+ !V->isInstantiationDependent()) {
+ auto NotScalarExpr =
+ (X->isInstantiationDependent() || X->getType()->isScalarType())
+ ? V
+ : X;
+ ErrorFound = NotAScalarType;
+ ErrorLoc = AtomicBinOp->getExprLoc();
+ ErrorRange = AtomicBinOp->getSourceRange();
+ NoteLoc = NotScalarExpr->getExprLoc();
+ NoteRange = NotScalarExpr->getSourceRange();
+ }
+ } else {
+ ErrorFound = NotAnAssignmentOp;
+ ErrorLoc = AtomicBody->getExprLoc();
+ ErrorRange = AtomicBody->getSourceRange();
+ NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
+ : AtomicBody->getExprLoc();
+ NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
+ : AtomicBody->getSourceRange();
+ }
+ } else {
+ ErrorFound = NotAnExpression;
+ NoteLoc = ErrorLoc = Body->getLocStart();
+ NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
+ }
+ if (ErrorFound != NoError) {
+ Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
+ << ErrorRange;
+ Diag(NoteLoc, diag::note_omp_atomic_read_write) << ErrorFound
+ << NoteRange;
+ return StmtError();
+ } else if (CurContext->isDependentContext())
+ V = X = nullptr;
+ } else if (AtomicKind == OMPC_write) {
+ SourceLocation ErrorLoc, NoteLoc;
+ SourceRange ErrorRange, NoteRange;
+ // If clause is write:
+ // x = expr;
+ if (auto AtomicBody = dyn_cast<Expr>(Body)) {
+ auto AtomicBinOp =
+ dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
+ if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
+ X = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
+ E = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
+ if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
+ (E->isInstantiationDependent() || E->getType()->isScalarType())) {
+ if (!X->isLValue()) {
+ ErrorFound = NotAnLValue;
+ ErrorLoc = AtomicBinOp->getExprLoc();
+ ErrorRange = AtomicBinOp->getSourceRange();
+ NoteLoc = X->getExprLoc();
+ NoteRange = X->getSourceRange();
+ }
+ } else if (!X->isInstantiationDependent() ||
+ !E->isInstantiationDependent()) {
+ auto NotScalarExpr =
+ (X->isInstantiationDependent() || X->getType()->isScalarType())
+ ? E
+ : X;
+ ErrorFound = NotAScalarType;
+ ErrorLoc = AtomicBinOp->getExprLoc();
+ ErrorRange = AtomicBinOp->getSourceRange();
+ NoteLoc = NotScalarExpr->getExprLoc();
+ NoteRange = NotScalarExpr->getSourceRange();
+ }
+ } else {
+ ErrorFound = NotAnAssignmentOp;
+ ErrorLoc = AtomicBody->getExprLoc();
+ ErrorRange = AtomicBody->getSourceRange();
+ NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
+ : AtomicBody->getExprLoc();
+ NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
+ : AtomicBody->getSourceRange();
+ }
+ } else {
+ ErrorFound = NotAnExpression;
+ NoteLoc = ErrorLoc = Body->getLocStart();
+ NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
+ }
+ if (ErrorFound != NoError) {
+ Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
+ << ErrorRange;
+ Diag(NoteLoc, diag::note_omp_atomic_read_write) << ErrorFound
+ << NoteRange;
+ return StmtError();
+ } else if (CurContext->isDependentContext())
+ E = X = nullptr;
+ } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
+ if (!isa<Expr>(Body)) {
+ Diag(Body->getLocStart(),
+ diag::err_omp_atomic_update_not_expression_statement)
+ << (AtomicKind == OMPC_update);
+ return StmtError();
+ }
+ } else if (AtomicKind == OMPC_capture) {
+ if (isa<Expr>(Body) && !isa<BinaryOperator>(Body)) {
+ Diag(Body->getLocStart(),
+ diag::err_omp_atomic_capture_not_expression_statement);
+ return StmtError();
+ } else if (!isa<Expr>(Body) && !isa<CompoundStmt>(Body)) {
+ Diag(Body->getLocStart(),
+ diag::err_omp_atomic_capture_not_compound_statement);
+ return StmtError();
+ }
+ }
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPAtomicDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
+ X, V, E);
+}
+
+StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+
+ // OpenMP [2.16, Nesting of Regions]
+ // If specified, a teams construct must be contained within a target
+ // construct. That target construct must contain no statements or directives
+ // outside of the teams construct.
+ if (DSAStack->hasInnerTeamsRegion()) {
+ auto S = AStmt->IgnoreContainers(/*IgnoreCaptured*/ true);
+ bool OMPTeamsFound = true;
+ if (auto *CS = dyn_cast<CompoundStmt>(S)) {
+ auto I = CS->body_begin();
+ while (I != CS->body_end()) {
+ auto OED = dyn_cast<OMPExecutableDirective>(*I);
+ if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind())) {
+ OMPTeamsFound = false;
+ break;
+ }
+ ++I;
+ }
+ assert(I != CS->body_end() && "Not found statement");
+ S = *I;
+ }
+ if (!OMPTeamsFound) {
+ Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
+ Diag(DSAStack->getInnerTeamsRegionLoc(),
+ diag::note_omp_nested_teams_construct_here);
+ Diag(S->getLocStart(), diag::note_omp_nested_statement_here)
+ << isa<OMPExecutableDirective>(S);
+ return StmtError();
+ }
+ }
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
+}
+
+StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
+}
+
OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -2303,6 +3513,11 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_flush:
+ case OMPC_read:
+ case OMPC_write:
+ case OMPC_update:
+ case OMPC_capture:
+ case OMPC_seq_cst:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -2345,7 +3560,6 @@ OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition,
return new (Context) OMPFinalClause(ValExpr, StartLoc, LParenLoc, EndLoc);
}
-
ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
Expr *Op) {
if (!Op)
@@ -2396,7 +3610,6 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
SourceLocation EndLoc) {
Expr *ValExpr = NumThreads;
if (!NumThreads->isValueDependent() && !NumThreads->isTypeDependent() &&
- !NumThreads->isInstantiationDependent() &&
!NumThreads->containsUnexpandedParameterPack()) {
SourceLocation NumThreadsLoc = NumThreads->getLocStart();
ExprResult Val =
@@ -2437,6 +3650,11 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
<< getOpenMPClauseName(CKind) << E->getSourceRange();
return ExprError();
}
+ if (CKind == OMPC_aligned && !Result.isPowerOf2()) {
+ Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
+ << E->getSourceRange();
+ return ExprError();
+ }
return ICE;
}
@@ -2506,6 +3724,11 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_flush:
+ case OMPC_read:
+ case OMPC_write:
+ case OMPC_update:
+ case OMPC_capture:
+ case OMPC_seq_cst:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -2621,6 +3844,11 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_flush:
+ case OMPC_read:
+ case OMPC_write:
+ case OMPC_update:
+ case OMPC_capture:
+ case OMPC_seq_cst:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -2700,6 +3928,21 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_mergeable:
Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
break;
+ case OMPC_read:
+ Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
+ break;
+ case OMPC_write:
+ Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
+ break;
+ case OMPC_update:
+ Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
+ break;
+ case OMPC_capture:
+ Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
+ break;
+ case OMPC_seq_cst:
+ Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
@@ -2727,6 +3970,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
SourceLocation EndLoc) {
+ DSAStack->setOrderedRegion();
return new (Context) OMPOrderedClause(StartLoc, EndLoc);
}
@@ -2745,6 +3989,31 @@ OMPClause *Sema::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
return new (Context) OMPMergeableClause(StartLoc, EndLoc);
}
+OMPClause *Sema::ActOnOpenMPReadClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPReadClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPWriteClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPWriteClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPUpdateClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPCaptureClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPSeqCstClause(StartLoc, EndLoc);
+}
+
OMPClause *Sema::ActOnOpenMPVarListClause(
OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
@@ -2798,6 +4067,11 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
+ case OMPC_read:
+ case OMPC_write:
+ case OMPC_update:
+ case OMPC_capture:
+ case OMPC_seq_cst:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -2809,11 +4083,13 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> PrivateCopies;
for (auto &RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP private clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ PrivateCopies.push_back(nullptr);
continue;
}
@@ -2835,6 +4111,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
if (Type->isDependentType() || Type->isInstantiationDependentType()) {
// It will be analyzed later.
Vars.push_back(DE);
+ PrivateCopies.push_back(nullptr);
continue;
}
@@ -2860,54 +4137,8 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
// A variable of class type (or array thereof) that appears in a private
// clause requires an accessible, unambiguous default constructor for the
// class type.
- while (Type.getNonReferenceType()->isArrayType()) {
- Type = cast<ArrayType>(Type.getNonReferenceType().getTypePtr())
- ->getElementType();
- }
- CXXRecordDecl *RD = getLangOpts().CPlusPlus
- ? Type.getNonReferenceType()->getAsCXXRecordDecl()
- : nullptr;
- // FIXME This code must be replaced by actual constructing/destructing of
- // the private variable.
- if (RD) {
- CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
- PartialDiagnostic PD =
- PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
- if (!CD ||
- CheckConstructorAccess(ELoc, CD,
- InitializedEntity::InitializeTemporary(Type),
- CD->getAccess(), PD) == AR_inaccessible ||
- CD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_private) << 0;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
- }
- MarkFunctionReferenced(ELoc, CD);
- DiagnoseUseOfDecl(CD, ELoc);
-
- CXXDestructorDecl *DD = RD->getDestructor();
- if (DD) {
- if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
- DD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_private) << 4;
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
- }
- MarkFunctionReferenced(ELoc, DD);
- DiagnoseUseOfDecl(DD, ELoc);
- }
+ while (Type->isArrayType()) {
+ Type = cast<ArrayType>(Type.getTypePtr())->getElementType();
}
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -2925,14 +4156,59 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
continue;
}
+ // Generate helper private variable and initialize it with the default
+ // value. The address of the original variable is replaced by the address of
+ // the new private variable in CodeGen. This new variable is not added to
+ // IdResolver, so the code in the OpenMP region uses original variable for
+ // proper diagnostics.
+ auto VDPrivate =
+ VarDecl::Create(Context, CurContext, DE->getLocStart(),
+ DE->getExprLoc(), VD->getIdentifier(), VD->getType(),
+ VD->getTypeSourceInfo(), /*S*/ SC_Auto);
+ ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto*/ false);
+ if (VDPrivate->isInvalidDecl())
+ continue;
+ CurContext->addDecl(VDPrivate);
+ auto VDPrivateRefExpr =
+ DeclRefExpr::Create(Context, /*QualifierLoc*/ NestedNameSpecifierLoc(),
+ /*TemplateKWLoc*/ SourceLocation(), VDPrivate,
+ /*RefersToEnclosingVariableOrCapture*/ false,
+ /*NameLoc*/ SourceLocation(), DE->getType(),
+ /*VK*/ VK_LValue);
+
DSAStack->addDSA(VD, DE, OMPC_private);
Vars.push_back(DE);
+ PrivateCopies.push_back(VDPrivateRefExpr);
}
if (Vars.empty())
return nullptr;
- return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
+ return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
+ PrivateCopies);
+}
+
+namespace {
+class DiagsUninitializedSeveretyRAII {
+private:
+ DiagnosticsEngine &Diags;
+ SourceLocation SavedLoc;
+ bool IsIgnored;
+
+public:
+ DiagsUninitializedSeveretyRAII(DiagnosticsEngine &Diags, SourceLocation Loc,
+ bool IsIgnored)
+ : Diags(Diags), SavedLoc(Loc), IsIgnored(IsIgnored) {
+ if (!IsIgnored) {
+ Diags.setSeverity(/*Diag*/ diag::warn_uninit_self_reference_in_init,
+ /*Map*/ diag::Severity::Ignored, Loc);
+ }
+ }
+ ~DiagsUninitializedSeveretyRAII() {
+ if (!IsIgnored)
+ Diags.popMappings(SavedLoc);
+ }
+};
}
OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
@@ -2940,6 +4216,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> PrivateCopies;
+ SmallVector<Expr *, 8> Inits;
bool IsImplicitClause =
StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
auto ImplicitClauseLoc = DSAStack->getConstructLoc();
@@ -2949,11 +4227,13 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ PrivateCopies.push_back(nullptr);
+ Inits.push_back(nullptr);
continue;
}
- SourceLocation ELoc = IsImplicitClause ? ImplicitClauseLoc
- : RefExpr->getExprLoc();
+ SourceLocation ELoc =
+ IsImplicitClause ? ImplicitClauseLoc : RefExpr->getExprLoc();
// OpenMP [2.1, C/C++]
// A list item is a variable name.
// OpenMP [2.9.3.3, Restrictions, p.1]
@@ -2971,6 +4251,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
if (Type->isDependentType() || Type->isInstantiationDependentType()) {
// It will be analyzed later.
Vars.push_back(DE);
+ PrivateCopies.push_back(nullptr);
+ Inits.push_back(nullptr);
continue;
}
@@ -3004,65 +4286,6 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// clause requires an accessible, unambiguous copy constructor for the
// class type.
Type = Context.getBaseElementType(Type);
- CXXRecordDecl *RD = getLangOpts().CPlusPlus
- ? Type.getNonReferenceType()->getAsCXXRecordDecl()
- : nullptr;
- // FIXME This code must be replaced by actual constructing/destructing of
- // the firstprivate variable.
- if (RD) {
- CXXConstructorDecl *CD = LookupCopyingConstructor(RD, 0);
- PartialDiagnostic PD =
- PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
- if (!CD ||
- CheckConstructorAccess(ELoc, CD,
- InitializedEntity::InitializeTemporary(Type),
- CD->getAccess(), PD) == AR_inaccessible ||
- CD->isDeleted()) {
- if (IsImplicitClause) {
- Diag(ImplicitClauseLoc,
- diag::err_omp_task_predetermined_firstprivate_required_method)
- << 0;
- Diag(RefExpr->getExprLoc(), diag::note_used_here);
- } else {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_firstprivate) << 1;
- }
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
- }
- MarkFunctionReferenced(ELoc, CD);
- DiagnoseUseOfDecl(CD, ELoc);
-
- CXXDestructorDecl *DD = RD->getDestructor();
- if (DD) {
- if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
- DD->isDeleted()) {
- if (IsImplicitClause) {
- Diag(ImplicitClauseLoc,
- diag::err_omp_task_predetermined_firstprivate_required_method)
- << 1;
- Diag(RefExpr->getExprLoc(), diag::note_used_here);
- } else {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_firstprivate) << 4;
- }
- bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
- VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- Diag(RD->getLocation(), diag::note_previous_decl) << RD;
- continue;
- }
- MarkFunctionReferenced(ELoc, DD);
- DiagnoseUseOfDecl(DD, ELoc);
- }
- }
// If an implicit firstprivate variable found it was checked already.
if (!IsImplicitClause) {
@@ -3152,15 +4375,75 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
}
}
+ Type = Type.getUnqualifiedType();
+ auto VDPrivate = VarDecl::Create(Context, CurContext, DE->getLocStart(),
+ ELoc, VD->getIdentifier(), VD->getType(),
+ VD->getTypeSourceInfo(), /*S*/ SC_Auto);
+ // Generate helper private variable and initialize it with the value of the
+ // original variable. The address of the original variable is replaced by
+ // the address of the new private variable in the CodeGen. This new variable
+ // is not added to IdResolver, so the code in the OpenMP region uses
+ // original variable for proper diagnostics and variable capturing.
+ Expr *VDInitRefExpr = nullptr;
+ // For arrays generate initializer for single element and replace it by the
+ // original array element in CodeGen.
+ if (DE->getType()->isArrayType()) {
+ auto VDInit = VarDecl::Create(Context, CurContext, DE->getLocStart(),
+ ELoc, VD->getIdentifier(), Type,
+ VD->getTypeSourceInfo(), /*S*/ SC_Auto);
+ CurContext->addHiddenDecl(VDInit);
+ VDInitRefExpr = DeclRefExpr::Create(
+ Context, /*QualifierLoc*/ NestedNameSpecifierLoc(),
+ /*TemplateKWLoc*/ SourceLocation(), VDInit,
+ /*RefersToEnclosingVariableOrCapture*/ true, ELoc, Type,
+ /*VK*/ VK_LValue);
+ VDInit->setIsUsed();
+ auto Init = DefaultLvalueConversion(VDInitRefExpr).get();
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(VDInit);
+ InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
+
+ InitializationSequence InitSeq(*this, Entity, Kind, Init);
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Init);
+ if (Result.isInvalid())
+ VDPrivate->setInvalidDecl();
+ else
+ VDPrivate->setInit(Result.getAs<Expr>());
+ } else {
+ AddInitializerToDecl(
+ VDPrivate,
+ DefaultLvalueConversion(
+ DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
+ SourceLocation(), DE->getDecl(),
+ /*RefersToEnclosingVariableOrCapture=*/true,
+ DE->getExprLoc(), DE->getType(),
+ /*VK=*/VK_LValue)).get(),
+ /*DirectInit=*/false, /*TypeMayContainAuto=*/false);
+ }
+ if (VDPrivate->isInvalidDecl()) {
+ if (IsImplicitClause) {
+ Diag(DE->getExprLoc(),
+ diag::note_omp_task_predetermined_firstprivate_here);
+ }
+ continue;
+ }
+ CurContext->addDecl(VDPrivate);
+ auto VDPrivateRefExpr =
+ DeclRefExpr::Create(Context, /*QualifierLoc*/ NestedNameSpecifierLoc(),
+ /*TemplateKWLoc*/ SourceLocation(), VDPrivate,
+ /*RefersToEnclosingVariableOrCapture*/ false,
+ DE->getLocStart(), DE->getType(),
+ /*VK*/ VK_LValue);
DSAStack->addDSA(VD, DE, OMPC_firstprivate);
Vars.push_back(DE);
+ PrivateCopies.push_back(VDPrivateRefExpr);
+ Inits.push_back(VDInitRefExpr);
}
if (Vars.empty())
return nullptr;
return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
- Vars);
+ Vars, PrivateCopies, Inits);
}
OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
@@ -4099,4 +5382,3 @@ OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
}
-#undef DSAStack
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 03001d89f07e..9195ee59075d 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -35,7 +35,7 @@
#include <algorithm>
#include <cstdlib>
-namespace clang {
+using namespace clang;
using namespace sema;
/// A convenience routine for creating a decayed reference to a function.
@@ -102,43 +102,9 @@ CompareDerivedToBaseConversions(Sema &S,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2);
-
-
-/// GetConversionCategory - Retrieve the implicit conversion
-/// category corresponding to the given implicit conversion kind.
-ImplicitConversionCategory
-GetConversionCategory(ImplicitConversionKind Kind) {
- static const ImplicitConversionCategory
- Category[(int)ICK_Num_Conversion_Kinds] = {
- ICC_Identity,
- ICC_Lvalue_Transformation,
- ICC_Lvalue_Transformation,
- ICC_Lvalue_Transformation,
- ICC_Identity,
- ICC_Qualification_Adjustment,
- ICC_Promotion,
- ICC_Promotion,
- ICC_Promotion,
- ICC_Conversion,
- ICC_Conversion,
- ICC_Conversion,
- ICC_Conversion,
- ICC_Conversion,
- ICC_Conversion,
- ICC_Conversion,
- ICC_Conversion,
- ICC_Conversion,
- ICC_Conversion,
- ICC_Conversion,
- ICC_Conversion,
- ICC_Conversion
- };
- return Category[(int)Kind];
-}
-
/// GetConversionRank - Retrieve the implicit conversion rank
/// corresponding to the given implicit conversion kind.
-ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) {
+ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) {
static const ImplicitConversionRank
Rank[(int)ICK_Num_Conversion_Kinds] = {
ICR_Exact_Match,
@@ -171,7 +137,7 @@ ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) {
/// GetImplicitConversionName - Return the name of this kind of
/// implicit conversion.
-const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
+static const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
static const char* const Name[(int)ICK_Num_Conversion_Kinds] = {
"No conversion",
"Lvalue-to-rvalue",
@@ -195,7 +161,7 @@ const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
"Vector splat",
"Complex-real conversion",
"Block Pointer conversion",
- "Transparent Union Conversion"
+ "Transparent Union Conversion",
"Writeback conversion"
};
return Name[Kind];
@@ -568,9 +534,10 @@ namespace {
/// \brief Convert from Sema's representation of template deduction information
/// to the form used in overload-candidate information.
-DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context,
- Sema::TemplateDeductionResult TDK,
- TemplateDeductionInfo &Info) {
+DeductionFailureInfo
+clang::MakeDeductionFailureInfo(ASTContext &Context,
+ Sema::TemplateDeductionResult TDK,
+ TemplateDeductionInfo &Info) {
DeductionFailureInfo Result;
Result.Result = static_cast<unsigned>(TDK);
Result.HasDiagnostic = false;
@@ -1067,7 +1034,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
// is a redeclaration of OldMethod.
unsigned OldQuals = OldMethod->getTypeQualifiers();
unsigned NewQuals = NewMethod->getTypeQualifiers();
- if (!getLangOpts().CPlusPlus1y && NewMethod->isConstexpr() &&
+ if (!getLangOpts().CPlusPlus14 && NewMethod->isConstexpr() &&
!isa<CXXConstructorDecl>(NewMethod))
NewQuals |= Qualifiers::Const;
@@ -1268,11 +1235,11 @@ Sema::TryImplicitConversion(Expr *From, QualType ToType,
bool InOverloadResolution,
bool CStyle,
bool AllowObjCWritebackConversion) {
- return clang::TryImplicitConversion(*this, From, ToType,
- SuppressUserConversions, AllowExplicit,
- InOverloadResolution, CStyle,
- AllowObjCWritebackConversion,
- /*AllowObjCConversionOnExplicit=*/false);
+ return ::TryImplicitConversion(*this, From, ToType,
+ SuppressUserConversions, AllowExplicit,
+ InOverloadResolution, CStyle,
+ AllowObjCWritebackConversion,
+ /*AllowObjCConversionOnExplicit=*/false);
}
/// PerformImplicitConversion - Perform an implicit conversion of the
@@ -1301,13 +1268,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
if (getLangOpts().ObjC1)
CheckObjCBridgeRelatedConversions(From->getLocStart(),
ToType, From->getType(), From);
- ICS = clang::TryImplicitConversion(*this, From, ToType,
- /*SuppressUserConversions=*/false,
- AllowExplicit,
- /*InOverloadResolution=*/false,
- /*CStyle=*/false,
- AllowObjCWritebackConversion,
- /*AllowObjCConversionOnExplicit=*/false);
+ ICS = ::TryImplicitConversion(*this, From, ToType,
+ /*SuppressUserConversions=*/false,
+ AllowExplicit,
+ /*InOverloadResolution=*/false,
+ /*CStyle=*/false,
+ AllowObjCWritebackConversion,
+ /*AllowObjCConversionOnExplicit=*/false);
return PerformImplicitConversion(From, ToType, ICS, Action);
}
@@ -1451,6 +1418,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// We were able to resolve the address of the overloaded function,
// so we can convert to the type of that function.
FromType = Fn->getType();
+ SCS.setFromType(FromType);
// we can sometimes resolve &foo<int> regardless of ToType, so check
// if the type matches (identity) or we are converting to bool
@@ -3656,7 +3624,7 @@ CompareStandardConversionSequences(Sema &S,
/// CompareQualificationConversions - Compares two standard conversion
/// sequences to determine whether they can be ranked based on their
/// qualification conversions (C++ 13.3.3.2p3 bullet 3).
-ImplicitConversionSequence::CompareKind
+static ImplicitConversionSequence::CompareKind
CompareQualificationConversions(Sema &S,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2) {
@@ -3769,7 +3737,7 @@ CompareQualificationConversions(Sema &S,
/// various kinds of derived-to-base conversions (C++
/// [over.ics.rank]p4b3). As part of these checks, we also look at
/// conversions between Objective-C interface types.
-ImplicitConversionSequence::CompareKind
+static ImplicitConversionSequence::CompareKind
CompareDerivedToBaseConversions(Sema &S,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2) {
@@ -4849,9 +4817,8 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
// Note that we always use the true parent context when performing
// the actual argument initialization.
- ImplicitConversionSequence ICS
- = TryObjectArgumentInitialization(*this, From->getType(), FromClassification,
- Method, Method->getParent());
+ ImplicitConversionSequence ICS = TryObjectArgumentInitialization(
+ *this, From->getType(), FromClassification, Method, Method->getParent());
if (ICS.isBad()) {
if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) {
Qualifiers FromQs = FromRecordType.getQualifiers();
@@ -4927,41 +4894,51 @@ static bool CheckConvertedConstantConversions(Sema &S,
// conversions are fine.
switch (SCS.Second) {
case ICK_Identity:
+ case ICK_NoReturn_Adjustment:
case ICK_Integral_Promotion:
- case ICK_Integral_Conversion:
- case ICK_Zero_Event_Conversion:
+ case ICK_Integral_Conversion: // Narrowing conversions are checked elsewhere.
return true;
case ICK_Boolean_Conversion:
// Conversion from an integral or unscoped enumeration type to bool is
- // classified as ICK_Boolean_Conversion, but it's also an integral
- // conversion, so it's permitted in a converted constant expression.
+ // classified as ICK_Boolean_Conversion, but it's also arguably an integral
+ // conversion, so we allow it in a converted constant expression.
+ //
+ // FIXME: Per core issue 1407, we should not allow this, but that breaks
+ // a lot of popular code. We should at least add a warning for this
+ // (non-conforming) extension.
return SCS.getFromType()->isIntegralOrUnscopedEnumerationType() &&
SCS.getToType(2)->isBooleanType();
+ case ICK_Pointer_Conversion:
+ case ICK_Pointer_Member:
+ // C++1z: null pointer conversions and null member pointer conversions are
+ // only permitted if the source type is std::nullptr_t.
+ return SCS.getFromType()->isNullPtrType();
+
+ case ICK_Floating_Promotion:
+ case ICK_Complex_Promotion:
+ case ICK_Floating_Conversion:
+ case ICK_Complex_Conversion:
case ICK_Floating_Integral:
+ case ICK_Compatible_Conversion:
+ case ICK_Derived_To_Base:
+ case ICK_Vector_Conversion:
+ case ICK_Vector_Splat:
case ICK_Complex_Real:
+ case ICK_Block_Pointer_Conversion:
+ case ICK_TransparentUnionConversion:
+ case ICK_Writeback_Conversion:
+ case ICK_Zero_Event_Conversion:
return false;
case ICK_Lvalue_To_Rvalue:
case ICK_Array_To_Pointer:
case ICK_Function_To_Pointer:
- case ICK_NoReturn_Adjustment:
+ llvm_unreachable("found a first conversion kind in Second");
+
case ICK_Qualification:
- case ICK_Compatible_Conversion:
- case ICK_Vector_Conversion:
- case ICK_Vector_Splat:
- case ICK_Derived_To_Base:
- case ICK_Pointer_Conversion:
- case ICK_Pointer_Member:
- case ICK_Block_Pointer_Conversion:
- case ICK_Writeback_Conversion:
- case ICK_Floating_Promotion:
- case ICK_Complex_Promotion:
- case ICK_Complex_Conversion:
- case ICK_Floating_Conversion:
- case ICK_TransparentUnionConversion:
- llvm_unreachable("unexpected second conversion kind");
+ llvm_unreachable("found a third conversion kind in Second");
case ICK_Num_Conversion_Kinds:
break;
@@ -4973,67 +4950,71 @@ static bool CheckConvertedConstantConversions(Sema &S,
/// CheckConvertedConstantExpression - Check that the expression From is a
/// converted constant expression of type T, perform the conversion and produce
/// the converted expression, per C++11 [expr.const]p3.
-ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
- llvm::APSInt &Value,
- CCEKind CCE) {
- assert(LangOpts.CPlusPlus11 && "converted constant expression outside C++11");
- assert(T->isIntegralOrEnumerationType() && "unexpected converted const type");
-
- if (checkPlaceholderForOverload(*this, From))
+static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
+ QualType T, APValue &Value,
+ Sema::CCEKind CCE,
+ bool RequireInt) {
+ assert(S.getLangOpts().CPlusPlus11 &&
+ "converted constant expression outside C++11");
+
+ if (checkPlaceholderForOverload(S, From))
return ExprError();
- // C++11 [expr.const]p3 with proposed wording fixes:
- // A converted constant expression of type T is a core constant expression,
- // implicitly converted to a prvalue of type T, where the converted
- // expression is a literal constant expression and the implicit conversion
- // sequence contains only user-defined conversions, lvalue-to-rvalue
- // conversions, integral promotions, and integral conversions other than
- // narrowing conversions.
+ // C++1z [expr.const]p3:
+ // A converted constant expression of type T is an expression,
+ // implicitly converted to type T, where the converted
+ // expression is a constant expression and the implicit conversion
+ // sequence contains only [... list of conversions ...].
ImplicitConversionSequence ICS =
- TryImplicitConversion(From, T,
+ TryCopyInitialization(S, From, T,
/*SuppressUserConversions=*/false,
- /*AllowExplicit=*/false,
/*InOverloadResolution=*/false,
- /*CStyle=*/false,
- /*AllowObjcWritebackConversion=*/false);
+ /*AllowObjcWritebackConversion=*/false,
+ /*AllowExplicit=*/false);
StandardConversionSequence *SCS = nullptr;
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
- if (!CheckConvertedConstantConversions(*this, ICS.Standard))
- return Diag(From->getLocStart(),
- diag::err_typecheck_converted_constant_expression_disallowed)
- << From->getType() << From->getSourceRange() << T;
SCS = &ICS.Standard;
break;
case ImplicitConversionSequence::UserDefinedConversion:
- // We are converting from class type to an integral or enumeration type, so
- // the Before sequence must be trivial.
- if (!CheckConvertedConstantConversions(*this, ICS.UserDefined.After))
- return Diag(From->getLocStart(),
- diag::err_typecheck_converted_constant_expression_disallowed)
- << From->getType() << From->getSourceRange() << T;
+ // We are converting to a non-class type, so the Before sequence
+ // must be trivial.
SCS = &ICS.UserDefined.After;
break;
case ImplicitConversionSequence::AmbiguousConversion:
case ImplicitConversionSequence::BadConversion:
- if (!DiagnoseMultipleUserDefinedConversion(From, T))
- return Diag(From->getLocStart(),
- diag::err_typecheck_converted_constant_expression)
- << From->getType() << From->getSourceRange() << T;
+ if (!S.DiagnoseMultipleUserDefinedConversion(From, T))
+ return S.Diag(From->getLocStart(),
+ diag::err_typecheck_converted_constant_expression)
+ << From->getType() << From->getSourceRange() << T;
return ExprError();
case ImplicitConversionSequence::EllipsisConversion:
llvm_unreachable("ellipsis conversion in converted constant expression");
}
- ExprResult Result = PerformImplicitConversion(From, T, ICS, AA_Converting);
+ // Check that we would only use permitted conversions.
+ if (!CheckConvertedConstantConversions(S, *SCS)) {
+ return S.Diag(From->getLocStart(),
+ diag::err_typecheck_converted_constant_expression_disallowed)
+ << From->getType() << From->getSourceRange() << T;
+ }
+ // [...] and where the reference binding (if any) binds directly.
+ if (SCS->ReferenceBinding && !SCS->DirectBinding) {
+ return S.Diag(From->getLocStart(),
+ diag::err_typecheck_converted_constant_expression_indirect)
+ << From->getType() << From->getSourceRange() << T;
+ }
+
+ ExprResult Result =
+ S.PerformImplicitConversion(From, T, ICS, Sema::AA_Converting);
if (Result.isInvalid())
return Result;
// Check for a narrowing implicit conversion.
APValue PreNarrowingValue;
QualType PreNarrowingType;
- switch (SCS->getNarrowingKind(Context, Result.get(), PreNarrowingValue,
+ switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue,
PreNarrowingType)) {
case NK_Variable_Narrowing:
// Implicit conversion to a narrower type, and the value is not a constant
@@ -5042,13 +5023,13 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
break;
case NK_Constant_Narrowing:
- Diag(From->getLocStart(), diag::ext_cce_narrowing)
+ S.Diag(From->getLocStart(), diag::ext_cce_narrowing)
<< CCE << /*Constant*/1
- << PreNarrowingValue.getAsString(Context, PreNarrowingType) << T;
+ << PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << T;
break;
case NK_Type_Narrowing:
- Diag(From->getLocStart(), diag::ext_cce_narrowing)
+ S.Diag(From->getLocStart(), diag::ext_cce_narrowing)
<< CCE << /*Constant*/0 << From->getType() << T;
break;
}
@@ -5058,12 +5039,15 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
Expr::EvalResult Eval;
Eval.Diag = &Notes;
- if (!Result.get()->EvaluateAsRValue(Eval, Context) || !Eval.Val.isInt()) {
+ if ((T->isReferenceType()
+ ? !Result.get()->EvaluateAsLValue(Eval, S.Context)
+ : !Result.get()->EvaluateAsRValue(Eval, S.Context)) ||
+ (RequireInt && !Eval.Val.isInt())) {
// The expression can't be folded, so we can't keep it at this position in
// the AST.
Result = ExprError();
} else {
- Value = Eval.Val.getInt();
+ Value = Eval.Val;
if (Notes.empty()) {
// It's a constant expression.
@@ -5074,16 +5058,34 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
// It's not a constant expression. Produce an appropriate diagnostic.
if (Notes.size() == 1 &&
Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr)
- Diag(Notes[0].first, diag::err_expr_not_cce) << CCE;
+ S.Diag(Notes[0].first, diag::err_expr_not_cce) << CCE;
else {
- Diag(From->getLocStart(), diag::err_expr_not_cce)
+ S.Diag(From->getLocStart(), diag::err_expr_not_cce)
<< CCE << From->getSourceRange();
for (unsigned I = 0; I < Notes.size(); ++I)
- Diag(Notes[I].first, Notes[I].second);
+ S.Diag(Notes[I].first, Notes[I].second);
}
- return Result;
+ return ExprError();
+}
+
+ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
+ APValue &Value, CCEKind CCE) {
+ return ::CheckConvertedConstantExpression(*this, From, T, Value, CCE, false);
}
+ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
+ llvm::APSInt &Value,
+ CCEKind CCE) {
+ assert(T->isIntegralOrEnumerationType() && "unexpected converted const type");
+
+ APValue V;
+ auto R = ::CheckConvertedConstantExpression(*this, From, T, V, CCE, true);
+ if (!R.isInvalid())
+ Value = V.getInt();
+ return R;
+}
+
+
/// dropPointerConversions - If the given standard conversion sequence
/// involves any pointer conversions, remove them. This may change
/// the result type of the conversion sequence.
@@ -5364,14 +5366,14 @@ ExprResult Sema::PerformContextualImplicitConversion(
CXXConversionDecl *Conversion;
FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
if (ConvTemplate) {
- if (getLangOpts().CPlusPlus1y)
+ if (getLangOpts().CPlusPlus14)
Conversion = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
else
continue; // C++11 does not consider conversion operator templates(?).
} else
Conversion = cast<CXXConversionDecl>(D);
- assert((!ConvTemplate || getLangOpts().CPlusPlus1y) &&
+ assert((!ConvTemplate || getLangOpts().CPlusPlus14) &&
"Conversion operator templates are considered potentially "
"viable in C++1y");
@@ -5384,7 +5386,7 @@ ExprResult Sema::PerformContextualImplicitConversion(
if (!ConvTemplate)
ExplicitConversions.addDecl(I.getDecl(), I.getAccess());
} else {
- if (!ConvTemplate && getLangOpts().CPlusPlus1y) {
+ if (!ConvTemplate && getLangOpts().CPlusPlus14) {
if (ToType.isNull())
ToType = CurToType.getUnqualifiedType();
else if (HasUniqueTargetType &&
@@ -5396,7 +5398,7 @@ ExprResult Sema::PerformContextualImplicitConversion(
}
}
- if (getLangOpts().CPlusPlus1y) {
+ if (getLangOpts().CPlusPlus14) {
// C++1y [conv]p6:
// ... An expression e of class type E appearing in such a context
// is said to be contextually implicitly converted to a specified
@@ -5584,6 +5586,15 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// Overload resolution is always an unevaluated context.
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+ // Add this candidate
+ OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size());
+ Candidate.FoundDecl = FoundDecl;
+ Candidate.Function = Function;
+ Candidate.Viable = true;
+ Candidate.IsSurrogate = false;
+ Candidate.IgnoreObjectArgument = false;
+ Candidate.ExplicitCallArguments = Args.size();
+
if (Constructor) {
// C++ [class.copy]p3:
// A member function template is never instantiated to perform the copy
@@ -5592,19 +5603,13 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
if (Args.size() == 1 &&
Constructor->isSpecializationCopyingObject() &&
(Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) ||
- IsDerivedFrom(Args[0]->getType(), ClassType)))
+ IsDerivedFrom(Args[0]->getType(), ClassType))) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_illegal_constructor;
return;
+ }
}
- // Add this candidate
- OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size());
- Candidate.FoundDecl = FoundDecl;
- Candidate.Function = Function;
- Candidate.Viable = true;
- Candidate.IsSurrogate = false;
- Candidate.IgnoreObjectArgument = false;
- Candidate.ExplicitCallArguments = Args.size();
-
unsigned NumParams = Proto->getNumParams();
// (C++ 13.3.2p2): A candidate function having fewer than m
@@ -5633,7 +5638,11 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// (CUDA B.1): Check for invalid calls between targets.
if (getLangOpts().CUDA)
if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext))
- if (CheckCUDATarget(Caller, Function)) {
+ // Skip the check for callers that are implicit members, because in this
+ // case we may not yet know what the member's target is; the target is
+ // inferred for the member automatically, based on the bases and fields of
+ // the class.
+ if (!Caller->isImplicit() && CheckCUDATarget(Caller, Function)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_target;
return;
@@ -5676,6 +5685,93 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
}
}
+ObjCMethodDecl *Sema::SelectBestMethod(Selector Sel, MultiExprArg Args,
+ bool IsInstance) {
+ SmallVector<ObjCMethodDecl*, 4> Methods;
+ if (!CollectMultipleMethodsInGlobalPool(Sel, Methods, IsInstance))
+ return nullptr;
+
+ for (unsigned b = 0, e = Methods.size(); b < e; b++) {
+ bool Match = true;
+ ObjCMethodDecl *Method = Methods[b];
+ unsigned NumNamedArgs = Sel.getNumArgs();
+ // Method might have more arguments than selector indicates. This is due
+ // to addition of c-style arguments in method.
+ if (Method->param_size() > NumNamedArgs)
+ NumNamedArgs = Method->param_size();
+ if (Args.size() < NumNamedArgs)
+ continue;
+
+ for (unsigned i = 0; i < NumNamedArgs; i++) {
+ // We can't do any type-checking on a type-dependent argument.
+ if (Args[i]->isTypeDependent()) {
+ Match = false;
+ break;
+ }
+
+ ParmVarDecl *param = Method->parameters()[i];
+ Expr *argExpr = Args[i];
+ assert(argExpr && "SelectBestMethod(): missing expression");
+
+ // Strip the unbridged-cast placeholder expression off unless it's
+ // a consumed argument.
+ if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) &&
+ !param->hasAttr<CFConsumedAttr>())
+ argExpr = stripARCUnbridgedCast(argExpr);
+
+ // If the parameter is __unknown_anytype, move on to the next method.
+ if (param->getType() == Context.UnknownAnyTy) {
+ Match = false;
+ break;
+ }
+
+ ImplicitConversionSequence ConversionState
+ = TryCopyInitialization(*this, argExpr, param->getType(),
+ /*SuppressUserConversions*/false,
+ /*InOverloadResolution=*/true,
+ /*AllowObjCWritebackConversion=*/
+ getLangOpts().ObjCAutoRefCount,
+ /*AllowExplicit*/false);
+ if (ConversionState.isBad()) {
+ Match = false;
+ break;
+ }
+ }
+ // Promote additional arguments to variadic methods.
+ if (Match && Method->isVariadic()) {
+ for (unsigned i = NumNamedArgs, e = Args.size(); i < e; ++i) {
+ if (Args[i]->isTypeDependent()) {
+ Match = false;
+ break;
+ }
+ ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod,
+ nullptr);
+ if (Arg.isInvalid()) {
+ Match = false;
+ break;
+ }
+ }
+ } else {
+ // Check for extra arguments to non-variadic methods.
+ if (Args.size() != NumNamedArgs)
+ Match = false;
+ else if (Match && NumNamedArgs == 0 && Methods.size() > 1) {
+ // Special case when selectors have no argument. In this case, select
+ // one with the most general result type of 'id'.
+ for (unsigned b = 0, e = Methods.size(); b < e; b++) {
+ QualType ReturnT = Methods[b]->getReturnType();
+ if (ReturnT->isObjCIdType())
+ return Methods[b];
+ }
+ }
+ }
+
+ if (Match)
+ return Method;
+ }
+ return nullptr;
+}
+
static bool IsNotEnableIfAttr(Attr *A) { return !isa<EnableIfAttr>(A); }
EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
@@ -5696,6 +5792,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
// Convert the arguments.
SmallVector<Expr *, 16> ConvertedArgs;
bool InitializationFailed = false;
+ bool ContainsValueDependentExpr = false;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
if (i == 0 && !MissingImplicitThis && isa<CXXMethodDecl>(Function) &&
!cast<CXXMethodDecl>(Function)->isStatic() &&
@@ -5708,6 +5805,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
InitializationFailed = true;
break;
}
+ ContainsValueDependentExpr |= R.get()->isValueDependent();
ConvertedArgs.push_back(R.get());
} else {
ExprResult R =
@@ -5720,6 +5818,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
InitializationFailed = true;
break;
}
+ ContainsValueDependentExpr |= R.get()->isValueDependent();
ConvertedArgs.push_back(R.get());
}
}
@@ -5730,11 +5829,16 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
for (AttrVec::iterator I = Attrs.begin(); I != E; ++I) {
APValue Result;
EnableIfAttr *EIA = cast<EnableIfAttr>(*I);
+ if (EIA->getCond()->isValueDependent()) {
+ // Don't even try now, we'll examine it after instantiation.
+ continue;
+ }
+
if (!EIA->getCond()->EvaluateWithSubstitution(
- Result, Context, Function,
- ArrayRef<const Expr*>(ConvertedArgs.data(),
- ConvertedArgs.size())) ||
- !Result.isInt() || !Result.getInt().getBoolValue()) {
+ Result, Context, Function, llvm::makeArrayRef(ConvertedArgs))) {
+ if (!ContainsValueDependentExpr)
+ return EIA;
+ } else if (!Result.isInt() || !Result.getInt().getBoolValue()) {
return EIA;
}
}
@@ -5891,6 +5995,15 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
}
}
+ // (CUDA B.1): Check for invalid calls between targets.
+ if (getLangOpts().CUDA)
+ if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext))
+ if (CheckCUDATarget(Caller, Method)) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_target;
+ return;
+ }
+
// Determine the implicit conversion sequences for each of the
// arguments.
for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
@@ -6087,7 +6200,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
// If the conversion function has an undeduced return type, trigger its
// deduction now.
- if (getLangOpts().CPlusPlus1y && ConvType->isUndeducedType()) {
+ if (getLangOpts().CPlusPlus14 && ConvType->isUndeducedType()) {
if (DeduceReturnType(Conversion, From->getExprLoc()))
return;
ConvType = Conversion->getConversionType().getNonReferenceType();
@@ -6226,7 +6339,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
"Can only end up with a standard conversion sequence or failure");
}
- if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, ArrayRef<Expr*>())) {
+ if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, None)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
@@ -6379,7 +6492,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
}
}
- if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, ArrayRef<Expr*>())) {
+ if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, None)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
@@ -6610,7 +6723,7 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
const Qualifiers &VisibleQuals) {
// Insert this type.
- if (!PointerTypes.insert(Ty))
+ if (!PointerTypes.insert(Ty).second)
return false;
QualType PointeeTy;
@@ -6678,7 +6791,7 @@ bool
BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
QualType Ty) {
// Insert this type.
- if (!MemberPointerTypes.insert(Ty))
+ if (!MemberPointerTypes.insert(Ty).second)
return false;
const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>();
@@ -7248,7 +7361,7 @@ public:
MemPtr != MemPtrEnd;
++MemPtr) {
// Don't add the same builtin candidate twice.
- if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)).second)
continue;
QualType ParamTypes[2] = { *MemPtr, *MemPtr };
@@ -7323,7 +7436,7 @@ public:
PtrEnd = CandidateTypes[ArgIdx].pointer_end();
Ptr != PtrEnd; ++Ptr) {
// Don't add the same builtin candidate twice.
- if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)).second)
continue;
QualType ParamTypes[2] = { *Ptr, *Ptr };
@@ -7337,7 +7450,7 @@ public:
// Don't add the same builtin candidate twice, or if a user defined
// candidate exists.
- if (!AddedTypes.insert(CanonType) ||
+ if (!AddedTypes.insert(CanonType).second ||
UserDefinedBinaryOperators.count(std::make_pair(CanonType,
CanonType)))
continue;
@@ -7348,7 +7461,7 @@ public:
if (CandidateTypes[ArgIdx].hasNullPtrType()) {
CanQualType NullPtrTy = S.Context.getCanonicalType(S.Context.NullPtrTy);
- if (AddedTypes.insert(NullPtrTy) &&
+ if (AddedTypes.insert(NullPtrTy).second &&
!UserDefinedBinaryOperators.count(std::make_pair(NullPtrTy,
NullPtrTy))) {
QualType ParamTypes[2] = { NullPtrTy, NullPtrTy };
@@ -7401,7 +7514,7 @@ public:
}
if (Op == OO_Minus) {
// ptrdiff_t operator-(T, T);
- if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)).second)
continue;
QualType ParamTypes[2] = { *Ptr, *Ptr };
@@ -7530,7 +7643,7 @@ public:
Enum = CandidateTypes[ArgIdx].enumeration_begin(),
EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
Enum != EnumEnd; ++Enum) {
- if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)))
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)).second)
continue;
AddBuiltinAssignmentOperatorCandidates(S, *Enum, Args, CandidateSet);
@@ -7540,7 +7653,7 @@ public:
MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
MemPtr != MemPtrEnd; ++MemPtr) {
- if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)).second)
continue;
AddBuiltinAssignmentOperatorCandidates(S, *MemPtr, Args, CandidateSet);
@@ -7623,7 +7736,7 @@ public:
PtrEnd = CandidateTypes[1].pointer_end();
Ptr != PtrEnd; ++Ptr) {
// Make sure we don't add the same candidate twice.
- if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)).second)
continue;
QualType ParamTypes[2] = {
@@ -7904,7 +8017,7 @@ public:
Ptr = CandidateTypes[ArgIdx].pointer_begin(),
PtrEnd = CandidateTypes[ArgIdx].pointer_end();
Ptr != PtrEnd; ++Ptr) {
- if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)).second)
continue;
QualType ParamTypes[2] = { *Ptr, *Ptr };
@@ -7915,7 +8028,7 @@ public:
MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
MemPtr != MemPtrEnd; ++MemPtr) {
- if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)).second)
continue;
QualType ParamTypes[2] = { *MemPtr, *MemPtr };
@@ -7930,7 +8043,7 @@ public:
if (!(*Enum)->getAs<EnumType>()->getDecl()->isScoped())
continue;
- if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)))
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)).second)
continue;
QualType ParamTypes[2] = { *Enum, *Enum };
@@ -8184,12 +8297,10 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
/// isBetterOverloadCandidate - Determines whether the first overload
/// candidate is a better candidate than the second (C++ 13.3.3p1).
-bool
-isBetterOverloadCandidate(Sema &S,
- const OverloadCandidate &Cand1,
- const OverloadCandidate &Cand2,
- SourceLocation Loc,
- bool UserDefinedConversion) {
+bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
+ const OverloadCandidate &Cand2,
+ SourceLocation Loc,
+ bool UserDefinedConversion) {
// Define viable functions to be better candidates than non-viable
// functions.
if (!Cand2.Viable)
@@ -8521,9 +8632,8 @@ void ImplicitConversionSequence::DiagnoseAmbiguousConversion(
S.Diag(SourceLocation(), diag::note_ovl_too_many_candidates) << int(E - I);
}
-namespace {
-
-void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
+static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
+ unsigned I) {
const ImplicitConversionSequence &Conv = Cand->Conversions[I];
assert(Conv.isBad());
assert(Cand->Function && "for now, candidate must be a function");
@@ -8741,8 +8851,8 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
/// Additional arity mismatch diagnosis specific to a function overload
/// candidates. This is not covered by the more general DiagnoseArityMismatch()
/// over a candidate in any candidate set.
-bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand,
- unsigned NumArgs) {
+static bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand,
+ unsigned NumArgs) {
FunctionDecl *Fn = Cand->Function;
unsigned MinParams = Fn->getMinRequiredArguments();
@@ -8769,7 +8879,7 @@ bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand,
}
/// General arity mismatch diagnosis over a candidate in a candidate set.
-void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
+static void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
assert(isa<FunctionDecl>(D) &&
"The templated declaration should at least be a function"
" when diagnosing bad template argument deduction due to too many"
@@ -8813,13 +8923,13 @@ void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
}
/// Arity mismatch diagnosis specific to a function overload candidate.
-void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
- unsigned NumFormalArgs) {
+static void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
+ unsigned NumFormalArgs) {
if (!CheckArityMismatch(S, Cand, NumFormalArgs))
DiagnoseArityMismatch(S, Cand->Function, NumFormalArgs);
}
-TemplateDecl *getDescribedTemplate(Decl *Templated) {
+static TemplateDecl *getDescribedTemplate(Decl *Templated) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Templated))
return FD->getDescribedFunctionTemplate();
else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Templated))
@@ -8830,9 +8940,9 @@ TemplateDecl *getDescribedTemplate(Decl *Templated) {
}
/// Diagnose a failed template-argument deduction.
-void DiagnoseBadDeduction(Sema &S, Decl *Templated,
- DeductionFailureInfo &DeductionFailure,
- unsigned NumArgs) {
+static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
+ DeductionFailureInfo &DeductionFailure,
+ unsigned NumArgs) {
TemplateParameter Param = DeductionFailure.getTemplateParameter();
NamedDecl *ParamD;
(ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
@@ -9019,7 +9129,8 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated,
}
/// Diagnose a failed template-argument deduction, for function calls.
-void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, unsigned NumArgs) {
+static void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
+ unsigned NumArgs) {
unsigned TDK = Cand->DeductionFailure.Result;
if (TDK == Sema::TDK_TooFewArguments || TDK == Sema::TDK_TooManyArguments) {
if (CheckArityMismatch(S, Cand, NumArgs))
@@ -9030,7 +9141,7 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, unsigned NumArgs) {
}
/// CUDA: diagnose an invalid call across targets.
-void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
+static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
FunctionDecl *Caller = cast<FunctionDecl>(S.CurContext);
FunctionDecl *Callee = Cand->Function;
@@ -9041,10 +9152,50 @@ void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Callee, FnDesc);
S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target)
- << (unsigned) FnKind << CalleeTarget << CallerTarget;
+ << (unsigned)FnKind << CalleeTarget << CallerTarget;
+
+ // This could be an implicit constructor for which we could not infer the
+ // target due to a collsion. Diagnose that case.
+ CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Callee);
+ if (Meth != nullptr && Meth->isImplicit()) {
+ CXXRecordDecl *ParentClass = Meth->getParent();
+ Sema::CXXSpecialMember CSM;
+
+ switch (FnKind) {
+ default:
+ return;
+ case oc_implicit_default_constructor:
+ CSM = Sema::CXXDefaultConstructor;
+ break;
+ case oc_implicit_copy_constructor:
+ CSM = Sema::CXXCopyConstructor;
+ break;
+ case oc_implicit_move_constructor:
+ CSM = Sema::CXXMoveConstructor;
+ break;
+ case oc_implicit_copy_assignment:
+ CSM = Sema::CXXCopyAssignment;
+ break;
+ case oc_implicit_move_assignment:
+ CSM = Sema::CXXMoveAssignment;
+ break;
+ };
+
+ bool ConstRHS = false;
+ if (Meth->getNumParams()) {
+ if (const ReferenceType *RT =
+ Meth->getParamDecl(0)->getType()->getAs<ReferenceType>()) {
+ ConstRHS = RT->getPointeeType().isConstQualified();
+ }
+ }
+
+ S.inferCUDATargetForImplicitSpecialMember(ParentClass, CSM, Meth,
+ /* ConstRHS */ ConstRHS,
+ /* Diagnose */ true);
+ }
}
-void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) {
+static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) {
FunctionDecl *Callee = Cand->Function;
EnableIfAttr *Attr = static_cast<EnableIfAttr*>(Cand->DeductionFailure.Data);
@@ -9066,8 +9217,8 @@ void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) {
/// It would be great to be able to express per-candidate problems
/// more richly for those diagnostic clients that cared, but we'd
/// still have to be just as careful with the default diagnostics.
-void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
- unsigned NumArgs) {
+static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
+ unsigned NumArgs) {
FunctionDecl *Fn = Cand->Function;
// Note deleted candidates, but only if they're viable.
@@ -9097,6 +9248,13 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
case ovl_fail_bad_deduction:
return DiagnoseBadDeduction(S, Cand, NumArgs);
+ case ovl_fail_illegal_constructor: {
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_illegal_constructor)
+ << (Fn->getPrimaryTemplate() ? 1 : 0);
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+ }
+
case ovl_fail_trivial_conversion:
case ovl_fail_bad_final_conversion:
case ovl_fail_final_conversion_not_exact:
@@ -9122,7 +9280,7 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
}
}
-void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
+static void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
// Desugar the type of the surrogate down to a function type,
// retaining as many typedefs as possible while still showing
// the function type (and, therefore, its parameter types).
@@ -9155,10 +9313,9 @@ void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
MaybeEmitInheritedConstructorNote(S, Cand->Surrogate);
}
-void NoteBuiltinOperatorCandidate(Sema &S,
- StringRef Opc,
- SourceLocation OpLoc,
- OverloadCandidate *Cand) {
+static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc,
+ SourceLocation OpLoc,
+ OverloadCandidate *Cand) {
assert(Cand->NumConversions <= 2 && "builtin operator is not binary");
std::string TypeStr("operator");
TypeStr += Opc;
@@ -9175,8 +9332,8 @@ void NoteBuiltinOperatorCandidate(Sema &S,
}
}
-void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
- OverloadCandidate *Cand) {
+static void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
+ OverloadCandidate *Cand) {
unsigned NoOperands = Cand->NumConversions;
for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
@@ -9228,6 +9385,7 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
llvm_unreachable("Unhandled deduction result");
}
+namespace {
struct CompareOverloadCandidatesForDisplay {
Sema &S;
size_t NumArgs;
@@ -9351,11 +9509,12 @@ struct CompareOverloadCandidatesForDisplay {
return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc);
}
};
+}
/// CompleteNonViableCandidate - Normally, overload resolution only
/// computes up to the first. Produces the FixIt set if possible.
-void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
- ArrayRef<Expr *> Args) {
+static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
+ ArrayRef<Expr *> Args) {
assert(!Cand->Viable);
// Don't do anything on failures other than bad conversion.
@@ -9435,8 +9594,6 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
}
}
-} // end anonymous namespace
-
/// PrintOverloadCandidates - When overload resolution fails, prints
/// diagnostic messages containing the candidates in the candidate
/// set.
@@ -9513,6 +9670,7 @@ GetLocationForCandidate(const TemplateSpecCandidate *Cand) {
: SourceLocation();
}
+namespace {
struct CompareTemplateSpecCandidatesForDisplay {
Sema &S;
CompareTemplateSpecCandidatesForDisplay(Sema &S) : S(S) {}
@@ -9543,6 +9701,7 @@ struct CompareTemplateSpecCandidatesForDisplay {
return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc);
}
};
+}
/// Diagnose a template argument deduction failure.
/// We are treating these failures as overload failures due to bad
@@ -9631,10 +9790,10 @@ QualType Sema::ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType) {
return Ret;
}
+namespace {
// A helper class to help with address of function resolution
// - allows us to avoid passing around all those ugly parameters
-class AddressOfFunctionResolver
-{
+class AddressOfFunctionResolver {
Sema& S;
Expr* SourceExpr;
const QualType& TargetType;
@@ -9782,12 +9941,12 @@ private:
if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) {
if (S.getLangOpts().CUDA)
if (FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext))
- if (S.CheckCUDATarget(Caller, FunDecl))
+ if (!Caller->isImplicit() && S.CheckCUDATarget(Caller, FunDecl))
return false;
// If any candidate has a placeholder return type, trigger its deduction
// now.
- if (S.getLangOpts().CPlusPlus1y &&
+ if (S.getLangOpts().CPlusPlus14 &&
FunDecl->getReturnType()->isUndeducedType() &&
S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain))
return false;
@@ -9960,7 +10119,8 @@ public:
return &Matches[0].first;
}
};
-
+}
+
/// ResolveAddressOfOverloadedFunction - Try to resolve the address of
/// an overloaded function (C++ [over.over]), where @p From is an
/// expression with overloaded function type and @p ToType is the type
@@ -10092,7 +10252,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
if (FoundResult) *FoundResult = I.getPair();
}
- if (Matched && getLangOpts().CPlusPlus1y &&
+ if (Matched && getLangOpts().CPlusPlus14 &&
Matched->getReturnType()->isUndeducedType() &&
DeduceReturnType(Matched, ovl->getExprLoc(), Complain))
return nullptr;
@@ -10422,6 +10582,15 @@ public:
}
+static std::unique_ptr<CorrectionCandidateCallback>
+MakeValidator(Sema &SemaRef, MemberExpr *ME, size_t NumArgs,
+ bool HasTemplateArgs, bool AllowTypoCorrection) {
+ if (!AllowTypoCorrection)
+ return llvm::make_unique<NoTypoCorrectionCCC>();
+ return llvm::make_unique<FunctionCallFilterCCC>(SemaRef, NumArgs,
+ HasTemplateArgs, ME);
+}
+
/// Attempts to recover from a call where no functions were found.
///
/// Returns true if new candidates were found.
@@ -10455,19 +10624,15 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
Sema::LookupOrdinaryName);
- FunctionCallFilterCCC Validator(SemaRef, Args.size(),
- ExplicitTemplateArgs != nullptr,
- dyn_cast<MemberExpr>(Fn));
- NoTypoCorrectionCCC RejectAll;
- CorrectionCandidateCallback *CCC = AllowTypoCorrection ?
- (CorrectionCandidateCallback*)&Validator :
- (CorrectionCandidateCallback*)&RejectAll;
if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R,
OverloadCandidateSet::CSK_Normal,
ExplicitTemplateArgs, Args) &&
(!EmptyLookup ||
- SemaRef.DiagnoseEmptyLookup(S, SS, R, *CCC,
- ExplicitTemplateArgs, Args)))
+ SemaRef.DiagnoseEmptyLookup(
+ S, SS, R,
+ MakeValidator(SemaRef, dyn_cast<MemberExpr>(Fn), Args.size(),
+ ExplicitTemplateArgs != nullptr, AllowTypoCorrection),
+ ExplicitTemplateArgs, Args)))
return ExprError();
assert(!R.empty() && "lookup results empty despite recovery");
@@ -10945,10 +11110,13 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// Add operator candidates that are member functions.
AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet);
- // Add candidates from ADL.
- AddArgumentDependentLookupCandidates(OpName, OpLoc, Args,
- /*ExplicitTemplateArgs*/ nullptr,
- CandidateSet);
+ // Add candidates from ADL. Per [over.match.oper]p2, this lookup is not
+ // performed for an assignment operator (nor for operator[] nor operator->,
+ // which don't get here).
+ if (Opc != BO_Assign)
+ AddArgumentDependentLookupCandidates(OpName, OpLoc, Args,
+ /*ExplicitTemplateArgs*/ nullptr,
+ CandidateSet);
// Add builtin operator candidates.
AddBuiltinOperatorCandidates(Op, OpLoc, Args, CandidateSet);
@@ -11031,7 +11199,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// Cut off the implicit 'this'.
if (isa<CXXMethodDecl>(FnDecl))
ArgsArray = ArgsArray.slice(1);
- checkCall(FnDecl, ArgsArray, 0, isa<CXXMethodDecl>(FnDecl), OpLoc,
+
+ // Check for a self move.
+ if (Op == OO_Equal)
+ DiagnoseSelfMove(Args[0], Args[1], OpLoc);
+
+ checkCall(FnDecl, ArgsArray, 0, isa<CXXMethodDecl>(FnDecl), OpLoc,
TheCall->getSourceRange(), VariadicDoesNotApply);
return MaybeBindToTemporary(TheCall);
@@ -11352,6 +11525,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
<< (qualsString.find(' ') == std::string::npos ? 1 : 2);
}
+ if (resultType->isMemberPointerType())
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ RequireCompleteType(LParenLoc, resultType, 0);
+
CXXMemberCallExpr *call
= new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
resultType, valueKind, RParenLoc);
@@ -11505,6 +11682,18 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
ResultType, VK, RParenLoc);
+ // (CUDA B.1): Check for invalid calls between targets.
+ if (getLangOpts().CUDA) {
+ if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext)) {
+ if (CheckCUDATarget(Caller, Method)) {
+ Diag(MemExpr->getMemberLoc(), diag::err_ref_bad_target)
+ << IdentifyCUDATarget(Method) << Method->getIdentifier()
+ << IdentifyCUDATarget(Caller);
+ return ExprError();
+ }
+ }
+ }
+
// Check for a valid return type.
if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(),
TheCall, Method))
@@ -11568,7 +11757,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts))
return ExprError();
- assert(Object.get()->getType()->isRecordType() && "Requires object type argument");
+ assert(Object.get()->getType()->isRecordType() &&
+ "Requires object type argument");
const RecordType *Record = Object.get()->getType()->getAs<RecordType>();
// C++ [over.call.object]p1:
@@ -12272,5 +12462,3 @@ ExprResult Sema::FixOverloadedFunctionReference(ExprResult E,
FunctionDecl *Fn) {
return FixOverloadedFunctionReference(E.get(), Found, Fn);
}
-
-} // end namespace clang
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index aa3e89ed67a9..5e92d5d07c51 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -406,6 +406,10 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
BinaryOperatorKind opcode,
Expr *LHS, Expr *RHS) {
assert(BinaryOperator::isAssignmentOp(opcode));
+
+ // Recover from user error
+ if (isa<UnresolvedLookupExpr>(RHS))
+ return ExprError();
Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
OpaqueValueExpr *capturedRHS = capture(RHS);
@@ -615,7 +619,7 @@ bool ObjCPropertyOpBuilder::findSetter(bool warn) {
if (setter->isPropertyAccessor() && warn)
if (const ObjCInterfaceDecl *IFace =
dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) {
- const StringRef thisPropertyName(prop->getName());
+ StringRef thisPropertyName = prop->getName();
// Try flipping the case of the first character.
char front = thisPropertyName.front();
front = isLowercase(front) ? toUppercase(front) : toLowercase(front);
@@ -1022,7 +1026,8 @@ Sema::ObjCSubscriptKind
// If we don't have a class type in C++, there's no way we can get an
// expression of integral or enumeration type.
const RecordType *RecordTy = T->getAs<RecordType>();
- if (!RecordTy && T->isObjCObjectPointerType())
+ if (!RecordTy &&
+ (T->isObjCObjectPointerType() || T->isVoidPointerType()))
// All other scalar cases are assumed to be dictionary indexing which
// caller handles, with diagnostics if needed.
return OS_Dictionary;
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 278e6d66828b..22ed93082065 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/TypeLoc.h"
@@ -184,6 +185,12 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
const Expr *E = dyn_cast_or_null<Expr>(S);
if (!E)
return;
+
+ // If we are in an unevaluated expression context, then there can be no unused
+ // results because the results aren't expected to be used in the first place.
+ if (isUnevaluatedContext())
+ return;
+
SourceLocation ExprLoc = E->IgnoreParens()->getExprLoc();
// In most cases, we don't want to warn if the expression is written in a
// macro body, or if the macro comes from a system header. If the offending
@@ -364,6 +371,23 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
return StmtError();
}
+ ExprResult LHS =
+ CorrectDelayedTyposInExpr(LHSVal, [this](class Expr *E) {
+ if (!getLangOpts().CPlusPlus11)
+ return VerifyIntegerConstantExpression(E);
+ if (Expr *CondExpr =
+ getCurFunction()->SwitchStack.back()->getCond()) {
+ QualType CondType = CondExpr->getType();
+ llvm::APSInt TempVal;
+ return CheckConvertedConstantExpression(E, CondType, TempVal,
+ CCEK_CaseValue);
+ }
+ return ExprError();
+ });
+ if (LHS.isInvalid())
+ return StmtError();
+ LHSVal = LHS.get();
+
if (!getLangOpts().CPlusPlus11) {
// C99 6.8.4.2p3: The expression shall be an integer constant.
// However, GCC allows any evaluatable integer expression.
@@ -381,14 +405,19 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
}
}
- LHSVal = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false,
- getLangOpts().CPlusPlus11).get();
- if (RHSVal)
- RHSVal = ActOnFinishFullExpr(RHSVal, RHSVal->getExprLoc(), false,
- getLangOpts().CPlusPlus11).get();
+ LHS = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false,
+ getLangOpts().CPlusPlus11);
+ if (LHS.isInvalid())
+ return StmtError();
+
+ auto RHS = RHSVal ? ActOnFinishFullExpr(RHSVal, RHSVal->getExprLoc(), false,
+ getLangOpts().CPlusPlus11)
+ : ExprResult();
+ if (RHS.isInvalid())
+ return StmtError();
- CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc,
- ColonLoc);
+ CaseStmt *CS = new (Context)
+ CaseStmt(LHS.get(), RHS.get(), CaseLoc, DotDotDotLoc, ColonLoc);
getCurFunction()->SwitchStack.back()->addSwitchCase(CS);
return CS;
}
@@ -431,7 +460,11 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
TheDecl->setStmt(LS);
if (!TheDecl->isGnuLocal()) {
TheDecl->setLocStart(IdentLoc);
- TheDecl->setLocation(IdentLoc);
+ if (!TheDecl->isMSAsmLabel()) {
+ // Don't update the location of MS ASM labels. These will result in
+ // a diagnostic, and changing the location here will mess that up.
+ TheDecl->setLocation(IdentLoc);
+ }
}
return LS;
}
@@ -481,47 +514,6 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
thenStmt, ElseLoc, elseStmt);
}
-/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
-/// the specified width and sign. If an overflow occurs, detect it and emit
-/// the specified diagnostic.
-void Sema::ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &Val,
- unsigned NewWidth, bool NewSign,
- SourceLocation Loc,
- unsigned DiagID) {
- // Perform a conversion to the promoted condition type if needed.
- if (NewWidth > Val.getBitWidth()) {
- // If this is an extension, just do it.
- Val = Val.extend(NewWidth);
- Val.setIsSigned(NewSign);
-
- // If the input was signed and negative and the output is
- // unsigned, don't bother to warn: this is implementation-defined
- // behavior.
- // FIXME: Introduce a second, default-ignored warning for this case?
- } else if (NewWidth < Val.getBitWidth()) {
- // If this is a truncation, check for overflow.
- llvm::APSInt ConvVal(Val);
- ConvVal = ConvVal.trunc(NewWidth);
- ConvVal.setIsSigned(NewSign);
- ConvVal = ConvVal.extend(Val.getBitWidth());
- ConvVal.setIsSigned(Val.isSigned());
- if (ConvVal != Val)
- Diag(Loc, DiagID) << Val.toString(10) << ConvVal.toString(10);
-
- // Regardless of whether a diagnostic was emitted, really do the
- // truncation.
- Val = Val.trunc(NewWidth);
- Val.setIsSigned(NewSign);
- } else if (NewSign != Val.isSigned()) {
- // Convert the sign to match the sign of the condition. This can cause
- // overflow as well: unsigned(INTMIN)
- // We don't diagnose this overflow, because it is implementation-defined
- // behavior.
- // FIXME: Introduce a second, default-ignored warning for this case?
- Val.setIsSigned(NewSign);
- }
-}
-
namespace {
struct CaseCompareFunctor {
bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS,
@@ -671,33 +663,63 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
}
static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) {
- if (Val.getBitWidth() < BitWidth)
- Val = Val.extend(BitWidth);
- else if (Val.getBitWidth() > BitWidth)
- Val = Val.trunc(BitWidth);
+ Val = Val.extOrTrunc(BitWidth);
Val.setIsSigned(IsSigned);
}
+/// Check the specified case value is in range for the given unpromoted switch
+/// type.
+static void checkCaseValue(Sema &S, SourceLocation Loc, const llvm::APSInt &Val,
+ unsigned UnpromotedWidth, bool UnpromotedSign) {
+ // If the case value was signed and negative and the switch expression is
+ // unsigned, don't bother to warn: this is implementation-defined behavior.
+ // FIXME: Introduce a second, default-ignored warning for this case?
+ if (UnpromotedWidth < Val.getBitWidth()) {
+ llvm::APSInt ConvVal(Val);
+ AdjustAPSInt(ConvVal, UnpromotedWidth, UnpromotedSign);
+ AdjustAPSInt(ConvVal, Val.getBitWidth(), Val.isSigned());
+ // FIXME: Use different diagnostics for overflow in conversion to promoted
+ // type versus "switch expression cannot have this value". Use proper
+ // IntRange checking rather than just looking at the unpromoted type here.
+ if (ConvVal != Val)
+ S.Diag(Loc, diag::warn_case_value_overflow) << Val.toString(10)
+ << ConvVal.toString(10);
+ }
+}
+
+typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> EnumValsTy;
+
/// 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,
+static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S,
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)) {
+ const Expr *CaseExpr,
+ EnumValsTy::iterator &EI,
+ EnumValsTy::iterator &EIEnd,
+ const llvm::APSInt &Val) {
+ bool FlagType = ED->hasAttr<FlagEnumAttr>();
+
+ if (const DeclRefExpr *DRE =
+ dyn_cast<DeclRefExpr>(CaseExpr->IgnoreParenImpCasts())) {
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))
+ QualType EnumType = S.Context.getTypeDeclType(ED);
+ if (VD->hasGlobalStorage() && VarType.isConstQualified() &&
+ S.Context.hasSameUnqualifiedType(EnumType, VarType))
return false;
}
}
+
+ if (FlagType) {
+ return !S.IsValueInFlagEnum(ED, Val, false);
+ } else {
+ while (EI != EIEnd && EI->first < Val)
+ EI++;
+
+ if (EI != EIEnd && EI->first == Val)
+ return false;
+ }
+
return true;
}
@@ -708,9 +730,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
assert(SS == getCurFunction()->SwitchStack.back() &&
"switch stack missing push/pop!");
+ getCurFunction()->SwitchStack.pop_back();
+
if (!BodyStmt) return StmtError();
SS->setBody(BodyStmt, SwitchLoc);
- getCurFunction()->SwitchStack.pop_back();
Expr *CondExpr = SS->getCond();
if (!CondExpr) return StmtError();
@@ -744,13 +767,20 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
}
}
- // Get the bitwidth of the switched-on value before promotions. We must
+ // Get the bitwidth of the switched-on value after promotions. We must
// convert the integer case values to this width before comparison.
bool HasDependentValue
= CondExpr->isTypeDependent() || CondExpr->isValueDependent();
- unsigned CondWidth
+ unsigned CondWidth = HasDependentValue ? 0 : Context.getIntWidth(CondType);
+ bool CondIsSigned = CondType->isSignedIntegerOrEnumerationType();
+
+ // Get the width and signedness that the condition might actually have, for
+ // warning purposes.
+ // FIXME: Grab an IntRange for the condition rather than using the unpromoted
+ // type.
+ unsigned CondWidthBeforePromotion
= HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion);
- bool CondIsSigned
+ bool CondIsSignedBeforePromotion
= CondTypeBeforePromotion->isSignedIntegerOrEnumerationType();
// Accumulate all of the case values in a vector so that we can sort them
@@ -816,15 +846,13 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).get();
}
- // Convert the value to the same width/sign as the condition had prior to
- // integral promotions.
- //
- // FIXME: This causes us to reject valid code:
- // switch ((char)c) { case 256: case 0: return 0; }
- // Here we claim there is a duplicated condition value, but there is not.
- ConvertIntegerToTypeWarnOnOverflow(LoVal, CondWidth, CondIsSigned,
- Lo->getLocStart(),
- diag::warn_case_value_overflow);
+ // Check the unconverted value is within the range of possible values of
+ // the switch expression.
+ checkCaseValue(*this, Lo->getLocStart(), LoVal,
+ CondWidthBeforePromotion, CondIsSignedBeforePromotion);
+
+ // Convert the value to the same width/sign as the condition.
+ AdjustAPSInt(LoVal, CondWidth, CondIsSigned);
CS->setLHS(Lo);
@@ -847,9 +875,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
llvm::APSInt ConstantCondValue;
bool HasConstantCond = false;
if (!HasDependentValue && !TheDefaultStmt) {
- HasConstantCond
- = CondExprBeforePromotion->EvaluateAsInt(ConstantCondValue, Context,
- Expr::SE_AllowSideEffects);
+ HasConstantCond = CondExpr->EvaluateAsInt(ConstantCondValue, Context,
+ Expr::SE_AllowSideEffects);
assert(!HasConstantCond ||
(ConstantCondValue.getBitWidth() == CondWidth &&
ConstantCondValue.isSigned() == CondIsSigned));
@@ -935,10 +962,13 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).get();
}
+ // Check the unconverted value is within the range of possible values of
+ // the switch expression.
+ checkCaseValue(*this, Hi->getLocStart(), HiVal,
+ CondWidthBeforePromotion, CondIsSignedBeforePromotion);
+
// Convert the value to the same width/sign as the condition.
- ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned,
- Hi->getLocStart(),
- diag::warn_case_value_overflow);
+ AdjustAPSInt(HiVal, CondWidth, CondIsSigned);
CR->setRHS(Hi);
@@ -1029,8 +1059,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// If switch has default case, then ignore it.
if (!CaseListIsErroneous && !HasConstantCond && ET) {
const EnumDecl *ED = ET->getDecl();
- typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64>
- EnumValsTy;
EnumValsTy EnumVals;
// Gather all enum values, set their type and sort them,
@@ -1041,57 +1069,48 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
EnumVals.push_back(std::make_pair(Val, EDI));
}
std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals);
- EnumValsTy::iterator EIend =
+ auto EI = EnumVals.begin(), EIEnd =
std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);
// See which case values aren't in enum.
- EnumValsTy::const_iterator EI = EnumVals.begin();
for (CaseValsTy::const_iterator CI = CaseVals.begin();
- CI != CaseVals.end(); CI++) {
- while (EI != EIend && EI->first < CI->first)
- EI++;
- 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;
- }
+ CI != CaseVals.end(); CI++) {
+ Expr *CaseExpr = CI->second->getLHS();
+ if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd,
+ CI->first))
+ Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
+ << CondTypeBeforePromotion;
}
+
// See which of case ranges aren't in enum
EI = EnumVals.begin();
for (CaseRangesTy::const_iterator RI = CaseRanges.begin();
- RI != CaseRanges.end() && EI != EIend; RI++) {
- while (EI != EIend && EI->first < RI->first)
- EI++;
-
- if (EI == EIend || EI->first != RI->first) {
- Expr *CaseExpr = RI->second->getLHS();
- if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr))
- Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
- << CondTypeBeforePromotion;
- }
+ RI != CaseRanges.end(); RI++) {
+ Expr *CaseExpr = RI->second->getLHS();
+ if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd,
+ RI->first))
+ Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
+ << CondTypeBeforePromotion;
llvm::APSInt Hi =
RI->second->getRHS()->EvaluateKnownConstInt(Context);
AdjustAPSInt(Hi, CondWidth, CondIsSigned);
- while (EI != EIend && EI->first < Hi)
- EI++;
- 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;
- }
+
+ CaseExpr = RI->second->getRHS();
+ if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd,
+ Hi))
+ Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
+ << CondTypeBeforePromotion;
}
// Check which enum vals aren't in switch
- CaseValsTy::const_iterator CI = CaseVals.begin();
- CaseRangesTy::const_iterator RI = CaseRanges.begin();
+ auto CI = CaseVals.begin();
+ auto RI = CaseRanges.begin();
bool hasCasesNotInSwitch = false;
SmallVector<DeclarationName,8> UnhandledNames;
- for (EI = EnumVals.begin(); EI != EIend; EI++){
+ for (EI = EnumVals.begin(); EI != EIEnd; EI++){
// Drop unneeded case values
while (CI != CaseVals.end() && CI->first < EI->first)
CI++;
@@ -1178,30 +1197,37 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
llvm::APSInt RhsVal = SrcExpr->EvaluateKnownConstInt(Context);
AdjustAPSInt(RhsVal, DstWidth, DstIsSigned);
const EnumDecl *ED = ET->getDecl();
- typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64>
- EnumValsTy;
- EnumValsTy EnumVals;
-
- // Gather all enum values, set their type and sort them,
- // allowing easier comparison with rhs constant.
- for (auto *EDI : ED->enumerators()) {
- llvm::APSInt Val = EDI->getInitVal();
- AdjustAPSInt(Val, DstWidth, DstIsSigned);
- EnumVals.push_back(std::make_pair(Val, EDI));
- }
- if (EnumVals.empty())
- return;
- std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals);
- EnumValsTy::iterator EIend =
- std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);
-
- // See which values aren't in the enum.
- EnumValsTy::const_iterator EI = EnumVals.begin();
- while (EI != EIend && EI->first < RhsVal)
- EI++;
- if (EI == EIend || EI->first != RhsVal) {
- Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)
+
+ if (ED->hasAttr<FlagEnumAttr>()) {
+ if (!IsValueInFlagEnum(ED, RhsVal, true))
+ Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)
<< DstType.getUnqualifiedType();
+ } else {
+ typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64>
+ EnumValsTy;
+ EnumValsTy EnumVals;
+
+ // Gather all enum values, set their type and sort them,
+ // allowing easier comparison with rhs constant.
+ for (auto *EDI : ED->enumerators()) {
+ llvm::APSInt Val = EDI->getInitVal();
+ AdjustAPSInt(Val, DstWidth, DstIsSigned);
+ EnumVals.push_back(std::make_pair(Val, EDI));
+ }
+ if (EnumVals.empty())
+ return;
+ std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals);
+ EnumValsTy::iterator EIend =
+ std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);
+
+ // See which values aren't in the enum.
+ EnumValsTy::const_iterator EI = EnumVals.begin();
+ while (EI != EIend && EI->first < RhsVal)
+ EI++;
+ if (EI == EIend || EI->first != RhsVal) {
+ Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment)
+ << DstType.getUnqualifiedType();
+ }
}
}
}
@@ -1260,13 +1286,13 @@ namespace {
// the evaluated decls into a vector. Simple is set to true if none
// of the excluded constructs are used.
class DeclExtractor : public EvaluatedExprVisitor<DeclExtractor> {
- llvm::SmallPtrSet<VarDecl*, 8> &Decls;
+ llvm::SmallPtrSetImpl<VarDecl*> &Decls;
SmallVectorImpl<SourceRange> &Ranges;
bool Simple;
public:
typedef EvaluatedExprVisitor<DeclExtractor> Inherited;
- DeclExtractor(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls,
+ DeclExtractor(Sema &S, llvm::SmallPtrSetImpl<VarDecl*> &Decls,
SmallVectorImpl<SourceRange> &Ranges) :
Inherited(S.Context),
Decls(Decls),
@@ -1338,13 +1364,13 @@ namespace {
// DeclMatcher checks to see if the decls are used in a non-evauluated
// context.
class DeclMatcher : public EvaluatedExprVisitor<DeclMatcher> {
- llvm::SmallPtrSet<VarDecl*, 8> &Decls;
+ llvm::SmallPtrSetImpl<VarDecl*> &Decls;
bool FoundDecl;
public:
typedef EvaluatedExprVisitor<DeclMatcher> Inherited;
- DeclMatcher(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls,
+ DeclMatcher(Sema &S, llvm::SmallPtrSetImpl<VarDecl*> &Decls,
Stmt *Statement) :
Inherited(S.Context), Decls(Decls), FoundDecl(false) {
if (!Statement) return;
@@ -1427,8 +1453,8 @@ namespace {
if (Decls.size() == 0) return;
// Don't warn on volatile, static, or global variables.
- for (llvm::SmallPtrSet<VarDecl*, 8>::iterator I = Decls.begin(),
- E = Decls.end();
+ for (llvm::SmallPtrSetImpl<VarDecl*>::iterator I = Decls.begin(),
+ E = Decls.end();
I != E; ++I)
if ((*I)->getType().isVolatileQualified() ||
(*I)->hasGlobalStorage()) return;
@@ -1443,8 +1469,8 @@ namespace {
PDiag << 0;
else {
PDiag << Decls.size();
- for (llvm::SmallPtrSet<VarDecl*, 8>::iterator I = Decls.begin(),
- E = Decls.end();
+ for (llvm::SmallPtrSetImpl<VarDecl*>::iterator I = Decls.begin(),
+ E = Decls.end();
I != E; ++I)
PDiag << (*I)->getDeclName();
}
@@ -1660,11 +1686,16 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
if (!collection)
return ExprError();
+ ExprResult result = CorrectDelayedTyposInExpr(collection);
+ if (!result.isUsable())
+ return ExprError();
+ collection = result.get();
+
// Bail out early if we've got a type-dependent expression.
if (collection->isTypeDependent()) return collection;
// Perform normal l-value conversion.
- ExprResult result = DefaultFunctionArrayLvalueConversion(collection);
+ result = DefaultFunctionArrayLvalueConversion(collection);
if (result.isInvalid())
return ExprError();
collection = result.get();
@@ -2453,7 +2484,7 @@ VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType,
// - in a return statement in a function [where] ...
// ... the expression is the name of a non-volatile automatic object ...
DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens());
- if (!DR || DR->refersToEnclosingLocal())
+ if (!DR || DR->refersToEnclosingVariableOrCapture())
return nullptr;
VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
if (!VD)
@@ -2621,8 +2652,12 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
return StmtError();
RetValExp = Result.get();
+ // DR1048: even prior to C++14, we should use the 'auto' deduction rules
+ // when deducing a return type for a lambda-expression (or by extension
+ // for a block). These rules differ from the stated C++11 rules only in
+ // that they remove top-level cv-qualifiers.
if (!CurContext->isDependentContext())
- FnRetType = RetValExp->getType();
+ FnRetType = RetValExp->getType().getUnqualifiedType();
else
FnRetType = CurCap->ReturnType = Context.DependentTy;
} else {
@@ -2727,14 +2762,54 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
return Result;
}
+namespace {
+/// \brief Marks all typedefs in all local classes in a type referenced.
+///
+/// In a function like
+/// auto f() {
+/// struct S { typedef int a; };
+/// return S();
+/// }
+///
+/// the local type escapes and could be referenced in some TUs but not in
+/// others. Pretend that all local typedefs are always referenced, to not warn
+/// on this. This isn't necessary if f has internal linkage, or the typedef
+/// is private.
+class LocalTypedefNameReferencer
+ : public RecursiveASTVisitor<LocalTypedefNameReferencer> {
+public:
+ LocalTypedefNameReferencer(Sema &S) : S(S) {}
+ bool VisitRecordType(const RecordType *RT);
+private:
+ Sema &S;
+};
+bool LocalTypedefNameReferencer::VisitRecordType(const RecordType *RT) {
+ auto *R = dyn_cast<CXXRecordDecl>(RT->getDecl());
+ if (!R || !R->isLocalClass() || !R->isLocalClass()->isExternallyVisible() ||
+ R->isDependentType())
+ return true;
+ for (auto *TmpD : R->decls())
+ if (auto *T = dyn_cast<TypedefNameDecl>(TmpD))
+ if (T->getAccess() != AS_private || R->hasFriends())
+ S.MarkAnyDeclReferenced(T->getLocation(), T, /*OdrUse=*/false);
+ return true;
+}
+}
+
+TypeLoc Sema::getReturnTypeLoc(FunctionDecl *FD) const {
+ TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
+ while (auto ATL = TL.getAs<AttributedTypeLoc>())
+ TL = ATL.getModifiedLoc().IgnoreParens();
+ return TL.castAs<FunctionProtoTypeLoc>().getReturnLoc();
+}
+
/// Deduce the return type for a function from a returned expression, per
/// C++1y [dcl.spec.auto]p6.
bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
SourceLocation ReturnLoc,
Expr *&RetExpr,
AutoType *AT) {
- TypeLoc OrigResultType = FD->getTypeSourceInfo()->getTypeLoc().
- IgnoreParens().castAs<FunctionProtoTypeLoc>().getReturnLoc();
+ TypeLoc OrigResultType = getReturnTypeLoc(FD);
QualType Deduced;
if (RetExpr && isa<InitListExpr>(RetExpr)) {
@@ -2772,6 +2847,11 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
if (DAR != DAR_Succeeded)
return true;
+
+ // If a local type is part of the returned type, mark its fields as
+ // referenced.
+ LocalTypedefNameReferencer Referencer(*this);
+ Referencer.TraverseType(RetExpr->getType());
} else {
// In the case of a return with no operand, the initializer is considered
// to be void().
@@ -2872,7 +2952,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// FIXME: Add a flag to the ScopeInfo to indicate whether we're performing
// deduction.
- if (getLangOpts().CPlusPlus1y) {
+ if (getLangOpts().CPlusPlus14) {
if (AutoType *AT = FnRetType->getContainedAutoType()) {
FunctionDecl *FD = cast<FunctionDecl>(CurContext);
if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
@@ -2964,14 +3044,26 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr);
} else if (!RetValExp && !HasDependentReturnType) {
- unsigned DiagID = diag::warn_return_missing_expr; // C90 6.6.6.4p4
- // C99 6.8.6.4p1 (ext_ since GCC warns)
- if (getLangOpts().C99) DiagID = diag::ext_return_missing_expr;
+ FunctionDecl *FD = getCurFunctionDecl();
- if (FunctionDecl *FD = getCurFunctionDecl())
+ unsigned DiagID;
+ if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
+ // C++11 [stmt.return]p2
+ DiagID = diag::err_constexpr_return_missing_expr;
+ FD->setInvalidDecl();
+ } else if (getLangOpts().C99) {
+ // C99 6.8.6.4p1 (ext_ since GCC warns)
+ DiagID = diag::ext_return_missing_expr;
+ } else {
+ // C90 6.6.6.4p4
+ DiagID = diag::warn_return_missing_expr;
+ }
+
+ if (FD)
Diag(ReturnLoc, DiagID) << FD->getIdentifier() << 0/*fn*/;
else
Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/;
+
Result = new (Context) ReturnStmt(ReturnLoc);
} else {
assert(RetValExp || HasDependentReturnType);
@@ -3119,9 +3211,24 @@ Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) {
if (!type->isDependentType() &&
!type->isObjCObjectPointerType()) {
const PointerType *pointerType = type->getAs<PointerType>();
- if (!pointerType || !pointerType->getPointeeType()->isVoidType())
- return Diag(atLoc, diag::error_objc_synchronized_expects_object)
- << type << operand->getSourceRange();
+ if (!pointerType || !pointerType->getPointeeType()->isVoidType()) {
+ if (getLangOpts().CPlusPlus) {
+ if (RequireCompleteType(atLoc, type,
+ diag::err_incomplete_receiver_type))
+ return Diag(atLoc, diag::error_objc_synchronized_expects_object)
+ << type << operand->getSourceRange();
+
+ ExprResult result = PerformContextuallyConvertToObjCPointer(operand);
+ if (!result.isUsable())
+ return Diag(atLoc, diag::error_objc_synchronized_expects_object)
+ << type << operand->getSourceRange();
+
+ operand = result.get();
+ } else {
+ return Diag(atLoc, diag::error_objc_synchronized_expects_object)
+ << type << operand->getSourceRange();
+ }
+ }
}
// The operand to @synchronized is a full-expression.
@@ -3249,15 +3356,16 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
return CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers);
}
-StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc,
- Stmt *TryBlock, Stmt *Handler,
- int HandlerIndex, int HandlerParentIndex) {
+StmtResult
+Sema::ActOnSEHTryBlock(bool IsCXXTry,
+ SourceLocation TryLoc,
+ Stmt *TryBlock,
+ Stmt *Handler) {
assert(TryBlock && Handler);
getCurFunction()->setHasBranchProtectedScope();
- return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler,
- HandlerIndex, HandlerParentIndex);
+ return SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler);
}
StmtResult
@@ -3330,6 +3438,7 @@ Sema::CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc,
else
RD = RecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/nullptr);
+ RD->setCapturedRecord();
DC->addDecl(RD);
RD->setImplicit();
RD->startDefinition();
@@ -3353,6 +3462,11 @@ static void buildCapturedStmtCaptureList(
CapturedStmt::VCK_This));
CaptureInits.push_back(Cap->getInitExpr());
continue;
+ } else if (Cap->isVLATypeCapture()) {
+ Captures.push_back(
+ CapturedStmt::Capture(Cap->getLocation(), CapturedStmt::VCK_VLAType));
+ CaptureInits.push_back(nullptr);
+ continue;
}
assert(Cap->isReferenceCapture() &&
diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp
index 5d076cac940f..286c7619ed40 100644
--- a/lib/Sema/SemaStmtAsm.cpp
+++ b/lib/Sema/SemaStmtAsm.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/RecordLayout.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
@@ -74,6 +75,32 @@ static bool isOperandMentioned(unsigned OpNo,
return false;
}
+static bool CheckNakedParmReference(Expr *E, Sema &S) {
+ FunctionDecl *Func = dyn_cast<FunctionDecl>(S.CurContext);
+ if (!Func)
+ return false;
+ if (!Func->hasAttr<NakedAttr>())
+ return false;
+
+ SmallVector<Expr*, 4> WorkList;
+ WorkList.push_back(E);
+ while (WorkList.size()) {
+ Expr *E = WorkList.pop_back_val();
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (isa<ParmVarDecl>(DRE->getDecl())) {
+ S.Diag(DRE->getLocStart(), diag::err_asm_naked_parm_ref);
+ S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
+ return true;
+ }
+ }
+ for (Stmt *Child : E->children()) {
+ if (Expr *E = dyn_cast_or_null<Expr>(Child))
+ WorkList.push_back(E);
+ }
+ }
+ return false;
+}
+
StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
bool IsVolatile, unsigned NumOutputs,
unsigned NumInputs, IdentifierInfo **Names,
@@ -89,15 +116,11 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
// The parser verifies that there is a string literal here.
- if (!AsmString->isAscii())
- return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character)
- << AsmString->getSourceRange());
+ assert(AsmString->isAscii());
for (unsigned i = 0; i != NumOutputs; i++) {
StringLiteral *Literal = Constraints[i];
- if (!Literal->isAscii())
- return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
- << Literal->getSourceRange());
+ assert(Literal->isAscii());
StringRef OutputName;
if (Names[i])
@@ -109,27 +132,69 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
diag::err_asm_invalid_output_constraint)
<< Info.getConstraintStr());
+ ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
+ if (ER.isInvalid())
+ return StmtError();
+ Exprs[i] = ER.get();
+
// Check that the output exprs are valid lvalues.
Expr *OutputExpr = Exprs[i];
- if (CheckAsmLValue(OutputExpr, *this))
- return StmtError(Diag(OutputExpr->getLocStart(),
- diag::err_asm_invalid_lvalue_in_output)
- << OutputExpr->getSourceRange());
- if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
- diag::err_dereference_incomplete_type))
+ // Referring to parameters is not allowed in naked functions.
+ if (CheckNakedParmReference(OutputExpr, *this))
return StmtError();
OutputConstraintInfos.push_back(Info);
+
+ // If this is dependent, just continue.
+ if (OutputExpr->isTypeDependent())
+ continue;
+
+ Expr::isModifiableLvalueResult IsLV =
+ OutputExpr->isModifiableLvalue(Context, /*Loc=*/nullptr);
+ switch (IsLV) {
+ case Expr::MLV_Valid:
+ // Cool, this is an lvalue.
+ break;
+ case Expr::MLV_ArrayType:
+ // This is OK too.
+ break;
+ case Expr::MLV_LValueCast: {
+ const Expr *LVal = OutputExpr->IgnoreParenNoopCasts(Context);
+ if (!getLangOpts().HeinousExtensions) {
+ Diag(LVal->getLocStart(), diag::err_invalid_asm_cast_lvalue)
+ << OutputExpr->getSourceRange();
+ } else {
+ Diag(LVal->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
+ << OutputExpr->getSourceRange();
+ }
+ // Accept, even if we emitted an error diagnostic.
+ break;
+ }
+ case Expr::MLV_IncompleteType:
+ case Expr::MLV_IncompleteVoidType:
+ if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
+ diag::err_dereference_incomplete_type))
+ return StmtError();
+ default:
+ return StmtError(Diag(OutputExpr->getLocStart(),
+ diag::err_asm_invalid_lvalue_in_output)
+ << OutputExpr->getSourceRange());
+ }
+
+ unsigned Size = Context.getTypeSize(OutputExpr->getType());
+ if (!Context.getTargetInfo().validateOutputSize(Literal->getString(),
+ Size))
+ return StmtError(Diag(OutputExpr->getLocStart(),
+ diag::err_asm_invalid_output_size)
+ << Info.getConstraintStr());
}
SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
StringLiteral *Literal = Constraints[i];
- if (!Literal->isAscii())
- return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
- << Literal->getSourceRange());
+ assert(Literal->isAscii());
StringRef InputName;
if (Names[i])
@@ -143,8 +208,17 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
<< Info.getConstraintStr());
}
+ ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
+ if (ER.isInvalid())
+ return StmtError();
+ Exprs[i] = ER.get();
+
Expr *InputExpr = Exprs[i];
+ // Referring to parameters is not allowed in naked functions.
+ if (CheckNakedParmReference(InputExpr, *this))
+ return StmtError();
+
// Only allow void types for memory constraints.
if (Info.allowsMemory() && !Info.allowsRegister()) {
if (CheckAsmLValue(InputExpr, *this))
@@ -152,6 +226,20 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
diag::err_asm_invalid_lvalue_in_input)
<< Info.getConstraintStr()
<< InputExpr->getSourceRange());
+ } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
+ llvm::APSInt Result;
+ if (!InputExpr->EvaluateAsInt(Result, Context))
+ return StmtError(
+ Diag(InputExpr->getLocStart(), diag::err_asm_invalid_type_in_input)
+ << InputExpr->getType() << Info.getConstraintStr()
+ << InputExpr->getSourceRange());
+ if (Result.slt(Info.getImmConstantMin()) ||
+ Result.sgt(Info.getImmConstantMax()))
+ return StmtError(Diag(InputExpr->getLocStart(),
+ diag::err_invalid_asm_value_for_constraint)
+ << Result.toString(10) << Info.getConstraintStr()
+ << InputExpr->getSourceRange());
+
} else {
ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
if (Result.isInvalid())
@@ -191,9 +279,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
// Check that the clobbers are valid.
for (unsigned i = 0; i != NumClobbers; i++) {
StringLiteral *Literal = Clobbers[i];
- if (!Literal->isAscii())
- return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
- << Literal->getSourceRange());
+ assert(Literal->isAscii());
StringRef Clobber = Literal->getString();
@@ -257,16 +343,47 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
continue;
unsigned Size = Context.getTypeSize(Ty);
- if (!Context.getTargetInfo()
- .validateConstraintModifier(Literal->getString(), Piece.getModifier(),
- Size))
+ std::string SuggestedModifier;
+ if (!Context.getTargetInfo().validateConstraintModifier(
+ Literal->getString(), Piece.getModifier(), Size,
+ SuggestedModifier)) {
Diag(Exprs[ConstraintIdx]->getLocStart(),
diag::warn_asm_mismatched_size_modifier);
+
+ if (!SuggestedModifier.empty()) {
+ auto B = Diag(Piece.getRange().getBegin(),
+ diag::note_asm_missing_constraint_modifier)
+ << SuggestedModifier;
+ SuggestedModifier = "%" + SuggestedModifier + Piece.getString();
+ B.AddFixItHint(FixItHint::CreateReplacement(Piece.getRange(),
+ SuggestedModifier));
+ }
+ }
}
// Validate tied input operands for type mismatches.
+ unsigned NumAlternatives = ~0U;
+ for (unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) {
+ TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
+ StringRef ConstraintStr = Info.getConstraintStr();
+ unsigned AltCount = ConstraintStr.count(',') + 1;
+ if (NumAlternatives == ~0U)
+ NumAlternatives = AltCount;
+ else if (NumAlternatives != AltCount)
+ return StmtError(Diag(NS->getOutputExpr(i)->getLocStart(),
+ diag::err_asm_unexpected_constraint_alternatives)
+ << NumAlternatives << AltCount);
+ }
for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
+ StringRef ConstraintStr = Info.getConstraintStr();
+ unsigned AltCount = ConstraintStr.count(',') + 1;
+ if (NumAlternatives == ~0U)
+ NumAlternatives = AltCount;
+ else if (NumAlternatives != AltCount)
+ return StmtError(Diag(NS->getInputExpr(i)->getLocStart(),
+ diag::err_asm_unexpected_constraint_alternatives)
+ << NumAlternatives << AltCount);
// If this is a tied constraint, verify that the output and input have
// either exactly the same type, or that they are int/ptr operands with the
@@ -394,6 +511,10 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
Result = CheckPlaceholderExpr(Result.get());
if (!Result.isUsable()) return Result;
+ // Referring to parameters is not allowed in naked functions.
+ if (CheckNakedParmReference(Result.get(), *this))
+ return ExprError();
+
QualType T = Result.get()->getType();
// For now, reject dependent types.
@@ -443,9 +564,10 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
NamedDecl *FoundDecl = BaseResult.getFoundDecl();
if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
RT = VD->getType()->getAs<RecordType>();
- else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl))
+ else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) {
+ MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
RT = TD->getUnderlyingType()->getAs<RecordType>();
- else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
+ } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
RT = TD->getTypeForDecl()->getAs<RecordType>();
if (!RT)
return true;
@@ -481,6 +603,7 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
ArrayRef<Expr*> Exprs,
SourceLocation EndLoc) {
bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
+ getCurFunction()->setHasBranchProtectedScope();
MSAsmStmt *NS =
new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
/*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
@@ -488,3 +611,34 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
Clobbers, EndLoc);
return NS;
}
+
+LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
+ SourceLocation Location,
+ bool AlwaysCreate) {
+ LabelDecl* Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
+ Location);
+
+ if (Label->isMSAsmLabel()) {
+ // If we have previously created this label implicitly, mark it as used.
+ Label->markUsed(Context);
+ } else {
+ // Otherwise, insert it, but only resolve it if we have seen the label itself.
+ std::string InternalName;
+ llvm::raw_string_ostream OS(InternalName);
+ // Create an internal name for the label. The name should not be a valid mangled
+ // name, and should be unique. We use a dot to make the name an invalid mangled
+ // name.
+ OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__" << ExternalLabelName;
+ Label->setMSAsmLabel(OS.str());
+ }
+ if (AlwaysCreate) {
+ // The label might have been created implicitly from a previously encountered
+ // goto statement. So, for both newly created and looked up labels, we mark
+ // them as resolved.
+ Label->setMSAsmLabelResolved();
+ }
+ // Adjust their location for being able to generate accurate diagnostics.
+ Label->setLocation(Location);
+
+ return Label;
+}
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index a32e0fbcb622..19e2c8ed652f 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -47,30 +47,36 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
SourceRange) {
IdentifierLoc *PragmaNameLoc = A.getArgAsIdent(0);
IdentifierLoc *OptionLoc = A.getArgAsIdent(1);
- IdentifierInfo *OptionInfo = OptionLoc->Ident;
- IdentifierLoc *ValueLoc = A.getArgAsIdent(2);
- IdentifierInfo *ValueInfo = ValueLoc ? ValueLoc->Ident : nullptr;
+ IdentifierLoc *StateLoc = A.getArgAsIdent(2);
Expr *ValueExpr = A.getArgAsExpr(3);
- assert(OptionInfo && "Attribute must have valid option info.");
-
+ bool PragmaUnroll = PragmaNameLoc->Ident->getName() == "unroll";
+ bool PragmaNoUnroll = PragmaNameLoc->Ident->getName() == "nounroll";
if (St->getStmtClass() != Stmt::DoStmtClass &&
St->getStmtClass() != Stmt::ForStmtClass &&
St->getStmtClass() != Stmt::CXXForRangeStmtClass &&
St->getStmtClass() != Stmt::WhileStmtClass) {
- const char *Pragma = PragmaNameLoc->Ident->getName() == "unroll"
- ? "#pragma unroll"
- : "#pragma clang loop";
+ const char *Pragma =
+ llvm::StringSwitch<const char *>(PragmaNameLoc->Ident->getName())
+ .Case("unroll", "#pragma unroll")
+ .Case("nounroll", "#pragma nounroll")
+ .Default("#pragma clang loop");
S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
return nullptr;
}
LoopHintAttr::OptionType Option;
LoopHintAttr::Spelling Spelling;
- if (PragmaNameLoc->Ident->getName() == "unroll") {
- Option = ValueLoc ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll;
+ if (PragmaUnroll) {
+ Option = ValueExpr ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll;
Spelling = LoopHintAttr::Pragma_unroll;
+ } else if (PragmaNoUnroll) {
+ Option = LoopHintAttr::Unroll;
+ Spelling = LoopHintAttr::Pragma_nounroll;
} else {
+ assert(OptionLoc && OptionLoc->Ident &&
+ "Attribute must have valid option info.");
+ IdentifierInfo *OptionInfo = OptionLoc->Ident;
Option = llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName())
.Case("vectorize", LoopHintAttr::Vectorize)
.Case("vectorize_width", LoopHintAttr::VectorizeWidth)
@@ -82,53 +88,45 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
Spelling = LoopHintAttr::Pragma_clang_loop;
}
- int ValueInt;
- if (Option == LoopHintAttr::Unroll &&
- Spelling == LoopHintAttr::Pragma_unroll) {
- ValueInt = 1;
- } else if (Option == LoopHintAttr::Vectorize ||
- Option == LoopHintAttr::Interleave ||
- Option == LoopHintAttr::Unroll) {
- if (!ValueInfo) {
- S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword);
- return nullptr;
- }
- if (ValueInfo->isStr("disable"))
- ValueInt = 0;
- else if (ValueInfo->isStr("enable"))
- ValueInt = 1;
- else {
- S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword);
- return nullptr;
- }
+ LoopHintAttr::LoopHintState State = LoopHintAttr::Default;
+ if (PragmaNoUnroll) {
+ State = LoopHintAttr::Disable;
} else if (Option == LoopHintAttr::VectorizeWidth ||
Option == LoopHintAttr::InterleaveCount ||
Option == LoopHintAttr::UnrollCount) {
- // FIXME: We should support template parameters for the loop hint value.
- // See bug report #19610.
- llvm::APSInt ValueAPS;
- if (!ValueExpr || !ValueExpr->isIntegerConstantExpr(ValueAPS, S.Context) ||
- (ValueInt = ValueAPS.getSExtValue()) < 1) {
- S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value);
+ assert(ValueExpr && "Attribute must have a valid value expression.");
+ if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart()))
return nullptr;
+ } else if (Option == LoopHintAttr::Vectorize ||
+ Option == LoopHintAttr::Interleave ||
+ Option == LoopHintAttr::Unroll) {
+ // Default state is assumed if StateLoc is not specified, such as with
+ // '#pragma unroll'.
+ if (StateLoc && StateLoc->Ident) {
+ if (StateLoc->Ident->isStr("disable"))
+ State = LoopHintAttr::Disable;
+ else
+ State = LoopHintAttr::Enable;
}
- } else
- llvm_unreachable("Unknown loop hint option");
+ }
- return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, ValueInt,
- A.getRange());
+ return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, State,
+ ValueExpr, A.getRange());
}
-static void CheckForIncompatibleAttributes(
- Sema &S, const SmallVectorImpl<const Attr *> &Attrs) {
- // There are 3 categories of loop hints: vectorize, interleave, and
- // unroll. Each comes in two variants: an enable/disable form and a
- // form which takes a numeric argument. For example:
- // unroll(enable|disable) and unroll_count(N). The following array
- // accumulate the hints encountered while iterating through the
- // attributes to check for compatibility.
+static void
+CheckForIncompatibleAttributes(Sema &S,
+ const SmallVectorImpl<const Attr *> &Attrs) {
+ // There are 3 categories of loop hints attributes: vectorize, interleave,
+ // and unroll. Each comes in two variants: a state form and a numeric form.
+ // The state form selectively defaults/enables/disables the transformation
+ // for the loop (for unroll, default indicates full unrolling rather than
+ // enabling the transformation). The numeric form form provides an integer
+ // hint (for example, unroll count) to the transformer. The following array
+ // accumulates the hints encountered while iterating through the attributes
+ // to check for compatibility.
struct {
- const LoopHintAttr *EnableAttr;
+ const LoopHintAttr *StateAttr;
const LoopHintAttr *NumericAttr;
} HintAttrs[] = {{nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}};
@@ -141,49 +139,53 @@ static void CheckForIncompatibleAttributes(
int Option = LH->getOption();
int Category;
+ enum { Vectorize, Interleave, Unroll };
switch (Option) {
case LoopHintAttr::Vectorize:
case LoopHintAttr::VectorizeWidth:
- Category = 0;
+ Category = Vectorize;
break;
case LoopHintAttr::Interleave:
case LoopHintAttr::InterleaveCount:
- Category = 1;
+ Category = Interleave;
break;
case LoopHintAttr::Unroll:
case LoopHintAttr::UnrollCount:
- Category = 2;
+ Category = Unroll;
break;
};
auto &CategoryState = HintAttrs[Category];
- SourceLocation OptionLoc = LH->getRange().getBegin();
const LoopHintAttr *PrevAttr;
if (Option == LoopHintAttr::Vectorize ||
Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) {
// Enable|disable hint. For example, vectorize(enable).
- PrevAttr = CategoryState.EnableAttr;
- CategoryState.EnableAttr = LH;
+ PrevAttr = CategoryState.StateAttr;
+ CategoryState.StateAttr = LH;
} else {
// Numeric hint. For example, vectorize_width(8).
PrevAttr = CategoryState.NumericAttr;
CategoryState.NumericAttr = LH;
}
+ PrintingPolicy Policy(S.Context.getLangOpts());
+ SourceLocation OptionLoc = LH->getRange().getBegin();
if (PrevAttr)
// Cannot specify same type of attribute twice.
S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
- << /*Duplicate=*/true << PrevAttr->getDiagnosticName()
- << LH->getDiagnosticName();
-
- if (CategoryState.EnableAttr && !CategoryState.EnableAttr->getValue() &&
- CategoryState.NumericAttr) {
- // Disable hints are not compatible with numeric hints of the
- // same category.
+ << /*Duplicate=*/true << PrevAttr->getDiagnosticName(Policy)
+ << LH->getDiagnosticName(Policy);
+
+ if (CategoryState.StateAttr && CategoryState.NumericAttr &&
+ (Category == Unroll ||
+ CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) {
+ // Disable hints are not compatible with numeric hints of the same
+ // category. As a special case, numeric unroll hints are also not
+ // compatible with "enable" form of the unroll pragma, unroll(full).
S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
<< /*Duplicate=*/false
- << CategoryState.EnableAttr->getDiagnosticName()
- << CategoryState.NumericAttr->getDiagnosticName();
+ << CategoryState.StateAttr->getDiagnosticName(Policy)
+ << CategoryState.NumericAttr->getDiagnosticName(Policy);
}
}
}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 7e8f0b721dfe..67c36a5fb5e9 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -107,7 +107,7 @@ void Sema::FilterAcceptableTemplateNames(LookupResult &R,
// template itself and not a specialization thereof, and is not
// ambiguous.
if (ClassTemplateDecl *ClassTmpl = dyn_cast<ClassTemplateDecl>(Repl))
- if (!ClassTemplates.insert(ClassTmpl)) {
+ if (!ClassTemplates.insert(ClassTmpl).second) {
filter.erase();
continue;
}
@@ -318,15 +318,14 @@ void Sema::LookupTemplateName(LookupResult &Found,
DeclarationName Name = Found.getLookupName();
Found.clear();
// Simple filter callback that, for keywords, only accepts the C++ *_cast
- CorrectionCandidateCallback FilterCCC;
- FilterCCC.WantTypeSpecifiers = false;
- FilterCCC.WantExpressionKeywords = false;
- FilterCCC.WantRemainingKeywords = false;
- FilterCCC.WantCXXNamedCasts = true;
- if (TypoCorrection Corrected = CorrectTypo(Found.getLookupNameInfo(),
- Found.getLookupKind(), S, &SS,
- FilterCCC, CTK_ErrorRecovery,
- LookupCtx)) {
+ auto FilterCCC = llvm::make_unique<CorrectionCandidateCallback>();
+ FilterCCC->WantTypeSpecifiers = false;
+ FilterCCC->WantExpressionKeywords = false;
+ FilterCCC->WantRemainingKeywords = false;
+ FilterCCC->WantCXXNamedCasts = true;
+ if (TypoCorrection Corrected = CorrectTypo(
+ Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS,
+ std::move(FilterCCC), CTK_ErrorRecovery, LookupCtx)) {
Found.setLookupName(Corrected.getCorrection());
if (Corrected.getCorrectionDecl())
Found.addDecl(Corrected.getCorrectionDecl());
@@ -652,12 +651,8 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
// A non-type template-parameter of type "array of T" or
// "function returning T" is adjusted to be of type "pointer to
// T" or "pointer to function returning T", respectively.
- else if (T->isArrayType())
- // FIXME: Keep the type prior to promotion?
- return Context.getArrayDecayedType(T);
- else if (T->isFunctionType())
- // FIXME: Keep the type prior to promotion?
- return Context.getPointerType(T);
+ else if (T->isArrayType() || T->isFunctionType())
+ return Context.getDecayedType(T);
Diag(Loc, diag::err_template_nontype_parm_bad_type)
<< T;
@@ -720,7 +715,8 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
return Param;
TemplateArgument Converted;
- ExprResult DefaultRes = CheckTemplateArgument(Param, Param->getType(), Default, Converted);
+ ExprResult DefaultRes =
+ CheckTemplateArgument(Param, Param->getType(), Default, Converted);
if (DefaultRes.isInvalid()) {
Param->setInvalidDecl();
return Param;
@@ -1105,9 +1101,13 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
AddPushedVisibilityAttribute(NewClass);
- if (TUK != TUK_Friend)
- PushOnScopeChains(NewTemplate, S);
- else {
+ if (TUK != TUK_Friend) {
+ // Per C++ [basic.scope.temp]p2, skip the template parameter scopes.
+ Scope *Outer = S;
+ while ((Outer->getFlags() & Scope::TemplateParamScope) != 0)
+ Outer = Outer->getParent();
+ PushOnScopeChains(NewTemplate, Outer);
+ } else {
if (PrevClassTemplate && PrevClassTemplate->getAccess() != AS_none) {
NewTemplate->setAccess(PrevClassTemplate->getAccess());
NewClass->setAccess(PrevClassTemplate->getAccess());
@@ -2396,7 +2396,7 @@ makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {
DeclResult Sema::ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation TemplateKWLoc,
- TemplateParameterList *TemplateParams, VarDecl::StorageClass SC,
+ TemplateParameterList *TemplateParams, StorageClass SC,
bool IsPartialSpecialization) {
// D must be variable template id.
assert(D.getName().getKind() == UnqualifiedId::IK_TemplateId &&
@@ -4106,6 +4106,7 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
return false;
case NestedNameSpecifier::TypeSpec:
@@ -4595,8 +4596,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
return true;
// Create the template argument.
- Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
- ParamType->isReferenceType());
+ Converted =
+ TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()), ParamType);
S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity, false);
return false;
}
@@ -4691,7 +4692,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
Converted = TemplateArgument(Arg);
} else {
VD = cast<ValueDecl>(VD->getCanonicalDecl());
- Converted = TemplateArgument(VD, /*isReferenceParam*/false);
+ Converted = TemplateArgument(VD, ParamType);
}
return Invalid;
}
@@ -4720,7 +4721,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
Converted = TemplateArgument(Arg);
} else {
ValueDecl *D = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
- Converted = TemplateArgument(D, /*isReferenceParam*/false);
+ Converted = TemplateArgument(D, ParamType);
}
return Invalid;
}
@@ -4738,30 +4739,152 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
///
/// This routine implements the semantics of C++ [temp.arg.nontype].
/// If an error occurred, it returns ExprError(); otherwise, it
-/// returns the converted template argument. \p
-/// InstantiatedParamType is the type of the non-type template
-/// parameter after it has been instantiated.
+/// returns the converted template argument. \p ParamType is the
+/// type of the non-type template parameter after it has been instantiated.
ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
- QualType InstantiatedParamType, Expr *Arg,
+ QualType ParamType, Expr *Arg,
TemplateArgument &Converted,
CheckTemplateArgumentKind CTAK) {
SourceLocation StartLoc = Arg->getLocStart();
// If either the parameter has a dependent type or the argument is
// type-dependent, there's nothing we can check now.
- if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) {
+ if (ParamType->isDependentType() || Arg->isTypeDependent()) {
// FIXME: Produce a cloned, canonical expression?
Converted = TemplateArgument(Arg);
return Arg;
}
+ // We should have already dropped all cv-qualifiers by now.
+ assert(!ParamType.hasQualifiers() &&
+ "non-type template parameter type cannot be qualified");
+
+ if (CTAK == CTAK_Deduced &&
+ !Context.hasSameUnqualifiedType(ParamType, Arg->getType())) {
+ // C++ [temp.deduct.type]p17:
+ // If, in the declaration of a function template with a non-type
+ // template-parameter, the non-type template-parameter is used
+ // in an expression in the function parameter-list and, if the
+ // corresponding template-argument is deduced, the
+ // template-argument type shall match the type of the
+ // template-parameter exactly, except that a template-argument
+ // deduced from an array bound may be of any integral type.
+ Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
+ << Arg->getType().getUnqualifiedType()
+ << ParamType.getUnqualifiedType();
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return ExprError();
+ }
+
+ if (getLangOpts().CPlusPlus1z) {
+ // FIXME: We can do some limited checking for a value-dependent but not
+ // type-dependent argument.
+ if (Arg->isValueDependent()) {
+ Converted = TemplateArgument(Arg);
+ return Arg;
+ }
+
+ // C++1z [temp.arg.nontype]p1:
+ // A template-argument for a non-type template parameter shall be
+ // a converted constant expression of the type of the template-parameter.
+ APValue Value;
+ ExprResult ArgResult = CheckConvertedConstantExpression(
+ Arg, ParamType, Value, CCEK_TemplateArg);
+ if (ArgResult.isInvalid())
+ return ExprError();
+
+ QualType CanonParamType = Context.getCanonicalType(ParamType);
+
+ // Convert the APValue to a TemplateArgument.
+ switch (Value.getKind()) {
+ case APValue::Uninitialized:
+ assert(ParamType->isNullPtrType());
+ Converted = TemplateArgument(CanonParamType, /*isNullPtr*/true);
+ break;
+ case APValue::Int:
+ assert(ParamType->isIntegralOrEnumerationType());
+ Converted = TemplateArgument(Context, Value.getInt(), CanonParamType);
+ break;
+ case APValue::MemberPointer: {
+ assert(ParamType->isMemberPointerType());
+
+ // FIXME: We need TemplateArgument representation and mangling for these.
+ if (!Value.getMemberPointerPath().empty()) {
+ Diag(Arg->getLocStart(),
+ diag::err_template_arg_member_ptr_base_derived_not_supported)
+ << Value.getMemberPointerDecl() << ParamType
+ << Arg->getSourceRange();
+ return ExprError();
+ }
+
+ auto *VD = const_cast<ValueDecl*>(Value.getMemberPointerDecl());
+ Converted = VD ? TemplateArgument(VD, CanonParamType)
+ : TemplateArgument(CanonParamType, /*isNullPtr*/true);
+ break;
+ }
+ case APValue::LValue: {
+ // For a non-type template-parameter of pointer or reference type,
+ // the value of the constant expression shall not refer to
+ assert(ParamType->isPointerType() || ParamType->isReferenceType() ||
+ ParamType->isNullPtrType());
+ // -- a temporary object
+ // -- a string literal
+ // -- the result of a typeid expression, or
+ // -- a predefind __func__ variable
+ if (auto *E = Value.getLValueBase().dyn_cast<const Expr*>()) {
+ if (isa<CXXUuidofExpr>(E)) {
+ Converted = TemplateArgument(const_cast<Expr*>(E));
+ break;
+ }
+ Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
+ << Arg->getSourceRange();
+ return ExprError();
+ }
+ auto *VD = const_cast<ValueDecl *>(
+ Value.getLValueBase().dyn_cast<const ValueDecl *>());
+ // -- a subobject
+ if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 &&
+ VD && VD->getType()->isArrayType() &&
+ Value.getLValuePath()[0].ArrayIndex == 0 &&
+ !Value.isLValueOnePastTheEnd() && ParamType->isPointerType()) {
+ // Per defect report (no number yet):
+ // ... other than a pointer to the first element of a complete array
+ // object.
+ } else if (!Value.hasLValuePath() || Value.getLValuePath().size() ||
+ Value.isLValueOnePastTheEnd()) {
+ Diag(StartLoc, diag::err_non_type_template_arg_subobject)
+ << Value.getAsString(Context, ParamType);
+ return ExprError();
+ }
+ assert((VD || !ParamType->isReferenceType()) &&
+ "null reference should not be a constant expression");
+ assert((!VD || !ParamType->isNullPtrType()) &&
+ "non-null value of type nullptr_t?");
+ Converted = VD ? TemplateArgument(VD, CanonParamType)
+ : TemplateArgument(CanonParamType, /*isNullPtr*/true);
+ break;
+ }
+ case APValue::AddrLabelDiff:
+ return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_diff);
+ case APValue::Float:
+ case APValue::ComplexInt:
+ case APValue::ComplexFloat:
+ case APValue::Vector:
+ case APValue::Array:
+ case APValue::Struct:
+ case APValue::Union:
+ llvm_unreachable("invalid kind for template argument");
+ }
+
+ return ArgResult.get();
+ }
+
// C++ [temp.arg.nontype]p5:
// The following conversions are performed on each expression used
// as a non-type template-argument. If a non-type
// template-argument cannot be converted to the type of the
// corresponding template-parameter then the program is
// ill-formed.
- QualType ParamType = InstantiatedParamType;
if (ParamType->isIntegralOrEnumerationType()) {
// C++11:
// -- for a non-type template-parameter of integral or
@@ -4773,23 +4896,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// enumeration type, integral promotions (4.5) and integral
// conversions (4.7) are applied.
- if (CTAK == CTAK_Deduced &&
- !Context.hasSameUnqualifiedType(ParamType, Arg->getType())) {
- // C++ [temp.deduct.type]p17:
- // If, in the declaration of a function template with a non-type
- // template-parameter, the non-type template-parameter is used
- // in an expression in the function parameter-list and, if the
- // corresponding template-argument is deduced, the
- // template-argument type shall match the type of the
- // template-parameter exactly, except that a template-argument
- // deduced from an array bound may be of any integral type.
- Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
- << Arg->getType().getUnqualifiedType()
- << ParamType.getUnqualifiedType();
- Diag(Param->getLocation(), diag::note_template_param_here);
- return ExprError();
- }
-
if (getLangOpts().CPlusPlus11) {
// We can't check arbitrary value-dependent arguments.
// FIXME: If there's no viable conversion to the template parameter type,
@@ -4867,9 +4973,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return ExprError();
}
- // From here on out, all we care about are the unqualified forms
- // of the parameter and argument types.
- ParamType = ParamType.getUnqualifiedType();
+ // From here on out, all we care about is the unqualified form
+ // of the argument type.
ArgType = ArgType.getUnqualifiedType();
// Try to convert the argument to the parameter's type.
@@ -4886,7 +4991,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// We can't perform this conversion.
Diag(Arg->getLocStart(),
diag::err_template_arg_not_convertible)
- << Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
+ << Arg->getType() << ParamType << Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
return ExprError();
}
@@ -6329,14 +6434,11 @@ Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
/// \brief Strips various properties off an implicit instantiation
/// that has just been explicitly specialized.
static void StripImplicitInstantiation(NamedDecl *D) {
- D->dropAttrs();
+ D->dropAttr<DLLImportAttr>();
+ D->dropAttr<DLLExportAttr>();
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
FD->setInlineSpecified(false);
-
- for (auto I : FD->params())
- I->dropAttrs();
- }
}
/// \brief Compute the diagnostic location for an explicit instantiation
@@ -7606,6 +7708,29 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// Ignore access control bits, we don't need them for redeclaration checking.
FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
+ // C++11 [except.spec]p4
+ // In an explicit instantiation an exception-specification may be specified,
+ // but is not required.
+ // If an exception-specification is specified in an explicit instantiation
+ // directive, it shall be compatible with the exception-specifications of
+ // other declarations of that function.
+ if (auto *FPT = R->getAs<FunctionProtoType>())
+ if (FPT->hasExceptionSpec()) {
+ unsigned DiagID =
+ diag::err_mismatched_exception_spec_explicit_instantiation;
+ if (getLangOpts().MicrosoftExt)
+ DiagID = diag::ext_mismatched_exception_spec_explicit_instantiation;
+ bool Result = CheckEquivalentExceptionSpec(
+ PDiag(DiagID) << Specialization->getType(),
+ PDiag(diag::note_explicit_instantiation_here),
+ Specialization->getType()->getAs<FunctionProtoType>(),
+ Specialization->getLocation(), FPT, D.getLocStart());
+ // In Microsoft mode, mismatching exception specifications just cause a
+ // warning.
+ if (!getLangOpts().MicrosoftExt && Result)
+ return true;
+ }
+
if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) {
Diag(D.getIdentifierLoc(),
diag::err_explicit_instantiation_member_function_not_instantiated)
@@ -7879,7 +8004,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
DeclarationName Name(&II);
LookupResult Result(*this, Name, IILoc, LookupOrdinaryName);
- LookupQualifiedName(Result, Ctx);
+ LookupQualifiedName(Result, Ctx, SS);
unsigned DiagID = 0;
Decl *Referenced = nullptr;
switch (Result.getResultKind()) {
@@ -7924,6 +8049,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {
// We found a type. Build an ElaboratedType, since the
// typename-specifier was just sugar.
+ MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false);
return Context.getElaboratedType(ETK_Typename,
QualifierLoc.getNestedNameSpecifier(),
Context.getTypeDeclType(Type));
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 53a75d227c7b..dd2a4d26979e 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -262,8 +262,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
// If we deduced two declarations, make sure they they refer to the
// same declaration.
if (Y.getKind() == TemplateArgument::Declaration &&
- isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) &&
- X.isDeclForReferenceParam() == Y.isDeclForReferenceParam())
+ isSameDeclaration(X.getAsDecl(), Y.getAsDecl()))
return X;
// All other combinations are incompatible.
@@ -384,7 +383,7 @@ DeduceNonTypeTemplateArgument(Sema &S,
"Cannot deduce non-type template argument with depth > 0");
D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
- TemplateArgument New(D, NTTP->getType()->isReferenceType());
+ TemplateArgument New(D, NTTP->getType());
DeducedTemplateArgument NewDeduced(New);
DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
Deduced[NTTP->getIndex()],
@@ -1302,7 +1301,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
// T &
case Type::LValueReference: {
- const LValueReferenceType *ReferenceArg = Arg->getAs<LValueReferenceType>();
+ const LValueReferenceType *ReferenceArg =
+ Arg->getAs<LValueReferenceType>();
if (!ReferenceArg)
return Sema::TDK_NonDeducedMismatch;
@@ -1313,7 +1313,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
// T && [C++0x]
case Type::RValueReference: {
- const RValueReferenceType *ReferenceArg = Arg->getAs<RValueReferenceType>();
+ const RValueReferenceType *ReferenceArg =
+ Arg->getAs<RValueReferenceType>();
if (!ReferenceArg)
return Sema::TDK_NonDeducedMismatch;
@@ -1492,7 +1493,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
const RecordType *NextT = ToVisit.pop_back_val();
// If we have already seen this type, skip it.
- if (!Visited.insert(NextT))
+ if (!Visited.insert(NextT).second)
continue;
// If this is a base class, try to perform template argument
@@ -1726,8 +1727,7 @@ DeduceTemplateArguments(Sema &S,
case TemplateArgument::Declaration:
if (Arg.getKind() == TemplateArgument::Declaration &&
- isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl()) &&
- Param.isDeclForReferenceParam() == Arg.isDeclForReferenceParam())
+ isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl()))
return Sema::TDK_Success;
Info.FirstArg = Param;
@@ -1962,8 +1962,7 @@ static bool isSameTemplateArg(ASTContext &Context,
Context.getCanonicalType(Y.getAsType());
case TemplateArgument::Declaration:
- return isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) &&
- X.isDeclForReferenceParam() == Y.isDeclForReferenceParam();
+ return isSameDeclaration(X.getAsDecl(), Y.getAsDecl());
case TemplateArgument::NullPtr:
return Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType());
@@ -2056,7 +2055,8 @@ getTrivialTemplateArgumentLoc(Sema &S,
TemplateName Template = Arg.getAsTemplate();
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
Builder.MakeTrivial(S.Context, DTN->getQualifier(), Loc);
- else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
+ else if (QualifiedTemplateName *QTN =
+ Template.getAsQualifiedTemplateName())
Builder.MakeTrivial(S.Context, QTN->getQualifier(), Loc);
if (Arg.getKind() == TemplateArgument::Template)
@@ -2588,6 +2588,9 @@ Sema::SubstituteExplicitTemplateArguments(
= Function->getType()->getAs<FunctionProtoType>();
assert(Proto && "Function template does not have a prototype?");
+ // Isolate our substituted parameters from our caller.
+ LocalInstantiationScope InstScope(*this, /*MergeWithOuterScope*/true);
+
// Instantiate the types of each of the function parameters given the
// explicitly-specified template arguments. If the function has a trailing
// return type, substitute it after the arguments to ensure we substitute
@@ -3000,7 +3003,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
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->getReturnType()->isUndeducedType() &&
+ if (S.getLangOpts().CPlusPlus14 && Fn->getReturnType()->isUndeducedType() &&
S.DeduceReturnType(Fn, R.Expression->getExprLoc(), /*Diagnose*/ false))
return QualType();
@@ -3229,9 +3232,9 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
return false;
}
-static bool hasDeducibleTemplateParameters(Sema &S,
- FunctionTemplateDecl *FunctionTemplate,
- QualType T);
+static bool
+hasDeducibleTemplateParameters(Sema &S, FunctionTemplateDecl *FunctionTemplate,
+ QualType T);
/// \brief Perform template argument deduction by matching a parameter type
/// against a single expression, where the expression is an element of
@@ -3488,8 +3491,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
}
return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
- NumExplicitlySpecified,
- Specialization, Info, &OriginalCallArgs);
+ NumExplicitlySpecified, Specialization,
+ Info, &OriginalCallArgs);
}
QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
@@ -3579,7 +3582,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// If the function has a deduced return type, substitute it for a dependent
// type so that we treat it as a non-deduced context in what follows.
bool HasDeducedReturnType = false;
- if (getLangOpts().CPlusPlus1y && InOverloadResolution &&
+ if (getLangOpts().CPlusPlus14 && InOverloadResolution &&
Function->getReturnType()->getContainedAutoType()) {
FunctionType = SubstAutoType(FunctionType, Context.DependentTy);
HasDeducedReturnType = true;
@@ -3788,7 +3791,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// C++0x [temp.deduct.conv]p4:
// If A is a cv-qualified type, the top level cv-qualifiers of A's
- // type are ignored for type deduction. If A is a reference type, the type
+ // type are ignored for type deduction. If A is a reference type, the type
// referred to by A is used for type deduction.
A = A.getUnqualifiedType();
}
@@ -3842,8 +3845,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
Specialization = cast_or_null<CXXConversionDecl>(ConversionSpecialized);
// If the conversion operator is being invoked on a lambda closure to convert
- // to a ptr-to-function, use the deduced arguments from the conversion function
- // to specialize the corresponding call operator.
+ // to a ptr-to-function, use the deduced arguments from the conversion
+ // function to specialize the corresponding call operator.
// e.g., int (*fp)(int) = [](auto a) { return a; };
if (Result == TDK_Success && isLambdaConversionOperator(ConversionGeneric)) {
@@ -3907,9 +3910,10 @@ namespace {
public TreeTransform<SubstituteAutoTransform> {
QualType Replacement;
public:
- SubstituteAutoTransform(Sema &SemaRef, QualType Replacement) :
- TreeTransform<SubstituteAutoTransform>(SemaRef), Replacement(Replacement) {
- }
+ SubstituteAutoTransform(Sema &SemaRef, QualType Replacement)
+ : TreeTransform<SubstituteAutoTransform>(SemaRef),
+ Replacement(Replacement) {}
+
QualType TransformAutoType(TypeLocBuilder &TLB, AutoTypeLoc TL) {
// If we're building the type pattern to deduce against, don't wrap the
// substituted type in an AutoType. Certain template deduction rules
@@ -3988,7 +3992,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
return DAR_FailedAlreadyDiagnosed;
}
- QualType Deduced = BuildDecltypeType(Init, Init->getLocStart());
+ QualType Deduced = BuildDecltypeType(Init, Init->getLocStart(), false);
// FIXME: Support a non-canonical deduced type for 'auto'.
Deduced = Context.getCanonicalType(Deduced);
Result = SubstituteAutoTransform(*this, Deduced).Apply(Type);
@@ -4885,8 +4889,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
Depth, Used);
// C++0x [temp.deduct.type]p9:
- // If the template argument list of P contains a pack expansion that is not
- // the last template argument, the entire template argument list is a
+ // If the template argument list of P contains a pack expansion that is
+ // not the last template argument, the entire template argument list is a
// non-deduced context.
if (OnlyDeduced &&
hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs()))
@@ -5069,10 +5073,9 @@ Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
/// \brief Marks all of the template parameters that will be deduced by a
/// call to the given function template.
-void
-Sema::MarkDeducedTemplateParameters(ASTContext &Ctx,
- const FunctionTemplateDecl *FunctionTemplate,
- llvm::SmallBitVector &Deduced) {
+void Sema::MarkDeducedTemplateParameters(
+ ASTContext &Ctx, const FunctionTemplateDecl *FunctionTemplate,
+ llvm::SmallBitVector &Deduced) {
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
Deduced.clear();
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 14c64050168a..6ac7175cf30f 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -448,6 +448,10 @@ void Sema::PrintInstantiationStack() {
diag::note_template_enum_def_here)
<< ED
<< Active->InstantiationRange;
+ } else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_template_nsdmi_here)
+ << FD << Active->InstantiationRange;
} else {
Diags.Report(Active->PointOfInstantiation,
diag::note_template_type_alias_instantiation_here)
@@ -767,6 +771,8 @@ namespace {
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = nullptr);
+ const LoopHintAttr *TransformLoopHintAttr(const LoopHintAttr *LH);
+
ExprResult TransformPredefinedExpr(PredefinedExpr *E);
ExprResult TransformDeclRefExpr(DeclRefExpr *E);
ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
@@ -789,11 +795,17 @@ namespace {
ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
- FunctionProtoTypeLoc TL);
+ FunctionProtoTypeLoc TL) {
+ // Call the base version; it will forward to our overridden version below.
+ return inherited::TransformFunctionProtoType(TLB, TL);
+ }
+
+ template<typename Fn>
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
CXXRecordDecl *ThisContext,
- unsigned ThisTypeQuals);
+ unsigned ThisTypeQuals,
+ Fn TransformExceptionSpec);
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
@@ -1023,7 +1035,7 @@ TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS,
TemplateName Name,
- SourceLocation NameLoc,
+ SourceLocation NameLoc,
QualType ObjectType,
NamedDecl *FirstQualifierInScope) {
if (TemplateTemplateParmDecl *TTP
@@ -1127,6 +1139,24 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
return transformNonTypeTemplateParmRef(NTTP, E->getLocation(), Arg);
}
+const LoopHintAttr *
+TemplateInstantiator::TransformLoopHintAttr(const LoopHintAttr *LH) {
+ Expr *TransformedExpr = getDerived().TransformExpr(LH->getValue()).get();
+
+ if (TransformedExpr == LH->getValue())
+ return LH;
+
+ // Generate error if there is a problem with the value.
+ if (getSema().CheckLoopHintExpr(TransformedExpr, LH->getLocation()))
+ return LH;
+
+ // Create new LoopHintValueAttr with integral expression in place of the
+ // non-type template parameter.
+ return LoopHintAttr::CreateImplicit(
+ getSema().Context, LH->getSemanticSpelling(), LH->getOption(),
+ LH->getState(), TransformedExpr, LH->getRange());
+}
+
ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
NonTypeTemplateParmDecl *parm,
SourceLocation loc,
@@ -1255,8 +1285,8 @@ TemplateInstantiator::TransformFunctionParmPackRefExpr(DeclRefExpr *E,
Decl *TransformedDecl;
if (DeclArgumentPack *Pack = Found->dyn_cast<DeclArgumentPack *>()) {
- // If this is a reference to a function parameter pack which we can substitute
- // but can't yet expand, build a FunctionParmPackExpr for it.
+ // If this is a reference to a function parameter pack which we can
+ // substitute but can't yet expand, build a FunctionParmPackExpr for it.
if (getSema().ArgumentPackSubstitutionIndex == -1) {
QualType T = TransformType(E->getType());
if (T.isNull())
@@ -1307,21 +1337,16 @@ ExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
E->getParam());
}
-QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
- FunctionProtoTypeLoc TL) {
- // We need a local instantiation scope for this function prototype.
- LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
- return inherited::TransformFunctionProtoType(TLB, TL);
-}
-
+template<typename Fn>
QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
CXXRecordDecl *ThisContext,
- unsigned ThisTypeQuals) {
+ unsigned ThisTypeQuals,
+ Fn TransformExceptionSpec) {
// We need a local instantiation scope for this function prototype.
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
- return inherited::TransformFunctionProtoType(TLB, TL, ThisContext,
- ThisTypeQuals);
+ return inherited::TransformFunctionProtoType(
+ TLB, TL, ThisContext, ThisTypeQuals, TransformExceptionSpec);
}
ParmVarDecl *
@@ -1556,7 +1581,8 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
/// A form of SubstType intended specifically for instantiating the
/// type of a FunctionDecl. Its purpose is solely to force the
-/// instantiation of default-argument expressions.
+/// instantiation of default-argument expressions and to avoid
+/// instantiating an exception-specification.
TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
const MultiLevelTemplateArgumentList &Args,
SourceLocation Loc,
@@ -1579,9 +1605,17 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
QualType Result;
- if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {
- Result = Instantiator.TransformFunctionProtoType(TLB, Proto, ThisContext,
- ThisTypeQuals);
+ if (FunctionProtoTypeLoc Proto =
+ TL.IgnoreParens().getAs<FunctionProtoTypeLoc>()) {
+ // Instantiate the type, other than its exception specification. The
+ // exception specification is instantiated in InitFunctionInstantiation
+ // once we've built the FunctionDecl.
+ // FIXME: Set the exception specification to EST_Uninstantiated here,
+ // instead of rebuilding the function type again later.
+ Result = Instantiator.TransformFunctionProtoType(
+ TLB, Proto, ThisContext, ThisTypeQuals,
+ [](FunctionProtoType::ExceptionSpecInfo &ESI,
+ bool &Changed) { return false; });
} else {
Result = Instantiator.TransformType(TLB, TL);
}
@@ -1591,6 +1625,26 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
return TLB.getTypeSourceInfo(Context, Result);
}
+void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
+ const MultiLevelTemplateArgumentList &Args) {
+ FunctionProtoType::ExceptionSpecInfo ESI =
+ Proto->getExtProtoInfo().ExceptionSpec;
+ assert(ESI.Type != EST_Uninstantiated);
+
+ TemplateInstantiator Instantiator(*this, Args, New->getLocation(),
+ New->getDeclName());
+
+ SmallVector<QualType, 4> ExceptionStorage;
+ bool Changed = false;
+ if (Instantiator.TransformExceptionSpec(
+ New->getTypeSourceInfo()->getTypeLoc().getLocEnd(), ESI,
+ ExceptionStorage, Changed))
+ // On error, recover by dropping the exception specification.
+ ESI.Type = EST_None;
+
+ UpdateExceptionSpec(New, ESI);
+}
+
ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
const MultiLevelTemplateArgumentList &TemplateArgs,
int indexAdjustment,
@@ -1947,8 +2001,6 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
SmallVector<Decl*, 4> Fields;
- SmallVector<std::pair<FieldDecl*, FieldDecl*>, 4>
- FieldsWithMemberInitializers;
// Delay instantiation of late parsed attributes.
LateInstantiatedAttrVec LateAttrs;
Instantiator.enableLateAttributeInstantiation(&LateAttrs);
@@ -1975,10 +2027,6 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
if (NewMember) {
if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) {
Fields.push_back(Field);
- FieldDecl *OldField = cast<FieldDecl>(Member);
- if (OldField->getInClassInitializer())
- FieldsWithMemberInitializers.push_back(std::make_pair(OldField,
- Field));
} else if (EnumDecl *Enum = dyn_cast<EnumDecl>(NewMember)) {
// C++11 [temp.inst]p1: The implicit instantiation of a class template
// specialization causes the implicit instantiation of the definitions
@@ -2015,31 +2063,6 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
SourceLocation(), SourceLocation(), nullptr);
CheckCompletedCXXClass(Instantiation);
- // Attach any in-class member initializers now the class is complete.
- // FIXME: We are supposed to defer instantiating these until they are needed.
- if (!FieldsWithMemberInitializers.empty()) {
- // C++11 [expr.prim.general]p4:
- // Otherwise, if a member-declarator declares a non-static data member
- // (9.2) of a class X, the expression this is a prvalue of type "pointer
- // to X" within the optional brace-or-equal-initializer. It shall not
- // appear elsewhere in the member-declarator.
- CXXThisScopeRAII ThisScope(*this, Instantiation, (unsigned)0);
-
- for (unsigned I = 0, N = FieldsWithMemberInitializers.size(); I != N; ++I) {
- FieldDecl *OldField = FieldsWithMemberInitializers[I].first;
- FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
- Expr *OldInit = OldField->getInClassInitializer();
-
- ActOnStartCXXInClassMemberInitializer();
- ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
- /*CXXDirectInit=*/false);
- Expr *Init = NewInit.get();
- assert((!Init || !isa<ParenListExpr>(Init)) &&
- "call-style init in class");
- ActOnFinishCXXInClassMemberInitializer(NewField,
- Init ? Init->getLocStart() : SourceLocation(), Init);
- }
- }
// Instantiate late parsed attributes, and attach them to their decls.
// See Sema::InstantiateAttrs
for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
@@ -2180,6 +2203,80 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
return Instantiation->isInvalidDecl();
}
+
+/// \brief Instantiate the definition of a field from the given pattern.
+///
+/// \param PointOfInstantiation The point of instantiation within the
+/// source code.
+/// \param Instantiation is the declaration whose definition is being
+/// instantiated. This will be a class of a class temploid
+/// specialization, or a local enumeration within a function temploid
+/// specialization.
+/// \param Pattern The templated declaration from which the instantiation
+/// occurs.
+/// \param TemplateArgs The template arguments to be substituted into
+/// the pattern.
+///
+/// \return \c true if an error occurred, \c false otherwise.
+bool Sema::InstantiateInClassInitializer(
+ SourceLocation PointOfInstantiation, FieldDecl *Instantiation,
+ FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs) {
+ // If there is no initializer, we don't need to do anything.
+ if (!Pattern->hasInClassInitializer())
+ return false;
+
+ assert(Instantiation->getInClassInitStyle() ==
+ Pattern->getInClassInitStyle() &&
+ "pattern and instantiation disagree about init style");
+
+ // Error out if we haven't parsed the initializer of the pattern yet because
+ // we are waiting for the closing brace of the outer class.
+ Expr *OldInit = Pattern->getInClassInitializer();
+ if (!OldInit) {
+ RecordDecl *PatternRD = Pattern->getParent();
+ RecordDecl *OutermostClass = PatternRD->getOuterLexicalRecordContext();
+ if (OutermostClass == PatternRD) {
+ Diag(Pattern->getLocEnd(), diag::err_in_class_initializer_not_yet_parsed)
+ << PatternRD << Pattern;
+ } else {
+ Diag(Pattern->getLocEnd(),
+ diag::err_in_class_initializer_not_yet_parsed_outer_class)
+ << PatternRD << OutermostClass << Pattern;
+ }
+ Instantiation->setInvalidDecl();
+ return true;
+ }
+
+ InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
+ if (Inst.isInvalid())
+ return true;
+
+ // Enter the scope of this instantiation. We don't use PushDeclContext because
+ // we don't have a scope.
+ ContextRAII SavedContext(*this, Instantiation->getParent());
+ EnterExpressionEvaluationContext EvalContext(*this,
+ Sema::PotentiallyEvaluated);
+
+ LocalInstantiationScope Scope(*this);
+
+ // Instantiate the initializer.
+ ActOnStartCXXInClassMemberInitializer();
+ CXXThisScopeRAII ThisScope(*this, Instantiation->getParent(), /*TypeQuals=*/0);
+
+ ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
+ /*CXXDirectInit=*/false);
+ Expr *Init = NewInit.get();
+ assert((!Init || !isa<ParenListExpr>(Init)) && "call-style init in class");
+ ActOnFinishCXXInClassMemberInitializer(
+ Instantiation, Init ? Init->getLocStart() : SourceLocation(), Init);
+
+ // Exit the scope of this instantiation.
+ SavedContext.pop();
+
+ // Return true if the in-class initializer is still missing.
+ return !Instantiation->getInClassInitializer();
+}
+
namespace {
/// \brief A partial specialization whose template arguments have matched
/// a given template-id.
@@ -2458,7 +2555,10 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
// 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.
- if (Record->isInjectedClassName() || Record->getPreviousDecl())
+ // Skip closure types; they'll get instantiated when we instantiate
+ // the corresponding lambda-expression.
+ if (Record->isInjectedClassName() || Record->getPreviousDecl() ||
+ Record->isLambda())
continue;
MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo();
@@ -2541,6 +2641,19 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
MSInfo->setTemplateSpecializationKind(TSK);
MSInfo->setPointOfInstantiation(PointOfInstantiation);
}
+ } else if (auto *Field = dyn_cast<FieldDecl>(D)) {
+ // No need to instantiate in-class initializers during explicit
+ // instantiation.
+ if (Field->hasInClassInitializer() && TSK == TSK_ImplicitInstantiation) {
+ CXXRecordDecl *ClassPattern =
+ Instantiation->getTemplateInstantiationPattern();
+ DeclContext::lookup_result Lookup =
+ ClassPattern->lookup(Field->getDeclName());
+ assert(Lookup.size() == 1);
+ FieldDecl *Pattern = cast<FieldDecl>(Lookup[0]);
+ InstantiateInClassInitializer(PointOfInstantiation, Field, Pattern,
+ TemplateArgs);
+ }
}
}
}
@@ -2649,8 +2762,7 @@ bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
return Instantiator.TransformTemplateArguments(Args, NumArgs, Result);
}
-
-static const Decl* getCanonicalParmVarDecl(const Decl *D) {
+static const Decl *getCanonicalParmVarDecl(const Decl *D) {
// When storing ParmVarDecls in the local instantiation scope, we always
// want to use the ParmVarDecl from the canonical function declaration,
// since the map is then valid for any redeclaration or definition of that
@@ -2658,7 +2770,10 @@ static const Decl* getCanonicalParmVarDecl(const Decl *D) {
if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(D)) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
unsigned i = PV->getFunctionScopeIndex();
- return FD->getCanonicalDecl()->getParamDecl(i);
+ // This parameter might be from a freestanding function type within the
+ // function and isn't necessarily referring to one of FD's parameters.
+ if (FD->getParamDecl(i) == PV)
+ return FD->getCanonicalDecl()->getParamDecl(i);
}
}
return D;
@@ -2707,12 +2822,22 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
D = getCanonicalParmVarDecl(D);
llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
- if (Stored.isNull())
+ if (Stored.isNull()) {
+#ifndef NDEBUG
+ // It should not be present in any surrounding scope either.
+ LocalInstantiationScope *Current = this;
+ while (Current->CombineWithOuterScope && Current->Outer) {
+ Current = Current->Outer;
+ assert(Current->LocalDecls.find(D) == Current->LocalDecls.end() &&
+ "Instantiated local in inner and outer scopes");
+ }
+#endif
Stored = Inst;
- else if (DeclArgumentPack *Pack = Stored.dyn_cast<DeclArgumentPack *>())
+ } else if (DeclArgumentPack *Pack = Stored.dyn_cast<DeclArgumentPack *>()) {
Pack->push_back(Inst);
- else
+ } else {
assert(Stored.get<Decl *>() == Inst && "Already instantiated this local");
+ }
}
void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
@@ -2723,9 +2848,16 @@ void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
}
void LocalInstantiationScope::MakeInstantiatedLocalArgPack(const Decl *D) {
+#ifndef NDEBUG
+ // This should be the first time we've been told about this decl.
+ for (LocalInstantiationScope *Current = this;
+ Current && Current->CombineWithOuterScope; Current = Current->Outer)
+ assert(Current->LocalDecls.find(D) == Current->LocalDecls.end() &&
+ "Creating local pack after instantiation of local");
+#endif
+
D = getCanonicalParmVarDecl(D);
llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
- assert(Stored.isNull() && "Already instantiated this local");
DeclArgumentPack *Pack = new DeclArgumentPack;
Stored = Pack;
ArgumentPacks.push_back(Pack);
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index accec95bf708..40e86175b2cd 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -36,14 +36,24 @@ static bool isDeclWithinFunction(const Decl *D) {
return false;
}
-bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl,
- DeclaratorDecl *NewDecl) {
+template<typename DeclT>
+static bool SubstQualifier(Sema &SemaRef, const DeclT *OldDecl, DeclT *NewDecl,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!OldDecl->getQualifierLoc())
return false;
+ assert((NewDecl->getFriendObjectKind() ||
+ !OldDecl->getLexicalDeclContext()->isDependentContext()) &&
+ "non-friend with qualified name defined in dependent context");
+ Sema::ContextRAII SavedContext(
+ SemaRef,
+ const_cast<DeclContext *>(NewDecl->getFriendObjectKind()
+ ? NewDecl->getLexicalDeclContext()
+ : OldDecl->getLexicalDeclContext()));
+
NestedNameSpecifierLoc NewQualifierLoc
- = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(),
- TemplateArgs);
+ = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(),
+ TemplateArgs);
if (!NewQualifierLoc)
return true;
@@ -52,20 +62,14 @@ bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl,
return false;
}
+bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl,
+ DeclaratorDecl *NewDecl) {
+ return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs);
+}
+
bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
TagDecl *NewDecl) {
- if (!OldDecl->getQualifierLoc())
- return false;
-
- NestedNameSpecifierLoc NewQualifierLoc
- = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(),
- TemplateArgs);
-
- if (!NewQualifierLoc)
- return true;
-
- NewDecl->setQualifierInfo(NewQualifierLoc);
- return false;
+ return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs);
}
// Include attribute instantiation code.
@@ -129,6 +133,40 @@ static void instantiateDependentAlignedAttr(
}
}
+static void instantiateDependentAssumeAlignedAttr(
+ Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
+ const AssumeAlignedAttr *Aligned, Decl *New) {
+ // The alignment expression is a constant expression.
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ConstantEvaluated);
+
+ Expr *E, *OE = nullptr;
+ ExprResult Result = S.SubstExpr(Aligned->getAlignment(), TemplateArgs);
+ if (Result.isInvalid())
+ return;
+ E = Result.getAs<Expr>();
+
+ if (Aligned->getOffset()) {
+ Result = S.SubstExpr(Aligned->getOffset(), TemplateArgs);
+ if (Result.isInvalid())
+ return;
+ OE = Result.getAs<Expr>();
+ }
+
+ S.AddAssumeAlignedAttr(Aligned->getLocation(), New, E, OE,
+ Aligned->getSpellingListIndex());
+}
+
+static void instantiateDependentAlignValueAttr(
+ Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
+ const AlignValueAttr *Aligned, Decl *New) {
+ // The alignment expression is a constant expression.
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ConstantEvaluated);
+ ExprResult Result = S.SubstExpr(Aligned->getAlignment(), TemplateArgs);
+ if (!Result.isInvalid())
+ S.AddAlignValueAttr(Aligned->getLocation(), New, Result.getAs<Expr>(),
+ Aligned->getSpellingListIndex());
+}
+
static void instantiateDependentEnableIfAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const EnableIfAttr *A, const Decl *Tmpl, Decl *New) {
@@ -176,6 +214,18 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
continue;
}
+ const AssumeAlignedAttr *AssumeAligned = dyn_cast<AssumeAlignedAttr>(TmplAttr);
+ if (AssumeAligned) {
+ instantiateDependentAssumeAlignedAttr(*this, TemplateArgs, AssumeAligned, New);
+ continue;
+ }
+
+ const AlignValueAttr *AlignValue = dyn_cast<AlignValueAttr>(TmplAttr);
+ if (AlignValue) {
+ instantiateDependentAlignValueAttr(*this, TemplateArgs, AlignValue, New);
+ continue;
+ }
+
const EnableIfAttr *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr);
if (EnableIf && EnableIf->getCond()->isValueDependent()) {
instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl,
@@ -183,6 +233,14 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
continue;
}
+ // Existing DLL attribute on the instantiation takes precedence.
+ if (TmplAttr->getKind() == attr::DLLExport ||
+ TmplAttr->getKind() == attr::DLLImport) {
+ if (New->hasAttr<DLLExportAttr>() || New->hasAttr<DLLImportAttr>()) {
+ continue;
+ }
+ }
+
assert(!TmplAttr->isPackExpansion());
if (TmplAttr->isLateParsed() && LateAttrs) {
// Late parsed attributes must be instantiated and attached after the
@@ -207,6 +265,24 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
}
}
+/// Get the previous declaration of a declaration for the purposes of template
+/// instantiation. If this finds a previous declaration, then the previous
+/// declaration of the instantiation of D should be an instantiation of the
+/// result of this function.
+template<typename DeclT>
+static DeclT *getPreviousDeclForInstantiation(DeclT *D) {
+ DeclT *Result = D->getPreviousDecl();
+
+ // If the declaration is within a class, and the previous declaration was
+ // merged from a different definition of that class, then we don't have a
+ // previous declaration for the purpose of template instantiation.
+ if (Result && isa<CXXRecordDecl>(D->getDeclContext()) &&
+ D->getLexicalDeclContext() != Result->getLexicalDeclContext())
+ return nullptr;
+
+ return Result;
+}
+
Decl *
TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
llvm_unreachable("Translation units cannot be instantiated");
@@ -293,7 +369,7 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
}
}
- if (TypedefNameDecl *Prev = D->getPreviousDecl()) {
+ if (TypedefNameDecl *Prev = getPreviousDeclForInstantiation(D)) {
NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev,
TemplateArgs);
if (!InstPrev)
@@ -316,13 +392,15 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/false);
- Owner->addDecl(Typedef);
+ if (Typedef)
+ Owner->addDecl(Typedef);
return Typedef;
}
Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) {
Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/true);
- Owner->addDecl(Typedef);
+ if (Typedef)
+ Owner->addDecl(Typedef);
return Typedef;
}
@@ -340,7 +418,7 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
TypeAliasDecl *Pattern = D->getTemplatedDecl();
TypeAliasTemplateDecl *PrevAliasTemplate = nullptr;
- if (Pattern->getPreviousDecl()) {
+ if (getPreviousDeclForInstantiation<TypedefNameDecl>(Pattern)) {
DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
if (!Found.empty()) {
PrevAliasTemplate = dyn_cast<TypeAliasTemplateDecl>(Found.front());
@@ -355,6 +433,7 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
TypeAliasTemplateDecl *Inst
= TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(),
D->getDeclName(), InstParams, AliasInst);
+ AliasInst->setDescribedAliasTemplate(Inst);
if (PrevAliasTemplate)
Inst->setPreviousDecl(PrevAliasTemplate);
@@ -578,11 +657,12 @@ Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
}
QualType T = cast<FieldDecl>(NamedChain[i-1])->getType();
- IndirectFieldDecl* IndirectField
- = IndirectFieldDecl::Create(SemaRef.Context, Owner, D->getLocation(),
- D->getIdentifier(), T,
- NamedChain, D->getChainingSize());
+ IndirectFieldDecl *IndirectField = IndirectFieldDecl::Create(
+ SemaRef.Context, Owner, D->getLocation(), D->getIdentifier(), T,
+ NamedChain, D->getChainingSize());
+ for (const auto *Attr : D->attrs())
+ IndirectField->addAttr(Attr->clone(SemaRef.Context));
IndirectField->setImplicit(D->isImplicit());
IndirectField->setAccess(D->getAccess());
@@ -659,9 +739,9 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
EnumDecl *PrevDecl = nullptr;
- if (D->getPreviousDecl()) {
+ if (EnumDecl *PatternPrev = getPreviousDeclForInstantiation(D)) {
NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(),
- D->getPreviousDecl(),
+ PatternPrev,
TemplateArgs);
if (!Prev) return nullptr;
PrevDecl = cast<EnumDecl>(Prev);
@@ -823,7 +903,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
CXXRecordDecl *PrevDecl = nullptr;
ClassTemplateDecl *PrevClassTemplate = nullptr;
- if (!isFriend && Pattern->getPreviousDecl()) {
+ if (!isFriend && getPreviousDeclForInstantiation(Pattern)) {
DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
if (!Found.empty()) {
PrevClassTemplate = dyn_cast<ClassTemplateDecl>(Found.front());
@@ -1017,7 +1097,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) {
VarDecl *Pattern = D->getTemplatedDecl();
VarTemplateDecl *PrevVarTemplate = nullptr;
- if (Pattern->getPreviousDecl()) {
+ if (getPreviousDeclForInstantiation(Pattern)) {
DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
if (!Found.empty())
PrevVarTemplate = dyn_cast<VarTemplateDecl>(Found.front());
@@ -1127,7 +1207,7 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
if (!isFriend) {
Owner->addDecl(InstTemplate);
} else if (InstTemplate->getDeclContext()->isRecord() &&
- !D->getPreviousDecl()) {
+ !getPreviousDeclForInstantiation(D)) {
SemaRef.CheckFriendAccess(InstTemplate);
}
@@ -1138,9 +1218,9 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
CXXRecordDecl *PrevDecl = nullptr;
if (D->isInjectedClassName())
PrevDecl = cast<CXXRecordDecl>(Owner);
- else if (D->getPreviousDecl()) {
+ else if (CXXRecordDecl *PatternPrev = getPreviousDeclForInstantiation(D)) {
NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(),
- D->getPreviousDecl(),
+ PatternPrev,
TemplateArgs);
if (!Prev) return nullptr;
PrevDecl = cast<CXXRecordDecl>(Prev);
@@ -1191,6 +1271,9 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
SemaRef.InstantiateClassMembers(D->getLocation(), Record, TemplateArgs,
TSK_ImplicitInstantiation);
}
+
+ SemaRef.DiagnoseUnusedNestedTypedefs(Record);
+
return Record;
}
@@ -2201,7 +2284,8 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
if (CheckRedeclaration) {
if (SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev, PrevDecl))
continue;
- } else if (UsingShadowDecl *OldPrev = Shadow->getPreviousDecl()) {
+ } else if (UsingShadowDecl *OldPrev =
+ getPreviousDeclForInstantiation(Shadow)) {
PrevDecl = cast_or_null<UsingShadowDecl>(SemaRef.FindInstantiatedDecl(
Shadow->getLocation(), OldPrev, TemplateArgs));
}
@@ -2276,8 +2360,10 @@ Decl * TemplateDeclInstantiator
Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
ClassScopeFunctionSpecializationDecl *Decl) {
CXXMethodDecl *OldFD = Decl->getSpecialization();
- CXXMethodDecl *NewFD = cast<CXXMethodDecl>(VisitCXXMethodDecl(OldFD,
- nullptr, true));
+ CXXMethodDecl *NewFD =
+ cast_or_null<CXXMethodDecl>(VisitCXXMethodDecl(OldFD, nullptr, true));
+ if (!NewFD)
+ return nullptr;
LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName,
Sema::ForRedeclaration);
@@ -2976,7 +3062,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
/// Introduce the instantiated function parameters into the local
/// instantiation scope, and set the parameter names to those used
/// in the template.
-static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
+static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
const FunctionDecl *PatternDecl,
LocalInstantiationScope &Scope,
const MultiLevelTemplateArgumentList &TemplateArgs) {
@@ -2987,15 +3073,22 @@ static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
// Simple case: not a parameter pack.
assert(FParamIdx < Function->getNumParams());
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+ FunctionParam->setDeclName(PatternParam->getDeclName());
// 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.
+ // per core issue 1668. Substitute into the type from the pattern, in case
+ // it's instantiation-dependent.
// FIXME: Updating the type to work around this is at best fragile.
- if (!PatternDecl->getType()->isDependentType())
- FunctionParam->setType(PatternParam->getType());
+ if (!PatternDecl->getType()->isDependentType()) {
+ QualType T = S.SubstType(PatternParam->getType(), TemplateArgs,
+ FunctionParam->getLocation(),
+ FunctionParam->getDeclName());
+ if (T.isNull())
+ return true;
+ FunctionParam->setType(T);
+ }
- FunctionParam->setDeclName(PatternParam->getDeclName());
Scope.InstantiatedLocal(PatternParam, FunctionParam);
++FParamIdx;
continue;
@@ -3007,137 +3100,27 @@ static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
= S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
assert(NumArgumentsInExpansion &&
"should only be called when all template arguments are known");
+ QualType PatternType =
+ PatternParam->getType()->castAs<PackExpansionType>()->getPattern();
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;
- }
- }
-}
-
-static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
- const FunctionProtoType *Proto,
- const MultiLevelTemplateArgumentList &TemplateArgs) {
- assert(Proto->getExceptionSpecType() != EST_Uninstantiated);
-
- // C++11 [expr.prim.general]p3:
- // If a declaration declares a member function or member function
- // template of a class X, the expression this is a prvalue of type
- // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
- // and the end of the function-definition, member-declarator, or
- // declarator.
- CXXRecordDecl *ThisContext = nullptr;
- unsigned ThisTypeQuals = 0;
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(New)) {
- ThisContext = Method->getParent();
- ThisTypeQuals = Method->getTypeQualifiers();
- }
- Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals,
- SemaRef.getLangOpts().CPlusPlus11);
-
- // The function has an exception specification or a "noreturn"
- // attribute. Substitute into each of the exception types.
- SmallVector<QualType, 4> Exceptions;
- for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
- // FIXME: Poor location information!
- if (const PackExpansionType *PackExpansion
- = Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
- // We have a pack expansion. Instantiate it.
- SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
- Unexpanded);
- assert(!Unexpanded.empty() &&
- "Pack expansion without parameter packs?");
-
- bool Expand = false;
- bool RetainExpansion = false;
- Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions();
- if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
- SourceRange(),
- Unexpanded,
- TemplateArgs,
- Expand,
- RetainExpansion,
- NumExpansions))
- break;
-
- if (!Expand) {
- // We can't expand this pack expansion into separate arguments yet;
- // just substitute into the pattern and create a new pack expansion
- // type.
- Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
- QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
- TemplateArgs,
- New->getLocation(), New->getDeclName());
+ if (!PatternDecl->getType()->isDependentType()) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg);
+ QualType T = S.SubstType(PatternType, TemplateArgs,
+ FunctionParam->getLocation(),
+ FunctionParam->getDeclName());
if (T.isNull())
- break;
-
- T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
- Exceptions.push_back(T);
- continue;
- }
-
- // Substitute into the pack expansion pattern for each template
- bool Invalid = false;
- for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
- Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
-
- QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
- TemplateArgs,
- New->getLocation(), New->getDeclName());
- if (T.isNull()) {
- Invalid = true;
- break;
- }
-
- Exceptions.push_back(T);
+ return true;
+ FunctionParam->setType(T);
}
- if (Invalid)
- break;
-
- continue;
- }
-
- QualType T
- = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
- New->getLocation(), New->getDeclName());
- if (T.isNull() ||
- SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))
- continue;
-
- Exceptions.push_back(T);
- }
- Expr *NoexceptExpr = nullptr;
- if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
- EnterExpressionEvaluationContext Unevaluated(SemaRef,
- Sema::ConstantEvaluated);
- ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);
- if (E.isUsable())
- E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart());
-
- if (E.isUsable()) {
- NoexceptExpr = E.get();
- if (!NoexceptExpr->isTypeDependent() &&
- !NoexceptExpr->isValueDependent())
- NoexceptExpr
- = SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
- nullptr, diag::err_noexcept_needs_constant_expression,
- /*AllowFold*/ false).get();
+ Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
+ ++FParamIdx;
}
}
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExceptionSpecType = Proto->getExceptionSpecType();
- EPI.NumExceptions = Exceptions.size();
- EPI.Exceptions = Exceptions.data();
- EPI.NoexceptExpr = NoexceptExpr;
-
- SemaRef.UpdateExceptionSpec(New, EPI);
+ return false;
}
void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
@@ -3151,9 +3134,7 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
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;
- EPI.ExceptionSpecType = EST_None;
- UpdateExceptionSpec(Decl, EPI);
+ UpdateExceptionSpec(Decl, EST_None);
return;
}
@@ -3166,11 +3147,14 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true);
FunctionDecl *Template = Proto->getExceptionSpecTemplate();
- addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs);
+ if (addInstantiatedParametersToScope(*this, Decl, Template, Scope,
+ TemplateArgs)) {
+ UpdateExceptionSpec(Decl, EST_None);
+ return;
+ }
- ::InstantiateExceptionSpec(*this, Decl,
- Template->getType()->castAs<FunctionProtoType>(),
- TemplateArgs);
+ SubstExceptionSpec(Decl, Template->getType()->castAs<FunctionProtoType>(),
+ TemplateArgs);
}
/// \brief Initializes the common fields of an instantiation function
@@ -3218,14 +3202,14 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
// DR1330: In C++11, defer instantiation of a non-trivial
// exception specification.
if (SemaRef.getLangOpts().CPlusPlus11 &&
- EPI.ExceptionSpecType != EST_None &&
- EPI.ExceptionSpecType != EST_DynamicNone &&
- EPI.ExceptionSpecType != EST_BasicNoexcept) {
+ EPI.ExceptionSpec.Type != EST_None &&
+ EPI.ExceptionSpec.Type != EST_DynamicNone &&
+ EPI.ExceptionSpec.Type != EST_BasicNoexcept) {
FunctionDecl *ExceptionSpecTemplate = Tmpl;
- if (EPI.ExceptionSpecType == EST_Uninstantiated)
- ExceptionSpecTemplate = EPI.ExceptionSpecTemplate;
+ if (EPI.ExceptionSpec.Type == EST_Uninstantiated)
+ ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate;
ExceptionSpecificationType NewEST = EST_Uninstantiated;
- if (EPI.ExceptionSpecType == EST_Unevaluated)
+ if (EPI.ExceptionSpec.Type == EST_Unevaluated)
NewEST = EST_Unevaluated;
// Mark the function has having an uninstantiated exception specification.
@@ -3233,13 +3217,13 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
= New->getType()->getAs<FunctionProtoType>();
assert(NewProto && "Template instantiation without function prototype?");
EPI = NewProto->getExtProtoInfo();
- EPI.ExceptionSpecType = NewEST;
- EPI.ExceptionSpecDecl = New;
- EPI.ExceptionSpecTemplate = ExceptionSpecTemplate;
+ EPI.ExceptionSpec.Type = NewEST;
+ EPI.ExceptionSpec.SourceDecl = New;
+ EPI.ExceptionSpec.SourceTemplate = ExceptionSpecTemplate;
New->setType(SemaRef.Context.getFunctionType(
NewProto->getReturnType(), NewProto->getParamTypes(), EPI));
} else {
- ::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs);
+ SemaRef.SubstExceptionSpec(New, Proto, TemplateArgs);
}
}
@@ -3322,6 +3306,20 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
return;
}
+ // If we're performing recursive template instantiation, create our own
+ // queue of pending implicit instantiations that we will instantiate later,
+ // while we're still within our own instantiation context.
+ // This has to happen before LateTemplateParser below is called, so that
+ // it marks vtables used in late parsed templates as used.
+ SavePendingLocalImplicitInstantiationsRAII
+ SavedPendingLocalImplicitInstantiations(*this);
+ std::unique_ptr<SavePendingInstantiationsAndVTableUsesRAII>
+ SavePendingInstantiationsAndVTableUses;
+ if (Recursive) {
+ SavePendingInstantiationsAndVTableUses.reset(
+ new SavePendingInstantiationsAndVTableUsesRAII(*this));
+ }
+
// Call the LateTemplateParser callback if there is a need to late parse
// a templated function definition.
if (!Pattern && PatternDecl->isLateTemplateParsed() &&
@@ -3353,6 +3351,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
Function->setInvalidDecl();
} else if (Function->getTemplateSpecializationKind()
== TSK_ExplicitInstantiationDefinition) {
+ assert(!Recursive);
PendingInstantiations.push_back(
std::make_pair(Function, PointOfInstantiation));
}
@@ -3389,18 +3388,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// Copy the inner loc start from the pattern.
Function->setInnerLocStart(PatternDecl->getInnerLocStart());
- // If we're performing recursive template instantiation, create our own
- // queue of pending implicit instantiations that we will instantiate later,
- // while we're still within our own instantiation context.
- SmallVector<VTableUse, 16> SavedVTableUses;
- std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
- SavePendingLocalImplicitInstantiationsRAII
- SavedPendingLocalImplicitInstantiations(*this);
- if (Recursive) {
- VTableUses.swap(SavedVTableUses);
- PendingInstantiations.swap(SavedPendingInstantiations);
- }
-
EnterExpressionEvaluationContext EvalContext(*this,
Sema::PotentiallyEvaluated);
@@ -3417,17 +3404,24 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (PatternDecl->isDefaulted())
SetDeclDefaulted(Function, PatternDecl->getLocation());
else {
+ MultiLevelTemplateArgumentList TemplateArgs =
+ getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl);
+
+ // Substitute into the qualifier; we can get a substitution failure here
+ // through evil use of alias templates.
+ // FIXME: Is CurContext correct for this? Should we go to the (instantiation
+ // of the) lexical context of the pattern?
+ SubstQualifier(*this, PatternDecl, Function, TemplateArgs);
+
ActOnStartOfFunctionDef(nullptr, Function);
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
Sema::ContextRAII savedContext(*this, Function);
- MultiLevelTemplateArgumentList TemplateArgs =
- getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl);
-
- addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
- TemplateArgs);
+ if (addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
+ TemplateArgs))
+ return;
// If this is a constructor, instantiate the member initializers.
if (const CXXConstructorDecl *Ctor =
@@ -3469,15 +3463,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// instantiation of this template.
PerformPendingInstantiations();
- // Restore the set of pending vtables.
- assert(VTableUses.empty() &&
- "VTableUses should be empty before it is discarded.");
- VTableUses.swap(SavedVTableUses);
-
- // Restore the set of pending implicit instantiations.
- assert(PendingInstantiations.empty() &&
- "PendingInstantiations should be empty before it is discarded.");
- PendingInstantiations.swap(SavedPendingInstantiations);
+ // Restore PendingInstantiations and VTableUses.
+ SavePendingInstantiationsAndVTableUses.reset();
}
}
@@ -3651,7 +3638,7 @@ void Sema::BuildVariableInstantiation(
// Diagnose unused local variables with dependent types, where the diagnostic
// will have been deferred.
if (!NewVar->isInvalidDecl() &&
- NewVar->getDeclContext()->isFunctionOrMethod() && !NewVar->isUsed() &&
+ NewVar->getDeclContext()->isFunctionOrMethod() &&
OldVar->getType()->isDependentType())
DiagnoseUnusedDecl(NewVar);
}
@@ -3793,11 +3780,11 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// If we're performing recursive template instantiation, create our own
// queue of pending implicit instantiations that we will instantiate
// later, while we're still within our own instantiation context.
- SmallVector<VTableUse, 16> SavedVTableUses;
- std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
+ std::unique_ptr<SavePendingInstantiationsAndVTableUsesRAII>
+ SavePendingInstantiationsAndVTableUses;
if (Recursive) {
- VTableUses.swap(SavedVTableUses);
- PendingInstantiations.swap(SavedPendingInstantiations);
+ SavePendingInstantiationsAndVTableUses.reset(
+ new SavePendingInstantiationsAndVTableUsesRAII(*this));
}
LocalInstantiationScope Local(*this);
@@ -3825,15 +3812,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// instantiation of this template.
PerformPendingInstantiations();
- // Restore the set of pending vtables.
- assert(VTableUses.empty() &&
- "VTableUses should be empty before it is discarded.");
- VTableUses.swap(SavedVTableUses);
-
- // Restore the set of pending implicit instantiations.
- assert(PendingInstantiations.empty() &&
- "PendingInstantiations should be empty before it is discarded.");
- PendingInstantiations.swap(SavedPendingInstantiations);
+ // Restore PendingInstantiations and VTableUses.
+ SavePendingInstantiationsAndVTableUses.reset();
}
}
@@ -3917,13 +3897,13 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// If we're performing recursive template instantiation, create our own
// queue of pending implicit instantiations that we will instantiate later,
// while we're still within our own instantiation context.
- SmallVector<VTableUse, 16> SavedVTableUses;
- std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
SavePendingLocalImplicitInstantiationsRAII
SavedPendingLocalImplicitInstantiations(*this);
+ std::unique_ptr<SavePendingInstantiationsAndVTableUsesRAII>
+ SavePendingInstantiationsAndVTableUses;
if (Recursive) {
- VTableUses.swap(SavedVTableUses);
- PendingInstantiations.swap(SavedPendingInstantiations);
+ SavePendingInstantiationsAndVTableUses.reset(
+ new SavePendingInstantiationsAndVTableUsesRAII(*this));
}
// Enter the scope of this instantiation. We don't use
@@ -3990,15 +3970,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// instantiation of this template.
PerformPendingInstantiations();
- // Restore the set of pending vtables.
- assert(VTableUses.empty() &&
- "VTableUses should be empty before it is discarded.");
- VTableUses.swap(SavedVTableUses);
-
- // Restore the set of pending implicit instantiations.
- assert(PendingInstantiations.empty() &&
- "PendingInstantiations should be empty before it is discarded.");
- PendingInstantiations.swap(SavedPendingInstantiations);
+ // Restore PendingInstantiations and VTableUses.
+ SavePendingInstantiationsAndVTableUses.reset();
}
}
@@ -4235,25 +4208,26 @@ static bool isInstantiationOf(EnumDecl *Pattern,
static bool isInstantiationOf(UsingShadowDecl *Pattern,
UsingShadowDecl *Instance,
ASTContext &C) {
- return C.getInstantiatedFromUsingShadowDecl(Instance) == Pattern;
+ return declaresSameEntity(C.getInstantiatedFromUsingShadowDecl(Instance),
+ Pattern);
}
static bool isInstantiationOf(UsingDecl *Pattern,
UsingDecl *Instance,
ASTContext &C) {
- return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+ return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance), Pattern);
}
static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
UsingDecl *Instance,
ASTContext &C) {
- return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+ return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance), Pattern);
}
static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
UsingDecl *Instance,
ASTContext &C) {
- return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+ return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance), Pattern);
}
static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
@@ -4319,8 +4293,8 @@ static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
if (FieldDecl *Field = dyn_cast<FieldDecl>(Other)) {
if (!Field->getDeclName()) {
// This is an unnamed field.
- return Ctx.getInstantiatedFromUnnamedFieldDecl(Field) ==
- cast<FieldDecl>(D);
+ return declaresSameEntity(Ctx.getInstantiatedFromUnnamedFieldDecl(Field),
+ cast<FieldDecl>(D));
}
}
@@ -4412,17 +4386,17 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
(isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) {
// D is a local of some kind. Look into the map of local
// declarations to their instantiations.
- typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
- llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found
- = CurrentInstantiationScope->findInstantiationOf(D);
-
- if (Found) {
- if (Decl *FD = Found->dyn_cast<Decl *>())
- return cast<NamedDecl>(FD);
-
- int PackIdx = ArgumentPackSubstitutionIndex;
- assert(PackIdx != -1 && "found declaration pack but not pack expanding");
- return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]);
+ if (CurrentInstantiationScope) {
+ if (auto Found = CurrentInstantiationScope->findInstantiationOf(D)) {
+ if (Decl *FD = Found->dyn_cast<Decl *>())
+ return cast<NamedDecl>(FD);
+
+ int PackIdx = ArgumentPackSubstitutionIndex;
+ assert(PackIdx != -1 &&
+ "found declaration pack but not pack expanding");
+ typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
+ return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]);
+ }
}
// If we're performing a partial substitution during template argument
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 8e4ce0d9da6f..e4fab71d995b 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -197,6 +197,20 @@ namespace {
};
}
+/// \brief Determine whether it's possible for an unexpanded parameter pack to
+/// be valid in this location. This only happens when we're in a declaration
+/// that is nested within an expression that could be expanded, such as a
+/// lambda-expression within a function call.
+///
+/// This is conservatively correct, but may claim that some unexpanded packs are
+/// permitted when they are not.
+bool Sema::isUnexpandedParameterPackPermitted() {
+ for (auto *SI : FunctionScopes)
+ if (isa<sema::LambdaScopeInfo>(SI))
+ return true;
+ return false;
+}
+
/// \brief Diagnose all of the unexpanded parameter packs in the given
/// vector.
bool
@@ -230,7 +244,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
else
Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier();
- if (Name && NamesKnown.insert(Name))
+ if (Name && NamesKnown.insert(Name).second)
Names.push_back(Name);
if (Unexpanded[I].second.isValid())
@@ -733,24 +747,48 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_error:
break;
}
-
+
for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) {
const DeclaratorChunk &Chunk = D.getTypeObject(I);
switch (Chunk.Kind) {
case DeclaratorChunk::Pointer:
case DeclaratorChunk::Reference:
case DeclaratorChunk::Paren:
+ case DeclaratorChunk::BlockPointer:
// These declarator chunks cannot contain any parameter packs.
break;
case DeclaratorChunk::Array:
+ if (Chunk.Arr.NumElts &&
+ Chunk.Arr.NumElts->containsUnexpandedParameterPack())
+ return true;
+ break;
case DeclaratorChunk::Function:
- case DeclaratorChunk::BlockPointer:
- // Syntactically, these kinds of declarator chunks all come after the
- // declarator-id (conceptually), so the parser should not invoke this
- // routine at this time.
- llvm_unreachable("Could not have seen this kind of declarator chunk");
-
+ for (unsigned i = 0, e = Chunk.Fun.NumParams; i != e; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(Chunk.Fun.Params[i].Param);
+ QualType ParamTy = Param->getType();
+ assert(!ParamTy.isNull() && "Couldn't parse type?");
+ if (ParamTy->containsUnexpandedParameterPack()) return true;
+ }
+
+ if (Chunk.Fun.getExceptionSpecType() == EST_Dynamic) {
+ for (unsigned i = 0; i != Chunk.Fun.NumExceptions; ++i) {
+ if (Chunk.Fun.Exceptions[i]
+ .Ty.get()
+ ->containsUnexpandedParameterPack())
+ return true;
+ }
+ } else if (Chunk.Fun.getExceptionSpecType() == EST_ComputedNoexcept &&
+ Chunk.Fun.NoexceptExpr->containsUnexpandedParameterPack())
+ return true;
+
+ if (Chunk.Fun.hasTrailingReturnType()) {
+ QualType T = Chunk.Fun.getTrailingReturnType().get();
+ if (!T.isNull() && T->containsUnexpandedParameterPack())
+ return true;
+ }
+ break;
+
case DeclaratorChunk::MemberPointer:
if (Chunk.Mem.Scope().getScopeRep() &&
Chunk.Mem.Scope().getScopeRep()->containsUnexpandedParameterPack())
@@ -800,7 +838,6 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
LookupName(R, S);
NamedDecl *ParameterPack = nullptr;
- ParameterPackValidatorCCC Validator;
switch (R.getResultKind()) {
case LookupResult::Found:
ParameterPack = R.getFoundDecl();
@@ -808,9 +845,10 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
- if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
- R.getLookupKind(), S, nullptr,
- Validator, CTK_ErrorRecovery)) {
+ if (TypoCorrection Corrected =
+ CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, nullptr,
+ llvm::make_unique<ParameterPackValidatorCCC>(),
+ CTK_ErrorRecovery)) {
diagnoseTypo(Corrected,
PDiag(diag::err_sizeof_pack_no_pack_name_suggest) << &Name,
PDiag(diag::note_parameter_pack_here));
@@ -897,3 +935,108 @@ Sema::getTemplateArgumentPackExpansionPattern(
llvm_unreachable("Invalid TemplateArgument Kind!");
}
+
+static void CheckFoldOperand(Sema &S, Expr *E) {
+ if (!E)
+ return;
+
+ E = E->IgnoreImpCasts();
+ if (isa<BinaryOperator>(E) || isa<AbstractConditionalOperator>(E)) {
+ S.Diag(E->getExprLoc(), diag::err_fold_expression_bad_operand)
+ << E->getSourceRange()
+ << FixItHint::CreateInsertion(E->getLocStart(), "(")
+ << FixItHint::CreateInsertion(E->getLocEnd(), ")");
+ }
+}
+
+ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
+ tok::TokenKind Operator,
+ SourceLocation EllipsisLoc, Expr *RHS,
+ SourceLocation RParenLoc) {
+ // LHS and RHS must be cast-expressions. We allow an arbitrary expression
+ // in the parser and reduce down to just cast-expressions here.
+ CheckFoldOperand(*this, LHS);
+ CheckFoldOperand(*this, RHS);
+
+ // [expr.prim.fold]p3:
+ // In a binary fold, op1 and op2 shall be the same fold-operator, and
+ // either e1 shall contain an unexpanded parameter pack or e2 shall contain
+ // an unexpanded parameter pack, but not both.
+ if (LHS && RHS &&
+ LHS->containsUnexpandedParameterPack() ==
+ RHS->containsUnexpandedParameterPack()) {
+ return Diag(EllipsisLoc,
+ LHS->containsUnexpandedParameterPack()
+ ? diag::err_fold_expression_packs_both_sides
+ : diag::err_pack_expansion_without_parameter_packs)
+ << LHS->getSourceRange() << RHS->getSourceRange();
+ }
+
+ // [expr.prim.fold]p2:
+ // In a unary fold, the cast-expression shall contain an unexpanded
+ // parameter pack.
+ if (!LHS || !RHS) {
+ Expr *Pack = LHS ? LHS : RHS;
+ assert(Pack && "fold expression with neither LHS nor RHS");
+ if (!Pack->containsUnexpandedParameterPack())
+ return Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+ << Pack->getSourceRange();
+ }
+
+ BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Operator);
+ return BuildCXXFoldExpr(LParenLoc, LHS, Opc, EllipsisLoc, RHS, RParenLoc);
+}
+
+ExprResult Sema::BuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
+ BinaryOperatorKind Operator,
+ SourceLocation EllipsisLoc, Expr *RHS,
+ SourceLocation RParenLoc) {
+ return new (Context) CXXFoldExpr(Context.DependentTy, LParenLoc, LHS,
+ Operator, EllipsisLoc, RHS, RParenLoc);
+}
+
+ExprResult Sema::BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc,
+ BinaryOperatorKind Operator) {
+ // [temp.variadic]p9:
+ // If N is zero for a unary fold-expression, the value of the expression is
+ // * -> 1
+ // + -> int()
+ // & -> -1
+ // | -> int()
+ // && -> true
+ // || -> false
+ // , -> void()
+ // if the operator is not listed [above], the instantiation is ill-formed.
+ //
+ // Note that we need to use something like int() here, not merely 0, to
+ // prevent the result from being a null pointer constant.
+ QualType ScalarType;
+ switch (Operator) {
+ case BO_Add:
+ ScalarType = Context.IntTy;
+ break;
+ case BO_Mul:
+ return ActOnIntegerConstant(EllipsisLoc, 1);
+ case BO_Or:
+ ScalarType = Context.IntTy;
+ break;
+ case BO_And:
+ return CreateBuiltinUnaryOp(EllipsisLoc, UO_Minus,
+ ActOnIntegerConstant(EllipsisLoc, 1).get());
+ case BO_LOr:
+ return ActOnCXXBoolLiteral(EllipsisLoc, tok::kw_false);
+ case BO_LAnd:
+ return ActOnCXXBoolLiteral(EllipsisLoc, tok::kw_true);
+ case BO_Comma:
+ ScalarType = Context.VoidTy;
+ break;
+
+ default:
+ return Diag(EllipsisLoc, diag::err_fold_expression_empty)
+ << BinaryOperator::getOpcodeStr(Operator);
+ }
+
+ return new (Context) CXXScalarValueInitExpr(
+ ScalarType, Context.getTrivialTypeSourceInfo(ScalarType, EllipsisLoc),
+ EllipsisLoc);
+}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index be1191c1e8e0..0f96a1cbce35 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -107,6 +107,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
case AttributeList::AT_StdCall: \
case AttributeList::AT_ThisCall: \
case AttributeList::AT_Pascal: \
+ case AttributeList::AT_VectorCall: \
case AttributeList::AT_MSABI: \
case AttributeList::AT_SysVABI: \
case AttributeList::AT_Regparm: \
@@ -660,26 +661,27 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
// ...and *prepend* it to the declarator.
SourceLocation NoLoc;
declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction(
- /*HasProto=*/true,
- /*IsAmbiguous=*/false,
- /*LParenLoc=*/NoLoc,
- /*ArgInfo=*/nullptr,
- /*NumArgs=*/0,
- /*EllipsisLoc=*/NoLoc,
- /*RParenLoc=*/NoLoc,
- /*TypeQuals=*/0,
- /*RefQualifierIsLvalueRef=*/true,
- /*RefQualifierLoc=*/NoLoc,
- /*ConstQualifierLoc=*/NoLoc,
- /*VolatileQualifierLoc=*/NoLoc,
- /*MutableLoc=*/NoLoc,
- EST_None,
- /*ESpecLoc=*/NoLoc,
- /*Exceptions=*/nullptr,
- /*ExceptionRanges=*/nullptr,
- /*NumExceptions=*/0,
- /*NoexceptExpr=*/nullptr,
- loc, loc, declarator));
+ /*HasProto=*/true,
+ /*IsAmbiguous=*/false,
+ /*LParenLoc=*/NoLoc,
+ /*ArgInfo=*/nullptr,
+ /*NumArgs=*/0,
+ /*EllipsisLoc=*/NoLoc,
+ /*RParenLoc=*/NoLoc,
+ /*TypeQuals=*/0,
+ /*RefQualifierIsLvalueRef=*/true,
+ /*RefQualifierLoc=*/NoLoc,
+ /*ConstQualifierLoc=*/NoLoc,
+ /*VolatileQualifierLoc=*/NoLoc,
+ /*RestrictQualifierLoc=*/NoLoc,
+ /*MutableLoc=*/NoLoc, EST_None,
+ /*ESpecLoc=*/NoLoc,
+ /*Exceptions=*/nullptr,
+ /*ExceptionRanges=*/nullptr,
+ /*NumExceptions=*/0,
+ /*NoexceptExpr=*/nullptr,
+ /*ExceptionSpecTokens=*/nullptr,
+ loc, loc, declarator));
// For consistency, make sure the state still has us as processing
// the decl spec.
@@ -763,7 +765,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// is inferred from the return statements inside the block.
// The declspec is always missing in a lambda expr context; it is either
// specified with a trailing return type or inferred.
- if (S.getLangOpts().CPlusPlus1y &&
+ if (S.getLangOpts().CPlusPlus14 &&
declarator.getContext() == Declarator::LambdaExprContext) {
// In C++1y, a lambda's implicit return type is 'auto'.
Result = Context.getAutoDeductType();
@@ -1005,16 +1007,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
const bool IsParameterPack = declarator.hasEllipsis();
-
- // Create a name for the invented template parameter type.
- std::string InventedTemplateParamName = "$auto-";
- llvm::raw_string_ostream ss(InventedTemplateParamName);
- ss << TemplateParameterDepth;
- ss << "-" << AutoParameterPosition;
- ss.flush();
-
- IdentifierInfo& TemplateParamII = Context.Idents.get(
- InventedTemplateParamName.c_str());
+
// Turns out we must create the TemplateTypeParmDecl here to
// retrieve the corresponding template parameter type.
TemplateTypeParmDecl *CorrespondingTemplateParam =
@@ -1029,11 +1022,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
/*NameLoc*/ declarator.getLocStart(),
TemplateParameterDepth,
AutoParameterPosition, // our template param index
- /* Identifier*/ &TemplateParamII, false, IsParameterPack);
+ /* Identifier*/ nullptr, false, IsParameterPack);
LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
// Replace the 'auto' in the function parameter with this invented
// template type parameter.
- Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0);
+ Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0);
} else {
Result = Context.getAutoType(QualType(), /*decltype(auto)*/false, false);
}
@@ -1107,8 +1100,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
S.Diag(DS.getConstSpecLoc(), diag::warn_typecheck_function_qualifiers)
<< Result << DS.getSourceRange();
else if (TypeQuals & DeclSpec::TQ_volatile)
- S.Diag(DS.getVolatileSpecLoc(), diag::warn_typecheck_function_qualifiers)
- << Result << DS.getSourceRange();
+ S.Diag(DS.getVolatileSpecLoc(),
+ diag::warn_typecheck_function_qualifiers)
+ << Result << DS.getSourceRange();
else {
assert((TypeQuals & (DeclSpec::TQ_restrict | DeclSpec::TQ_atomic)) &&
"Has CVRA quals but not C, V, R, or A?");
@@ -1174,6 +1168,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = Qualified;
}
+ assert(!Result.isNull() && "This function should not return a null type");
return Result;
}
@@ -1186,6 +1181,9 @@ static std::string getPrintableNameForEntity(DeclarationName Entity) {
QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
Qualifiers Qs, const DeclSpec *DS) {
+ if (T.isNull())
+ return QualType();
+
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
// object or incomplete types shall not be restrict-qualified."
if (Qs.hasRestrict()) {
@@ -1224,6 +1222,9 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
unsigned CVRA, const DeclSpec *DS) {
+ if (T.isNull())
+ return QualType();
+
// Convert from DeclSpec::TQ to Qualifiers::TQ by just dropping TQ_atomic.
unsigned CVR = CVRA & ~DeclSpec::TQ_atomic;
@@ -1746,7 +1747,7 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) {
}
// Functions cannot return half FP.
- if (T->isHalfType()) {
+ if (T->isHalfType() && !getLangOpts().HalfArgsAndReturns) {
Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 <<
FixItHint::CreateInsertion(Loc, "*");
return true;
@@ -1776,7 +1777,7 @@ QualType Sema::BuildFunctionType(QualType T,
if (ParamType->isVoidType()) {
Diag(Loc, diag::err_param_with_void_type);
Invalid = true;
- } else if (ParamType->isHalfType()) {
+ } else if (ParamType->isHalfType() && !getLangOpts().HalfArgsAndReturns) {
// Disallow half FP arguments.
Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 0 <<
FixItHint::CreateInsertion(Loc, "*");
@@ -2175,7 +2176,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Error = 0;
break;
case Declarator::LambdaExprParameterContext:
- if (!(SemaRef.getLangOpts().CPlusPlus1y
+ if (!(SemaRef.getLangOpts().CPlusPlus14
&& D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto))
Error = 14;
break;
@@ -2208,11 +2209,11 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Error = 10; // Type alias
break;
case Declarator::TrailingReturnContext:
- if (!SemaRef.getLangOpts().CPlusPlus1y)
+ if (!SemaRef.getLangOpts().CPlusPlus14)
Error = 11; // Function return type
break;
case Declarator::ConversionIdContext:
- if (!SemaRef.getLangOpts().CPlusPlus1y)
+ if (!SemaRef.getLangOpts().CPlusPlus14)
Error = 12; // conversion-type-id
break;
case Declarator::TypeNameContext:
@@ -2332,6 +2333,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
}
}
+ assert(!T.isNull() && "This function should not return a null type");
return T;
}
@@ -2481,7 +2483,8 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D,
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType declSpecType,
TypeSourceInfo *TInfo) {
-
+ // The TypeSourceInfo that this function returns will not be a null type.
+ // If there is an error, this function will fill in a dummy type as fallback.
QualType T = declSpecType;
Declarator &D = state.getDeclarator();
Sema &S = state.getSema();
@@ -2697,7 +2700,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// and not, for instance, a pointer to a function.
if (D.getDeclSpec().containsPlaceholderType() &&
!FTI.hasTrailingReturnType() && chunkIndex == 0 &&
- !S.getLangOpts().CPlusPlus1y) {
+ !S.getLangOpts().CPlusPlus14) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto
? diag::err_auto_missing_trailing_return
@@ -2751,7 +2754,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
S.Diag(D.getIdentifierLoc(), diag::err_opencl_half_return) << T;
D.setInvalidType(true);
}
- } else {
+ } else if (!S.getLangOpts().HalfArgsAndReturns) {
S.Diag(D.getIdentifierLoc(),
diag::err_parameters_retval_cannot_have_fp16_type) << 1;
D.setInvalidType(true);
@@ -2941,7 +2944,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
D.setInvalidType();
Param->setInvalidDecl();
}
- } else {
+ } else if (!S.getLangOpts().HalfArgsAndReturns) {
S.Diag(Param->getLocation(),
diag::err_parameters_retval_cannot_have_fp16_type) << 0;
D.setInvalidType();
@@ -2989,12 +2992,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
NoexceptExpr = FTI.NoexceptExpr;
}
- S.checkExceptionSpecification(FTI.getExceptionSpecType(),
+ S.checkExceptionSpecification(D.isFunctionDeclarationContext(),
+ FTI.getExceptionSpecType(),
DynamicExceptions,
DynamicExceptionRanges,
NoexceptExpr,
Exceptions,
- EPI);
+ EPI.ExceptionSpec);
T = Context.getFunctionType(T, ParamTys, EPI);
}
@@ -3021,6 +3025,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
llvm_unreachable("Nested-name-specifier must name a type");
case NestedNameSpecifier::TypeSpec:
@@ -3044,7 +3049,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
if (!ClsType.isNull())
- T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc, D.getIdentifier());
+ T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc,
+ D.getIdentifier());
if (T.isNull()) {
T = Context.IntTy;
D.setInvalidType(true);
@@ -3064,6 +3070,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
processTypeAttrs(state, T, TAL_DeclChunk, attrs);
}
+ assert(!T.isNull() && "T must not be null after this point");
+
if (LangOpts.CPlusPlus && T->isFunctionType()) {
const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>();
assert(FnTy && "Why oh why is there not a FunctionProtoType here?");
@@ -3120,9 +3128,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
RemovalLocs.push_back(Chunk.Fun.getConstQualifierLoc());
if (Chunk.Fun.TypeQuals & Qualifiers::Volatile)
RemovalLocs.push_back(Chunk.Fun.getVolatileQualifierLoc());
- // FIXME: We do not track the location of the __restrict qualifier.
- //if (Chunk.Fun.TypeQuals & Qualifiers::Restrict)
- // RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc());
+ if (Chunk.Fun.TypeQuals & Qualifiers::Restrict)
+ RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc());
if (!RemovalLocs.empty()) {
std::sort(RemovalLocs.begin(), RemovalLocs.end(),
BeforeThanCompare<SourceLocation>(S.getSourceManager()));
@@ -3153,12 +3160,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
// Apply any undistributed attributes from the declarator.
- if (!T.isNull())
- if (AttributeList *attrs = D.getAttributes())
- processTypeAttrs(state, T, TAL_DeclName, attrs);
+ if (AttributeList *attrs = D.getAttributes())
+ processTypeAttrs(state, T, TAL_DeclName, attrs);
// Diagnose any ignored type attributes.
- if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T);
+ state.diagnoseIgnoredTypeAttrs(T);
// C++0x [dcl.constexpr]p9:
// A constexpr specifier used in an object declaration declares the object
@@ -3169,7 +3175,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// If there was an ellipsis in the declarator, the declaration declares a
// parameter pack whose type may be a pack expansion type.
- if (D.hasEllipsis() && !T.isNull()) {
+ if (D.hasEllipsis()) {
// C++0x [dcl.fct]p13:
// A declarator-id or abstract-declarator containing an ellipsis shall
// only be used in a parameter-declaration. Such a parameter-declaration
@@ -3234,15 +3240,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case Declarator::TemplateTypeArgContext:
// FIXME: We may want to allow parameter packs in block-literal contexts
// in the future.
- S.Diag(D.getEllipsisLoc(), diag::err_ellipsis_in_declarator_not_parameter);
+ S.Diag(D.getEllipsisLoc(),
+ diag::err_ellipsis_in_declarator_not_parameter);
D.setEllipsisLoc(SourceLocation());
break;
}
}
- if (T.isNull())
- return Context.getNullTypeSourceInfo();
- else if (D.isInvalidType())
+ assert(!T.isNull() && "T must not be null at the end of this function");
+ if (D.isInvalidType())
return Context.getTrivialTypeSourceInfo(T);
return S.GetTypeSourceInfoForDeclarator(D, T, TInfo);
@@ -3261,8 +3267,6 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
TypeSourceInfo *ReturnTypeInfo = nullptr;
QualType T = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
- if (T.isNull())
- return Context.getNullTypeSourceInfo();
if (D.isPrototypeContext() && getLangOpts().ObjCAutoRefCount)
inferARCWriteback(state, T);
@@ -3376,8 +3380,6 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
TypeSourceInfo *ReturnTypeInfo = nullptr;
QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
- if (declSpecTy.isNull())
- return Context.getNullTypeSourceInfo();
if (getLangOpts().ObjCAutoRefCount) {
Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy);
@@ -3417,6 +3419,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
return AttributeList::AT_ThisCall;
case AttributedType::attr_pascal:
return AttributeList::AT_Pascal;
+ case AttributedType::attr_vectorcall:
+ return AttributeList::AT_VectorCall;
case AttributedType::attr_pcs:
case AttributedType::attr_pcs_vfp:
return AttributeList::AT_Pcs;
@@ -3717,6 +3721,7 @@ namespace {
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
llvm_unreachable("Nested-name-specifier must name a type");
}
@@ -3975,6 +3980,8 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
ASIdx = LangAS::opencl_local; break;
case AttributeList::AT_OpenCLConstantAddressSpace:
ASIdx = LangAS::opencl_constant; break;
+ case AttributeList::AT_OpenCLGenericAddressSpace:
+ ASIdx = LangAS::opencl_generic; break;
default:
assert(Attr.getKind() == AttributeList::AT_OpenCLPrivateAddressSpace);
ASIdx = 0; break;
@@ -4432,6 +4439,8 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
return AttributedType::attr_thiscall;
case AttributeList::AT_Pascal:
return AttributedType::attr_pascal;
+ case AttributeList::AT_VectorCall:
+ return AttributedType::attr_vectorcall;
case AttributeList::AT_Pcs: {
// The attribute may have had a fixit applied where we treated an
// identifier as a string literal. The contents of the string are valid,
@@ -4549,7 +4558,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
}
// Diagnose use of callee-cleanup calling convention on variadic functions.
- if (isCalleeCleanup(CC)) {
+ if (!supportsVariadicCall(CC)) {
const FunctionProtoType *FnP = dyn_cast<FunctionProtoType>(fn);
if (FnP && FnP->isVariadic()) {
unsigned DiagID = diag::err_cconv_varargs;
@@ -4564,23 +4573,12 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
}
}
- // Diagnose the use of X86 fastcall on unprototyped functions.
- if (CC == CC_X86FastCall) {
- if (isa<FunctionNoProtoType>(fn)) {
- S.Diag(attr.getLoc(), diag::err_cconv_knr)
- << FunctionType::getNameForCallConv(CC);
- attr.setInvalid();
- return true;
- }
-
- // Also diagnose fastcall with regparm.
- if (fn->getHasRegParm()) {
- S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "regparm"
- << FunctionType::getNameForCallConv(CC);
- attr.setInvalid();
- return true;
- }
+ // Also diagnose fastcall with regparm.
+ if (CC == CC_X86FastCall && fn->getHasRegParm()) {
+ S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << "regparm" << FunctionType::getNameForCallConv(CC_X86FastCall);
+ attr.setInvalid();
+ return true;
}
// Modify the CC from the wrapped function type, wrap it all back, and then
@@ -4739,9 +4737,7 @@ static bool isPermittedNeonBaseType(QualType &Ty,
// 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 ||
- Triple.getArch() == llvm::Triple::arm64_be;
+ Triple.getArch() == llvm::Triple::aarch64_be;
if (VecKind == VectorType::NeonPolyVector) {
if (IsPolyUnsigned) {
// AArch64 polynomial vectors are unsigned and support poly64.
@@ -4759,9 +4755,7 @@ static bool isPermittedNeonBaseType(QualType &Ty,
// Non-polynomial vector types: the usual suspects are allowed, as well as
// float64_t on AArch64.
bool Is64Bit = Triple.getArch() == llvm::Triple::aarch64 ||
- Triple.getArch() == llvm::Triple::aarch64_be ||
- Triple.getArch() == llvm::Triple::arm64 ||
- Triple.getArch() == llvm::Triple::arm64_be;
+ Triple.getArch() == llvm::Triple::aarch64_be;
if (Is64Bit && BTy->getKind() == BuiltinType::Double)
return true;
@@ -4899,6 +4893,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
case AttributeList::AT_OpenCLGlobalAddressSpace:
case AttributeList::AT_OpenCLLocalAddressSpace:
case AttributeList::AT_OpenCLConstantAddressSpace:
+ case AttributeList::AT_OpenCLGenericAddressSpace:
case AttributeList::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
@@ -5098,31 +5093,9 @@ static bool hasVisibleDefinition(Sema &S, NamedDecl *D, NamedDecl **Suggested) {
// If this definition was instantiated from a template, map back to the
// pattern from which it was instantiated.
- //
- // FIXME: There must be a better place for this to live.
if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
- if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
- auto From = TD->getInstantiatedFrom();
- if (auto *CTD = From.dyn_cast<ClassTemplateDecl*>()) {
- while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
- if (NewCTD->isMemberSpecialization())
- break;
- CTD = NewCTD;
- }
- RD = CTD->getTemplatedDecl();
- } else if (auto *CTPSD = From.dyn_cast<
- ClassTemplatePartialSpecializationDecl *>()) {
- while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
- if (NewCTPSD->isMemberSpecialization())
- break;
- CTPSD = NewCTPSD;
- }
- RD = CTPSD;
- }
- } else if (isTemplateInstantiation(RD->getTemplateSpecializationKind())) {
- while (auto *NewRD = RD->getInstantiatedFromMemberClass())
- RD = NewRD;
- }
+ if (auto *Pattern = RD->getTemplateInstantiationPattern())
+ RD = Pattern;
D = RD->getDefinition();
} else if (auto *ED = dyn_cast<EnumDecl>(D)) {
while (auto *NewED = ED->getInstantiatedFromMemberEnum())
@@ -5178,14 +5151,6 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
? S.ImplicitMSInheritanceAttrLoc
: RD->getSourceRange()));
}
-
- if (RD->hasDefinition()) {
- // Assign inheritance models to all of the base classes, because now we can
- // form pointers to members of base classes without calling
- // RequireCompleteType on the pointer to member of the base class type.
- for (const CXXBaseSpecifier &BS : RD->bases())
- assignInheritanceModel(S, BS.getType()->getAsCXXRecordDecl());
- }
}
/// \brief The implementation of RequireCompleteType
@@ -5510,6 +5475,8 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
} else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) {
if (PR->isExplicitProperty())
return PR->getExplicitProperty()->getType();
+ } else if (auto *PE = dyn_cast<PredefinedExpr>(E)) {
+ return PE->getType();
}
// C++11 [expr.lambda.prim]p18:
@@ -5550,11 +5517,19 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
return T;
}
-QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) {
+QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc,
+ bool AsUnevaluated) {
ExprResult ER = CheckPlaceholderExpr(E);
if (ER.isInvalid()) return QualType();
E = ER.get();
+ if (AsUnevaluated && ActiveTemplateInstantiations.empty() &&
+ E->HasSideEffects(Context, false)) {
+ // The expression operand for decltype is in an unevaluated expression
+ // context, so side effects could result in unintended consequences.
+ Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
+ }
+
return Context.getDecltypeType(E, getDecltypeForExpr(*this, E));
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 312811d2c008..36abbb624af7 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SEMA_TREETRANSFORM_H
-#define LLVM_CLANG_SEMA_TREETRANSFORM_H
+#ifndef LLVM_CLANG_LIB_SEMA_TREETRANSFORM_H
+#define LLVM_CLANG_LIB_SEMA_TREETRANSFORM_H
#include "TypeLocBuilder.h"
#include "clang/AST/Decl.h"
@@ -327,6 +327,27 @@ public:
/// \returns the transformed OpenMP clause.
OMPClause *TransformOMPClause(OMPClause *S);
+ /// \brief Transform the given attribute.
+ ///
+ /// By default, this routine transforms a statement by delegating to the
+ /// appropriate TransformXXXAttr function to transform a specific kind
+ /// of attribute. Subclasses may override this function to transform
+ /// attributed statements using some other mechanism.
+ ///
+ /// \returns the transformed attribute
+ const Attr *TransformAttr(const Attr *S);
+
+/// \brief Transform the specified attribute.
+///
+/// Subclasses should override the transformation of attributes with a pragma
+/// spelling to transform expressions stored within the attribute.
+///
+/// \returns the transformed attribute.
+#define ATTR(X)
+#define PRAGMA_SPELLING_ATTR(X) \
+ const X##Attr *Transform##X##Attr(const X##Attr *R) { return R; }
+#include "clang/Basic/AttrList.inc"
+
/// \brief Transform the given expression.
///
/// By default, this routine transforms an expression by delegating to the
@@ -542,10 +563,17 @@ public:
QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
#include "clang/AST/TypeLocNodes.def"
+ template<typename Fn>
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
CXXRecordDecl *ThisContext,
- unsigned ThisTypeQuals);
+ unsigned ThisTypeQuals,
+ Fn TransformExceptionSpec);
+
+ bool TransformExceptionSpec(SourceLocation Loc,
+ FunctionProtoType::ExceptionSpecInfo &ESI,
+ SmallVectorImpl<QualType> &Exceptions,
+ bool &Changed);
StmtResult TransformSEHHandler(Stmt *Handler);
@@ -560,10 +588,9 @@ public:
TemplateName Template,
CXXScopeSpec &SS);
- QualType
- TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
- DependentTemplateSpecializationTypeLoc TL,
- NestedNameSpecifierLoc QualifierLoc);
+ QualType TransformDependentTemplateSpecializationType(
+ TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL,
+ NestedNameSpecifierLoc QualifierLoc);
/// \brief Transforms the parameters of a function type into the
/// given vectors.
@@ -1665,10 +1692,8 @@ public:
}
StmtResult RebuildSEHTryStmt(bool IsCXXTry, SourceLocation TryLoc,
- Stmt *TryBlock, Stmt *Handler, int HandlerIndex,
- int HandlerParentIndex) {
- return getSema().ActOnSEHTryBlock(IsCXXTry, TryLoc, TryBlock, Handler,
- HandlerIndex, HandlerParentIndex);
+ Stmt *TryBlock, Stmt *Handler) {
+ return getSema().ActOnSEHTryBlock(IsCXXTry, TryLoc, TryBlock, Handler);
}
StmtResult RebuildSEHExceptStmt(SourceLocation Loc, Expr *FilterExpr,
@@ -1680,6 +1705,15 @@ public:
return getSema().ActOnSEHFinallyBlock(Loc, Block);
}
+ /// \brief Build a new predefined expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildPredefinedExpr(SourceLocation Loc,
+ PredefinedExpr::IdentType IT) {
+ return getSema().BuildPredefinedExpr(Loc, IT);
+ }
+
/// \brief Build a new expression that references a declaration.
///
/// By default, performs semantic analysis to build the new expression.
@@ -2757,6 +2791,27 @@ public:
return getSema().CheckPackExpansion(Pattern, EllipsisLoc, NumExpansions);
}
+ /// \brief Build a new C++1z fold-expression.
+ ///
+ /// By default, performs semantic analysis in order to build a new fold
+ /// expression.
+ ExprResult RebuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
+ BinaryOperatorKind Operator,
+ SourceLocation EllipsisLoc, Expr *RHS,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXFoldExpr(LParenLoc, LHS, Operator, EllipsisLoc,
+ RHS, RParenLoc);
+ }
+
+ /// \brief Build an empty C++1z fold-expression with the given operator.
+ ///
+ /// By default, produces the fallback value for the fold-expression, or
+ /// produce an error if there is no fallback value.
+ ExprResult RebuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc,
+ BinaryOperatorKind Operator) {
+ return getSema().BuildEmptyCXXFoldExpr(EllipsisLoc, Operator);
+ }
+
/// \brief Build a new atomic operation expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -3103,6 +3158,14 @@ TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
SS.MakeGlobal(SemaRef.Context, Q.getBeginLoc());
break;
+ case NestedNameSpecifier::Super: {
+ CXXRecordDecl *RD =
+ cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
+ SourceLocation(), QNNS->getAsRecordDecl()));
+ SS.MakeSuper(SemaRef.Context, RD, Q.getBeginLoc(), Q.getEndLoc());
+ break;
+ }
+
case NestedNameSpecifier::TypeSpecWithTemplate:
case NestedNameSpecifier::TypeSpec: {
TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType,
@@ -4515,15 +4578,20 @@ template<typename Derived>
QualType
TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL) {
- return getDerived().TransformFunctionProtoType(TLB, TL, nullptr, 0);
-}
-
-template<typename Derived>
-QualType
-TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
- FunctionProtoTypeLoc TL,
- CXXRecordDecl *ThisContext,
- unsigned ThisTypeQuals) {
+ SmallVector<QualType, 4> ExceptionStorage;
+ TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
+ return getDerived().TransformFunctionProtoType(
+ TLB, TL, nullptr, 0,
+ [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
+ return This->TransformExceptionSpec(TL.getBeginLoc(), ESI,
+ ExceptionStorage, Changed);
+ });
+}
+
+template<typename Derived> template<typename Fn>
+QualType TreeTransform<Derived>::TransformFunctionProtoType(
+ TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals, Fn TransformExceptionSpec) {
// Transform the parameters and return type.
//
// We are required to instantiate the params and return type in source order.
@@ -4568,15 +4636,21 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
return QualType();
}
- // FIXME: Need to transform the exception-specification too.
+ FunctionProtoType::ExtProtoInfo EPI = T->getExtProtoInfo();
+
+ bool EPIChanged = false;
+ if (TransformExceptionSpec(EPI.ExceptionSpec, EPIChanged))
+ return QualType();
+
+ // FIXME: Need to transform ConsumedParameters for variadic template
+ // expansion.
QualType Result = TL.getType();
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());
+ ParamTypes.begin()) || EPIChanged) {
+ Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes, EPI);
if (Result.isNull())
return QualType();
}
@@ -4593,6 +4667,107 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
}
template<typename Derived>
+bool TreeTransform<Derived>::TransformExceptionSpec(
+ SourceLocation Loc, FunctionProtoType::ExceptionSpecInfo &ESI,
+ SmallVectorImpl<QualType> &Exceptions, bool &Changed) {
+ assert(ESI.Type != EST_Uninstantiated && ESI.Type != EST_Unevaluated);
+
+ // Instantiate a dynamic noexcept expression, if any.
+ if (ESI.Type == EST_ComputedNoexcept) {
+ EnterExpressionEvaluationContext Unevaluated(getSema(),
+ Sema::ConstantEvaluated);
+ ExprResult NoexceptExpr = getDerived().TransformExpr(ESI.NoexceptExpr);
+ if (NoexceptExpr.isInvalid())
+ return true;
+
+ NoexceptExpr = getSema().CheckBooleanCondition(
+ NoexceptExpr.get(), NoexceptExpr.get()->getLocStart());
+ if (NoexceptExpr.isInvalid())
+ return true;
+
+ if (!NoexceptExpr.get()->isValueDependent()) {
+ NoexceptExpr = getSema().VerifyIntegerConstantExpression(
+ NoexceptExpr.get(), nullptr,
+ diag::err_noexcept_needs_constant_expression,
+ /*AllowFold*/false);
+ if (NoexceptExpr.isInvalid())
+ return true;
+ }
+
+ if (ESI.NoexceptExpr != NoexceptExpr.get())
+ Changed = true;
+ ESI.NoexceptExpr = NoexceptExpr.get();
+ }
+
+ if (ESI.Type != EST_Dynamic)
+ return false;
+
+ // Instantiate a dynamic exception specification's type.
+ for (QualType T : ESI.Exceptions) {
+ if (const PackExpansionType *PackExpansion =
+ T->getAs<PackExpansionType>()) {
+ Changed = true;
+
+ // We have a pack expansion. Instantiate it.
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
+ Unexpanded);
+ assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
+
+ // Determine whether the set of unexpanded parameter packs can and
+ // should
+ // be expanded.
+ bool Expand = false;
+ bool RetainExpansion = false;
+ Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions();
+ // FIXME: Track the location of the ellipsis (and track source location
+ // information for the types in the exception specification in general).
+ if (getDerived().TryExpandParameterPacks(
+ Loc, SourceRange(), Unexpanded, Expand,
+ RetainExpansion, NumExpansions))
+ return true;
+
+ if (!Expand) {
+ // We can't expand this pack expansion into separate arguments yet;
+ // just substitute into the pattern and create a new pack expansion
+ // type.
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+ QualType U = getDerived().TransformType(PackExpansion->getPattern());
+ if (U.isNull())
+ return true;
+
+ U = SemaRef.Context.getPackExpansionType(U, NumExpansions);
+ Exceptions.push_back(U);
+ continue;
+ }
+
+ // Substitute into the pack expansion pattern for each slice of the
+ // pack.
+ for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), ArgIdx);
+
+ QualType U = getDerived().TransformType(PackExpansion->getPattern());
+ if (U.isNull() || SemaRef.CheckSpecifiedExceptionType(U, Loc))
+ return true;
+
+ Exceptions.push_back(U);
+ }
+ } else {
+ QualType U = getDerived().TransformType(T);
+ if (U.isNull() || SemaRef.CheckSpecifiedExceptionType(U, Loc))
+ return true;
+ if (T != U)
+ Changed = true;
+
+ Exceptions.push_back(U);
+ }
+ }
+
+ ESI.Exceptions = Exceptions;
+ return false;
+}
+
+template<typename Derived>
QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
TypeLocBuilder &TLB,
FunctionNoProtoTypeLoc TL) {
@@ -5147,8 +5322,8 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
if (const TemplateSpecializationType *TST =
NamedT->getAs<TemplateSpecializationType>()) {
TemplateName Template = TST->getTemplateName();
- if (TypeAliasTemplateDecl *TAT =
- dyn_cast_or_null<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) {
+ if (TypeAliasTemplateDecl *TAT = dyn_cast_or_null<TypeAliasTemplateDecl>(
+ Template.getAsTemplateDecl())) {
SemaRef.Diag(TL.getNamedTypeLoc().getBeginLoc(),
diag::err_tag_reference_non_tag) << 4;
SemaRef.Diag(TAT->getLocation(), diag::note_declared_at);
@@ -5529,19 +5704,43 @@ TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
SubStmt.get());
}
-template<typename Derived>
-StmtResult
-TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S) {
+template <typename Derived>
+const Attr *TreeTransform<Derived>::TransformAttr(const Attr *R) {
+ if (!R)
+ return R;
+
+ switch (R->getKind()) {
+// Transform attributes with a pragma spelling by calling TransformXXXAttr.
+#define ATTR(X)
+#define PRAGMA_SPELLING_ATTR(X) \
+ case attr::X: \
+ return getDerived().Transform##X##Attr(cast<X##Attr>(R));
+#include "clang/Basic/AttrList.inc"
+ default:
+ return R;
+ }
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S) {
+ bool AttrsChanged = false;
+ SmallVector<const Attr *, 1> Attrs;
+
+ // Visit attributes and keep track if any are transformed.
+ for (const auto *I : S->getAttrs()) {
+ const Attr *R = getDerived().TransformAttr(I);
+ AttrsChanged |= (I != R);
+ Attrs.push_back(R);
+ }
+
StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
if (SubStmt.isInvalid())
return StmtError();
- // TODO: transform attributes
- if (SubStmt.get() == S->getSubStmt() /* && attrs are the same */)
+ if (SubStmt.get() == S->getSubStmt() && !AttrsChanged)
return S;
- return getDerived().RebuildAttributedStmt(S->getAttrLoc(),
- S->getAttrs(),
+ return getDerived().RebuildAttributedStmt(S->getAttrLoc(), Attrs,
SubStmt.get());
}
@@ -5824,7 +6023,8 @@ TreeTransform<Derived>::TransformBreakStmt(BreakStmt *S) {
template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformReturnStmt(ReturnStmt *S) {
- ExprResult Result = getDerived().TransformExpr(S->getRetValue());
+ ExprResult Result = getDerived().TransformInitializer(S->getRetValue(),
+ /*NotCopyInit*/false);
if (Result.isInvalid())
return StmtError();
@@ -6380,9 +6580,8 @@ StmtResult TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) {
Handler.get() == S->getHandler())
return S;
- return getDerived().RebuildSEHTryStmt(
- S->getIsCXXTry(), S->getTryLoc(), TryBlock.get(), Handler.get(),
- S->getHandlerIndex(), S->getHandlerParentIndex());
+ return getDerived().RebuildSEHTryStmt(S->getIsCXXTry(), S->getTryLoc(),
+ TryBlock.get(), Handler.get());
}
template <typename Derived>
@@ -6504,6 +6703,17 @@ TreeTransform<Derived>::TransformOMPForDirective(OMPForDirective *D) {
template <typename Derived>
StmtResult
+TreeTransform<Derived>::TransformOMPForSimdDirective(OMPForSimdDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_for_simd, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
TreeTransform<Derived>::TransformOMPSectionsDirective(OMPSectionsDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_sections, DirName, nullptr,
@@ -6568,6 +6778,17 @@ StmtResult TreeTransform<Derived>::TransformOMPParallelForDirective(
}
template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPParallelForSimdDirective(
+ OMPParallelForSimdDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel_for_simd, DirName,
+ nullptr, D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
StmtResult TreeTransform<Derived>::TransformOMPParallelSectionsDirective(
OMPParallelSectionsDirective *D) {
DeclarationNameInfo DirName;
@@ -6633,6 +6854,50 @@ TreeTransform<Derived>::TransformOMPFlushDirective(OMPFlushDirective *D) {
return Res;
}
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPOrderedDirective(OMPOrderedDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_ordered, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPAtomicDirective(OMPAtomicDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_atomic, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPTargetDirective(OMPTargetDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_target, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPTeamsDirective(OMPTeamsDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_teams, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clause transformation
//===----------------------------------------------------------------------===//
@@ -6740,6 +7005,39 @@ TreeTransform<Derived>::TransformOMPMergeableClause(OMPMergeableClause *C) {
}
template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPReadClause(OMPReadClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPWriteClause(OMPWriteClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPUpdateClause(OMPUpdateClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPCaptureClause(OMPCaptureClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPSeqCstClause(OMPSeqCstClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
@@ -6912,7 +7210,11 @@ OMPClause *TreeTransform<Derived>::TransformOMPFlushClause(OMPFlushClause *C) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
- return E;
+ if (!E->isTypeDependent())
+ return E;
+
+ return getDerived().RebuildPredefinedExpr(E->getLocation(),
+ E->getIdentType());
}
template<typename Derived>
@@ -7161,6 +7463,12 @@ TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) {
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformTypoExpr(TypoExpr *E) {
+ return E;
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformPseudoObjectExpr(PseudoObjectExpr *E) {
// Rebuild the syntactic form. The original syntactic form has
// opaque-value expressions in it, so strip those away and rebuild
@@ -7873,15 +8181,11 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
Type == E->getTypeInfoAsWritten() &&
SubExpr.get() == E->getSubExpr())
return E;
- return getDerived().RebuildCXXNamedCastExpr(E->getOperatorLoc(),
- E->getStmtClass(),
- E->getAngleBrackets().getBegin(),
- Type,
- E->getAngleBrackets().getEnd(),
- // FIXME. this should be '(' location
- E->getAngleBrackets().getEnd(),
- SubExpr.get(),
- E->getRParenLoc());
+ return getDerived().RebuildCXXNamedCastExpr(
+ E->getOperatorLoc(), E->getStmtClass(), E->getAngleBrackets().getBegin(),
+ Type, E->getAngleBrackets().getEnd(),
+ // FIXME. this should be '(' location
+ E->getAngleBrackets().getEnd(), SubExpr.get(), E->getRParenLoc());
}
template<typename Derived>
@@ -8786,113 +9090,68 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
-
- // Transform any init-capture expressions before entering the scope of the
+ // Transform any init-capture expressions before entering the scope of the
// lambda body, because they are not semantically within that scope.
SmallVector<InitCaptureInfoTy, 8> InitCaptureExprsAndTypes;
InitCaptureExprsAndTypes.resize(E->explicit_capture_end() -
E->explicit_capture_begin());
-
for (LambdaExpr::capture_iterator C = E->capture_begin(),
- CEnd = E->capture_end();
- C != CEnd; ++C) {
+ CEnd = E->capture_end();
+ C != CEnd; ++C) {
if (!C->isInitCapture())
continue;
- EnterExpressionEvaluationContext EEEC(getSema(),
- Sema::PotentiallyEvaluated);
+ EnterExpressionEvaluationContext EEEC(getSema(),
+ Sema::PotentiallyEvaluated);
ExprResult NewExprInitResult = getDerived().TransformInitializer(
C->getCapturedVar()->getInit(),
C->getCapturedVar()->getInitStyle() == VarDecl::CallInit);
-
+
if (NewExprInitResult.isInvalid())
return ExprError();
Expr *NewExprInit = NewExprInitResult.get();
-
+
VarDecl *OldVD = C->getCapturedVar();
- QualType NewInitCaptureType =
- getSema().performLambdaInitCaptureInitialization(C->getLocation(),
- OldVD->getType()->isReferenceType(), OldVD->getIdentifier(),
+ QualType NewInitCaptureType =
+ getSema().performLambdaInitCaptureInitialization(C->getLocation(),
+ OldVD->getType()->isReferenceType(), OldVD->getIdentifier(),
NewExprInit);
NewExprInitResult = NewExprInit;
InitCaptureExprsAndTypes[C - E->capture_begin()] =
std::make_pair(NewExprInitResult, NewInitCaptureType);
-
}
LambdaScopeInfo *LSI = getSema().PushLambdaScope();
+ Sema::FunctionScopeRAII FuncScopeCleanup(getSema());
+
// Transform the template parameters, and add them to the current
// instantiation scope. The null case is handled correctly.
LSI->GLTemplateParameterList = getDerived().TransformTemplateParameterList(
E->getTemplateParameterList());
- // Check to see if the TypeSourceInfo of the call operator needs to
- // be transformed, and if so do the transformation in the
- // CurrentInstantiationScope.
-
- TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
- FunctionProtoTypeLoc OldCallOpFPTL =
- OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
+ // Transform the type of the original lambda's call operator.
+ // The transformation MUST be done in the CurrentInstantiationScope since
+ // it introduces a mapping of the original to the newly created
+ // transformed parameters.
TypeSourceInfo *NewCallOpTSI = nullptr;
-
- const bool CallOpWasAlreadyTransformed =
- getDerived().AlreadyTransformed(OldCallOpTSI->getType());
-
- // Use the Old Call Operator's TypeSourceInfo if it is already transformed.
- if (CallOpWasAlreadyTransformed)
- NewCallOpTSI = OldCallOpTSI;
- else {
- // Transform the TypeSourceInfo of the Original Lambda's Call Operator.
- // The transformation MUST be done in the CurrentInstantiationScope since
- // it introduces a mapping of the original to the newly created
- // transformed parameters.
+ {
+ TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
+ FunctionProtoTypeLoc OldCallOpFPTL =
+ OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
TypeLocBuilder NewCallOpTLBuilder;
- QualType NewCallOpType = TransformFunctionProtoType(NewCallOpTLBuilder,
- OldCallOpFPTL,
- nullptr, 0);
+ SmallVector<QualType, 4> ExceptionStorage;
+ TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
+ QualType NewCallOpType = TransformFunctionProtoType(
+ NewCallOpTLBuilder, OldCallOpFPTL, nullptr, 0,
+ [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
+ return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,
+ ExceptionStorage, Changed);
+ });
+ if (NewCallOpType.isNull())
+ return ExprError();
NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
NewCallOpType);
}
- // Extract the ParmVarDecls from the NewCallOpTSI and add them to
- // the vector below - this will be used to synthesize the
- // NewCallOperator. Additionally, add the parameters of the untransformed
- // lambda call operator to the CurrentInstantiationScope.
- SmallVector<ParmVarDecl *, 4> Params;
- {
- FunctionProtoTypeLoc NewCallOpFPTL =
- NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
- ParmVarDecl **NewParamDeclArray = NewCallOpFPTL.getParmArray();
- const unsigned NewNumArgs = NewCallOpFPTL.getNumParams();
-
- for (unsigned I = 0; I < NewNumArgs; ++I) {
- // If this call operator's type does not require transformation,
- // the parameters do not get added to the current instantiation scope,
- // - so ADD them! This allows the following to compile when the enclosing
- // template is specialized and the entire lambda expression has to be
- // transformed.
- // template<class T> void foo(T t) {
- // auto L = [](auto a) {
- // auto M = [](char b) { <-- note: non-generic lambda
- // auto N = [](auto c) {
- // int x = sizeof(a);
- // x = sizeof(b); <-- specifically this line
- // x = sizeof(c);
- // };
- // };
- // };
- // }
- // foo('a')
- if (CallOpWasAlreadyTransformed)
- getDerived().transformedLocalDecl(NewParamDeclArray[I],
- NewParamDeclArray[I]);
- // Add to Params array, so these parameters can be used to create
- // the newly transformed call operator.
- Params.push_back(NewParamDeclArray[I]);
- }
- }
-
- if (!NewCallOpTSI)
- return ExprError();
// Create the local class that will describe the lambda.
CXXRecordDecl *Class
@@ -8900,19 +9159,21 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
NewCallOpTSI,
/*KnownDependent=*/false,
E->getCaptureDefault());
-
getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
// Build the call operator.
- CXXMethodDecl *NewCallOperator
- = getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
- NewCallOpTSI,
- E->getCallOperator()->getLocEnd(),
- Params);
+ CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition(
+ Class, E->getIntroducerRange(), NewCallOpTSI,
+ E->getCallOperator()->getLocEnd(),
+ NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams());
LSI->CallOperator = NewCallOperator;
getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
+ // TransformLambdaScope will manage the function scope, so we can disable the
+ // cleanup.
+ FuncScopeCleanup.disable();
+
return getDerived().TransformLambdaScope(E, NewCallOperator,
InitCaptureExprsAndTypes);
}
@@ -8954,6 +9215,10 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
getSema().CheckCXXThisCapture(C->getLocation(), C->isExplicit());
continue;
}
+ // Captured expression will be recaptured during captured variables
+ // rebuilding.
+ if (C->capturesVLAType())
+ continue;
// Rebuild init-captures, including the implied field declaration.
if (C->isInitCapture()) {
@@ -9033,7 +9298,7 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
VarDecl *CapturedVar
= cast_or_null<VarDecl>(getDerived().TransformDecl(C->getLocation(),
C->getCapturedVar()));
- if (!CapturedVar) {
+ if (!CapturedVar || CapturedVar->isInvalidDecl()) {
Invalid = true;
continue;
}
@@ -9398,6 +9663,128 @@ TreeTransform<Derived>::TransformMaterializeTemporaryExpr(
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
+ Expr *Pattern = E->getPattern();
+
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
+ assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
+
+ // Determine whether the set of unexpanded parameter packs can and should
+ // be expanded.
+ bool Expand = true;
+ bool RetainExpansion = false;
+ Optional<unsigned> NumExpansions;
+ if (getDerived().TryExpandParameterPacks(E->getEllipsisLoc(),
+ Pattern->getSourceRange(),
+ Unexpanded,
+ Expand, RetainExpansion,
+ NumExpansions))
+ return true;
+
+ if (!Expand) {
+ // Do not expand any packs here, just transform and rebuild a fold
+ // expression.
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+
+ ExprResult LHS =
+ E->getLHS() ? getDerived().TransformExpr(E->getLHS()) : ExprResult();
+ if (LHS.isInvalid())
+ return true;
+
+ ExprResult RHS =
+ E->getRHS() ? getDerived().TransformExpr(E->getRHS()) : ExprResult();
+ if (RHS.isInvalid())
+ return true;
+
+ if (!getDerived().AlwaysRebuild() &&
+ LHS.get() == E->getLHS() && RHS.get() == E->getRHS())
+ return E;
+
+ return getDerived().RebuildCXXFoldExpr(
+ E->getLocStart(), LHS.get(), E->getOperator(), E->getEllipsisLoc(),
+ RHS.get(), E->getLocEnd());
+ }
+
+ // The transform has determined that we should perform an elementwise
+ // expansion of the pattern. Do so.
+ ExprResult Result = getDerived().TransformExpr(E->getInit());
+ if (Result.isInvalid())
+ return true;
+ bool LeftFold = E->isLeftFold();
+
+ // If we're retaining an expansion for a right fold, it is the innermost
+ // component and takes the init (if any).
+ if (!LeftFold && RetainExpansion) {
+ ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+
+ ExprResult Out = getDerived().TransformExpr(Pattern);
+ if (Out.isInvalid())
+ return true;
+
+ Result = getDerived().RebuildCXXFoldExpr(
+ E->getLocStart(), Out.get(), E->getOperator(), E->getEllipsisLoc(),
+ Result.get(), E->getLocEnd());
+ if (Result.isInvalid())
+ return true;
+ }
+
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(
+ getSema(), LeftFold ? I : *NumExpansions - I - 1);
+ ExprResult Out = getDerived().TransformExpr(Pattern);
+ if (Out.isInvalid())
+ return true;
+
+ if (Out.get()->containsUnexpandedParameterPack()) {
+ // We still have a pack; retain a pack expansion for this slice.
+ Result = getDerived().RebuildCXXFoldExpr(
+ E->getLocStart(),
+ LeftFold ? Result.get() : Out.get(),
+ E->getOperator(), E->getEllipsisLoc(),
+ LeftFold ? Out.get() : Result.get(),
+ E->getLocEnd());
+ } else if (Result.isUsable()) {
+ // We've got down to a single element; build a binary operator.
+ Result = getDerived().RebuildBinaryOperator(
+ E->getEllipsisLoc(), E->getOperator(),
+ LeftFold ? Result.get() : Out.get(),
+ LeftFold ? Out.get() : Result.get());
+ } else
+ Result = Out;
+
+ if (Result.isInvalid())
+ return true;
+ }
+
+ // If we're retaining an expansion for a left fold, it is the outermost
+ // component and takes the complete expansion so far as its init (if any).
+ if (LeftFold && RetainExpansion) {
+ ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+
+ ExprResult Out = getDerived().TransformExpr(Pattern);
+ if (Out.isInvalid())
+ return true;
+
+ Result = getDerived().RebuildCXXFoldExpr(
+ E->getLocStart(), Result.get(),
+ E->getOperator(), E->getEllipsisLoc(),
+ Out.get(), E->getLocEnd());
+ if (Result.isInvalid())
+ return true;
+ }
+
+ // If we had no init and an empty pack, and we're not retaining an expansion,
+ // then produce a fallback value or error.
+ if (Result.isUnset())
+ return getDerived().RebuildEmptyCXXFoldExpr(E->getEllipsisLoc(),
+ E->getOperator());
+
+ return Result;
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformCXXStdInitializerListExpr(
CXXStdInitializerListExpr *E) {
return getDerived().TransformExpr(E->getSubExpr());
@@ -10292,7 +10679,7 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
SourceLocation RBrace;
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee)) {
- DeclarationNameLoc &NameLoc = DRE->getNameInfo().getInfo();
+ DeclarationNameLoc NameLoc = DRE->getNameInfo().getInfo();
LBrace = SourceLocation::getFromRawEncoding(
NameLoc.CXXOperatorName.BeginOpNameLoc);
RBrace = SourceLocation::getFromRawEncoding(
@@ -10348,9 +10735,16 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
// The scope type is now known to be a valid nested name specifier
// component. Tack it on to the end of the nested name specifier.
- if (ScopeType)
- SS.Extend(SemaRef.Context, SourceLocation(),
- ScopeType->getTypeLoc(), CCLoc);
+ if (ScopeType) {
+ if (!ScopeType->getType()->getAs<TagType>()) {
+ getSema().Diag(ScopeType->getTypeLoc().getBeginLoc(),
+ diag::err_expected_class_or_namespace)
+ << ScopeType->getType() << getSema().getLangOpts().CPlusPlus;
+ return ExprError();
+ }
+ SS.Extend(SemaRef.Context, SourceLocation(), ScopeType->getTypeLoc(),
+ CCLoc);
+ }
SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
return getSema().BuildMemberReferenceExpr(Base, BaseType,
@@ -10397,4 +10791,4 @@ TreeTransform<Derived>::TransformCapturedStmt(CapturedStmt *S) {
} // end namespace clang
-#endif // LLVM_CLANG_SEMA_TREETRANSFORM_H
+#endif
diff --git a/lib/Sema/TypeLocBuilder.h b/lib/Sema/TypeLocBuilder.h
index c3f874e1a854..82844b391467 100644
--- a/lib/Sema/TypeLocBuilder.h
+++ b/lib/Sema/TypeLocBuilder.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H
-#define LLVM_CLANG_SEMA_TYPELOCBUILDER_H
+#ifndef LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H
+#define LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/TypeLoc.h"